Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(735)

Side by Side Diff: chrome/browser/safe_browsing/certificate_reporting_service.cc

Issue 2543523002: Implement main CertificateReportingService code and add unit tests. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/bind_helpers.h"
5 #include "base/time/clock.h" 6 #include "base/time/clock.h"
6 #include "base/time/default_clock.h" 7 #include "base/time/default_clock.h"
7 #include "chrome/browser/safe_browsing/certificate_reporting_service.h" 8 #include "chrome/browser/safe_browsing/certificate_reporting_service.h"
8 #include "content/public/browser/browser_thread.h" 9 #include "content/public/browser/browser_thread.h"
9 10
10 namespace { 11 namespace {
11 // Compare function that orders Reports in reverse chronological order (i.e. 12 // Compare function that orders Reports in reverse chronological order (i.e.
12 // oldest item is last). 13 // oldest item is last).
13 bool ReportCompareFunc(const CertificateReportingService::Report& item1, 14 bool ReportCompareFunc(const CertificateReportingService::Report& item1,
14 const CertificateReportingService::Report& item2) { 15 const CertificateReportingService::Report& item2) {
15 return item1.creation_time > item2.creation_time; 16 return item1.creation_time > item2.creation_time;
16 } 17 }
17 18
18 } // namespace 19 } // namespace
19 20
21 // static
22 const char CertificateReportingService::kExtendedReportingUploadUrlInsecure[] =
23 "http://safebrowsing.googleusercontent.com/safebrowsing/clientreport/";
24
20 CertificateReportingService::BoundedReportList::BoundedReportList( 25 CertificateReportingService::BoundedReportList::BoundedReportList(
21 size_t max_size) 26 size_t max_size)
22 : max_size_(max_size) { 27 : max_size_(max_size) {
23 CHECK(max_size <= 20) 28 CHECK(max_size <= 20)
24 << "Current implementation is not efficient for a large list."; 29 << "Current implementation is not efficient for a large list.";
25 DCHECK(thread_checker_.CalledOnValidThread()); 30 DCHECK(thread_checker_.CalledOnValidThread());
26 } 31 }
27 32
28 CertificateReportingService::BoundedReportList::~BoundedReportList() {} 33 CertificateReportingService::BoundedReportList::~BoundedReportList() {}
29 34
(...skipping 20 matching lines...) Expand all
50 const std::vector<CertificateReportingService::Report>& 55 const std::vector<CertificateReportingService::Report>&
51 CertificateReportingService::BoundedReportList::items() const { 56 CertificateReportingService::BoundedReportList::items() const {
52 DCHECK(thread_checker_.CalledOnValidThread()); 57 DCHECK(thread_checker_.CalledOnValidThread());
53 return items_; 58 return items_;
54 } 59 }
55 60
56 CertificateReportingService::Reporter::Reporter( 61 CertificateReportingService::Reporter::Reporter(
57 std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter, 62 std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter,
58 std::unique_ptr<BoundedReportList> retry_list, 63 std::unique_ptr<BoundedReportList> retry_list,
59 base::Clock* clock, 64 base::Clock* clock,
60 base::TimeDelta report_ttl) 65 base::TimeDelta report_ttl,
66 EventObserver* event_observer,
67 bool retries_enabled)
61 : error_reporter_(std::move(error_reporter)), 68 : error_reporter_(std::move(error_reporter)),
62 retry_list_(std::move(retry_list)), 69 retry_list_(std::move(retry_list)),
63 test_clock_(clock), 70 test_clock_(clock),
64 report_ttl_(report_ttl), 71 report_ttl_(report_ttl),
72 event_observer_(event_observer),
73 retries_enabled_(retries_enabled),
65 current_report_id_(0), 74 current_report_id_(0),
66 weak_factory_(this) {} 75 weak_factory_(this) {}
67 76
68 CertificateReportingService::Reporter::~Reporter() {} 77 CertificateReportingService::Reporter::~Reporter() {}
69 78
70 void CertificateReportingService::Reporter::Send( 79 void CertificateReportingService::Reporter::Send(
71 const std::string& serialized_report) { 80 const std::string& serialized_report) {
72 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 81 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
73 base::Time now = 82 base::Time now =
74 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime(); 83 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime();
75 SendInternal(Report(current_report_id_++, now, serialized_report)); 84 SendInternal(Report(current_report_id_++, now, serialized_report));
76 } 85 }
77 86
78 void CertificateReportingService::Reporter::SendPending() { 87 void CertificateReportingService::Reporter::SendPending() {
79 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 88 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
89 if (!retries_enabled_) {
90 return;
91 }
80 base::Time now = 92 base::Time now =
81 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime(); 93 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime();
82 // Copy pending reports and clear the retry list. 94 // Copy pending reports and clear the retry list.
83 std::vector<Report> items = retry_list_->items(); 95 std::vector<Report> items = retry_list_->items();
84 retry_list_->Clear(); 96 retry_list_->Clear();
85 for (const Report& report : items) { 97 for (const Report& report : items) {
86 if (report.creation_time < now - report_ttl_) { 98 if (report.creation_time < now - report_ttl_) {
87 // Report too old, ignore. 99 // Report too old, ignore.
88 continue; 100 continue;
89 } 101 }
90 SendInternal(report); 102 SendInternal(report);
91 } 103 }
92 } 104 }
93 105
94 size_t 106 size_t
95 CertificateReportingService::Reporter::inflight_report_count_for_testing() 107 CertificateReportingService::Reporter::inflight_report_count_for_testing()
96 const { 108 const {
97 return inflight_reports_.size(); 109 return inflight_reports_.size();
98 } 110 }
99 111
100 CertificateReportingService::BoundedReportList* 112 CertificateReportingService::BoundedReportList*
101 CertificateReportingService::Reporter::GetQueueForTesting() const { 113 CertificateReportingService::Reporter::GetQueueForTesting() const {
102 return retry_list_.get(); 114 return retry_list_.get();
103 } 115 }
104 116
117 void CertificateReportingService::Reporter::SetEventObserverForTesting(
118 EventObserver* observer) {
119 event_observer_ = observer;
120 }
121
105 void CertificateReportingService::Reporter::SendInternal( 122 void CertificateReportingService::Reporter::SendInternal(
106 const CertificateReportingService::Report& report) { 123 const CertificateReportingService::Report& report) {
107 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 124 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
108 inflight_reports_.insert(std::make_pair(report.report_id, report)); 125 inflight_reports_.insert(std::make_pair(report.report_id, report));
109 error_reporter_->SendExtendedReportingReport( 126 error_reporter_->SendExtendedReportingReport(
110 report.serialized_report, 127 report.serialized_report,
111 base::Bind(&CertificateReportingService::Reporter::SuccessCallback, 128 base::Bind(&CertificateReportingService::Reporter::SuccessCallback,
112 weak_factory_.GetWeakPtr(), report.report_id), 129 weak_factory_.GetWeakPtr(), report.report_id),
113 base::Bind(&CertificateReportingService::Reporter::ErrorCallback, 130 base::Bind(&CertificateReportingService::Reporter::ErrorCallback,
114 weak_factory_.GetWeakPtr(), report.report_id)); 131 weak_factory_.GetWeakPtr(), report.report_id));
115 } 132 }
116 133
117 void CertificateReportingService::Reporter::ErrorCallback(int report_id, 134 void CertificateReportingService::Reporter::ErrorCallback(int report_id,
118 const GURL& url, 135 const GURL& url,
119 int error) { 136 int error) {
120 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 137 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
121 auto it = inflight_reports_.find(report_id); 138 if (retries_enabled_) {
122 DCHECK(it != inflight_reports_.end()); 139 auto it = inflight_reports_.find(report_id);
123 retry_list_->Add(it->second); 140 DCHECK(it != inflight_reports_.end());
141 retry_list_->Add(it->second);
142 }
124 CHECK_GT(inflight_reports_.erase(report_id), 0u); 143 CHECK_GT(inflight_reports_.erase(report_id), 0u);
144 content::BrowserThread::PostTask(
145 content::BrowserThread::UI, FROM_HERE,
146 base::Bind(&CertificateReportingService::EventObserver::OnSendComplete,
147 base::Unretained(event_observer_), report_id, false));
125 } 148 }
126 149
127 void CertificateReportingService::Reporter::SuccessCallback(int report_id) { 150 void CertificateReportingService::Reporter::SuccessCallback(int report_id) {
128 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 151 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
129 CHECK_GT(inflight_reports_.erase(report_id), 0u); 152 CHECK_GT(inflight_reports_.erase(report_id), 0u);
153 content::BrowserThread::PostTask(
154 content::BrowserThread::UI, FROM_HERE,
155 base::Bind(&CertificateReportingService::EventObserver::OnSendComplete,
156 base::Unretained(event_observer_), report_id, true));
130 } 157 }
158
159 CertificateReportingService::CertificateReportingService(
160 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
161 std::unique_ptr<EventObserver> event_observer,
162 size_t max_queued_report_count,
163 base::TimeDelta max_report_age,
164 base::Clock* test_clock)
165 : enabled_(true),
166 url_request_context_(nullptr),
167 event_observer_(std::move(event_observer)),
168 max_queued_report_count_(max_queued_report_count),
169 max_report_age_(max_report_age),
170 test_clock_(test_clock),
171 made_send_attempt_(false) {
172 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
173 content::BrowserThread::PostTaskAndReply(
174 content::BrowserThread::IO, FROM_HERE,
175 base::Bind(&CertificateReportingService::InitializeOnIOThread,
176 base::Unretained(this), enabled_, url_request_context_getter,
177 max_queued_report_count_, max_report_age_, test_clock_,
178 nullptr /* error_reporter */),
Jialiu Lin 2016/11/30 22:18:06 Maybe add a TODO here to indicate that "nullptr" n
meacer 2016/11/30 23:39:40 Looks like the parameter was just wrong, it should
179 base::Bind(&EventObserver::OnReset,
180 base::Unretained(event_observer_.get())));
181 }
182
183 CertificateReportingService::~CertificateReportingService() {
184 DCHECK(!reporter_);
185 }
186
187 void CertificateReportingService::Shutdown() {
188 // Shutdown will be called twice: Once after SafeBrowsing shuts down, and once
189 // when all KeyedServices shut down. All calls after the first one is a no-op.
190 enabled_ = false;
191
192 Reset(base::Bind(&EventObserver::OnReset,
193 base::Unretained(event_observer_.get())));
194 }
195
196 void CertificateReportingService::Send(const std::string& serialized_report) {
197 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
198 made_send_attempt_ = true;
199 if (!reporter_) {
200 DidAttemptSend(false);
201 return;
202 }
203 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
204 content::BrowserThread::PostTaskAndReply(
205 content::BrowserThread::IO, FROM_HERE,
206 base::Bind(&CertificateReportingService::Reporter::Send,
207 base::Unretained(reporter_.get()), serialized_report),
208 base::Bind(&CertificateReportingService::DidAttemptSend,
209 base::Unretained(this), true));
210 }
211
212 void CertificateReportingService::SendPending() {
213 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
214 made_send_attempt_ = true;
215 if (!reporter_) {
216 DidAttemptSend(false);
217 return;
218 }
219 content::BrowserThread::PostTaskAndReply(
220 content::BrowserThread::IO, FROM_HERE,
221 base::Bind(&CertificateReportingService::Reporter::SendPending,
222 base::Unretained(reporter_.get())),
223 base::Bind(&CertificateReportingService::DidAttemptSend,
224 base::Unretained(this), true));
225 }
226
227 void CertificateReportingService::InitializeOnIOThread(
228 bool enabled,
229 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
230 size_t max_queued_report_count,
231 base::TimeDelta max_report_age,
232 base::Clock* test_clock,
233 EventObserver* event_observer) {
234 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
235 DCHECK(!url_request_context_);
236 url_request_context_ = url_request_context_getter->GetURLRequestContext();
237 ResetOnIOThread(enabled, url_request_context_, max_queued_report_count,
238 max_report_age, test_clock, event_observer);
239 }
240
241 void CertificateReportingService::DidAttemptSend(bool sent) {
242 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
243 event_observer_->OnSendAttempt(sent);
244 }
245
246 void CertificateReportingService::SetEnabled(bool enabled) {
247 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
248 enabled_ = enabled;
249 Reset(base::Bind(&EventObserver::OnReset,
250 base::Unretained(event_observer_.get())));
251 }
252
253 CertificateReportingService::Reporter*
254 CertificateReportingService::get_reporter_for_testing() const {
255 return reporter_.get();
256 }
257
258 void CertificateReportingService::SetEventObserverForTesting(
259 std::unique_ptr<CertificateReportingService::EventObserver> observer) {
260 event_observer_ = std::move(observer);
261 // reporter_ can be null if reporting is disabled.
262 if (reporter_) {
263 reporter_->SetEventObserverForTesting(event_observer_.get());
264 }
265 }
266
267 void CertificateReportingService::SetMaxQueuedReportCountForTesting(
268 size_t count) {
269 DCHECK(!made_send_attempt_);
270 max_queued_report_count_ = count;
271 Reset(base::Bind(base::DoNothing));
272 }
273
274 void CertificateReportingService::SetClockForTesting(base::Clock* clock) {
275 DCHECK(!made_send_attempt_);
276 test_clock_ = clock;
277 Reset(base::Bind(base::DoNothing));
278 }
279
280 void CertificateReportingService::SetMaxReportAgeForTesting(
281 base::TimeDelta max_report_age) {
282 DCHECK(!made_send_attempt_);
283 max_report_age_ = max_report_age;
284 Reset(base::Bind(base::DoNothing));
285 }
286
287 void CertificateReportingService::Reset(
288 const base::Callback<void()>& callback) {
289 content::BrowserThread::PostTaskAndReply(
290 content::BrowserThread::IO, FROM_HERE,
291 base::Bind(&CertificateReportingService::ResetOnIOThread,
292 base::Unretained(this), enabled_, url_request_context_,
293 max_queued_report_count_, max_report_age_, test_clock_,
294 event_observer_.get()),
295 callback);
296 }
297
298 void CertificateReportingService::ResetOnIOThread(
299 bool enabled,
300 net::URLRequestContext* url_request_context,
301 size_t max_queued_report_count,
302 base::TimeDelta max_report_age,
303 base::Clock* test_clock,
304 EventObserver* event_observer) {
305 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
306 // url_request_context_ is null during shutdown.
307 if (!enabled || !url_request_context) {
308 reporter_.reset(nullptr);
309 return;
310 }
311 reporter_.reset(new Reporter(
312 std::unique_ptr<certificate_reporting::ErrorReporter>(
313 new certificate_reporting::ErrorReporter(
314 url_request_context, GURL(kExtendedReportingUploadUrlInsecure),
315 net::ReportSender::DO_NOT_SEND_COOKIES)),
316 std::unique_ptr<BoundedReportList>(
317 new BoundedReportList(max_queued_report_count)),
318 test_clock, max_report_age, event_observer, true /* retries_enabled */));
319 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698