forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfeedback_uploader.h
180 lines (137 loc) · 6.4 KB
/
feedback_uploader.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_
#define COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_
#include <list>
#include <queue>
#include <vector>
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"
namespace network {
struct ResourceRequest;
class SimpleURLLoader;
} // namespace network
namespace feedback {
class FeedbackReport;
// FeedbackUploader is used to add a feedback report to the queue of reports
// being uploaded. In case uploading a report fails, it is written to disk and
// tried again when it's turn comes up next in the queue.
class FeedbackUploader : public KeyedService,
public base::SupportsWeakPtr<FeedbackUploader> {
public:
// Some embedders want to delay the creation of the SharedURLLoaderFactory
// until it is required as the creation could be expensive. In that case,
// they can pass a callback that will be used to initialise the instance
// out of the object creation code path.
using SharedURLLoaderFactoryGetter =
base::OnceCallback<scoped_refptr<network::SharedURLLoaderFactory>()>;
FeedbackUploader(
bool is_off_the_record,
const base::FilePath& state_path,
SharedURLLoaderFactoryGetter shared_url_loader_factory_getter);
FeedbackUploader(
bool is_off_the_record,
const base::FilePath& state_path,
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
FeedbackUploader(const FeedbackUploader&) = delete;
FeedbackUploader& operator=(const FeedbackUploader&) = delete;
~FeedbackUploader() override;
static void SetMinimumRetryDelayForTesting(base::TimeDelta delay);
// Queues a report for uploading.
// |data|: The serialized userfeedback::ExtensionSubmit proto to send.
// |has_email|: True iff the user included their email address in the report.
// virtual for testing.
virtual void QueueReport(std::unique_ptr<std::string> data, bool has_email);
// Re-queues an existing report from disk for uploading.
void RequeueReport(scoped_refptr<FeedbackReport> report);
bool QueueEmpty() const { return reports_queue_.empty(); }
const base::FilePath& feedback_reports_path() const {
return feedback_reports_path_;
}
scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
return task_runner_;
}
base::TimeDelta retry_delay() const { return retry_delay_; }
protected:
// Virtual to give implementers a chance to do work before the report is
// disptached. Implementers can then call
// FeedbackUploader::StartSendingReport() when ready so that the report is
// dispatched.
virtual void StartDispatchingReport();
// Invoked when a feedback report upload succeeds. It will reset the
// |retry_delay_| to its minimum value and schedules the next report upload if
// any.
void OnReportUploadSuccess();
// Invoked when |report_being_dispatched_| fails to upload. If |should_retry|
// is true, it will double the |retry_delay_| and reenqueue
// |report_being_dispatched_| with the new delay. All subsequent retries will
// keep increasing the delay until a successful upload is encountered.
void OnReportUploadFailure(bool should_retry);
const scoped_refptr<FeedbackReport>& report_being_dispatched() const {
return report_being_dispatched_;
}
private:
friend class FeedbackUploaderTest;
// This is a std::list so that iterators remain valid during modifications.
using UrlLoaderList = std::list<std::unique_ptr<network::SimpleURLLoader>>;
struct ReportsUploadTimeComparator {
bool operator()(const scoped_refptr<FeedbackReport>& a,
const scoped_refptr<FeedbackReport>& b) const;
};
// Internal constructor. Exactly one of |url_loader_factory_getter| and
// |url_loader_factory| can be non-null.
FeedbackUploader(
bool is_off_the_record,
const base::FilePath& state_path,
SharedURLLoaderFactoryGetter url_loader_factory_getter,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
// Called from DispatchReport() to give implementers a chance to add extra
// headers to the upload request before it's sent.
virtual void AppendExtraHeadersToUploadRequest(
network::ResourceRequest* resource_request);
// Uploads the |report_being_dispatched_| to be uploaded. It must
// call either OnReportUploadSuccess() or OnReportUploadFailure() so that
// dispatching reports can progress.
void DispatchReport();
void OnDispatchComplete(UrlLoaderList::iterator it,
std::unique_ptr<std::string> response_body);
// Update our timer for uploading the next report.
void UpdateUploadTimer();
// Callback used to initialise |url_loader_factory_| lazily.
SharedURLLoaderFactoryGetter url_loader_factory_getter_;
// URLLoaderFactory used for network requests. May be null initially if the
// creation is delayed (see |url_loader_factory_getter_|).
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
const base::FilePath feedback_reports_path_;
// Timer to upload the next report at.
base::OneShotTimer upload_timer_;
// See comment of |FeedbackUploaderFactory::task_runner_|.
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
scoped_refptr<FeedbackReport> report_being_dispatched_;
const GURL feedback_post_url_;
// Priority queue of reports prioritized by the time the report is supposed
// to be uploaded at.
std::priority_queue<scoped_refptr<FeedbackReport>,
std::vector<scoped_refptr<FeedbackReport>>,
ReportsUploadTimeComparator>
reports_queue_;
base::TimeDelta retry_delay_;
// True when a report is currently being dispatched. Only a single report
// at-a-time should be dispatched.
bool is_dispatching_ = false;
// Whether the feedback is associated with off-the-record context.
const bool is_off_the_record_ = false;
UrlLoaderList uploads_in_progress_;
};
} // namespace feedback
#endif // COMPONENTS_FEEDBACK_FEEDBACK_UPLOADER_H_