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

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: Cleanup 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 bool retries_enabled)
61 : error_reporter_(std::move(error_reporter)), 67 : error_reporter_(std::move(error_reporter)),
62 retry_list_(std::move(retry_list)), 68 retry_list_(std::move(retry_list)),
63 test_clock_(clock), 69 clock_(clock),
64 report_ttl_(report_ttl), 70 report_ttl_(report_ttl),
71 retries_enabled_(retries_enabled),
65 current_report_id_(0), 72 current_report_id_(0),
66 weak_factory_(this) {} 73 weak_factory_(this) {}
67 74
68 CertificateReportingService::Reporter::~Reporter() {} 75 CertificateReportingService::Reporter::~Reporter() {}
69 76
70 void CertificateReportingService::Reporter::Send( 77 void CertificateReportingService::Reporter::Send(
71 const std::string& serialized_report) { 78 const std::string& serialized_report) {
72 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 79 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
73 base::Time now = 80 SendInternal(Report(current_report_id_++, clock_->Now(), serialized_report));
74 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime();
75 SendInternal(Report(current_report_id_++, now, serialized_report));
76 } 81 }
77 82
78 void CertificateReportingService::Reporter::SendPending() { 83 void CertificateReportingService::Reporter::SendPending() {
79 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 84 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
80 base::Time now = 85 if (!retries_enabled_) {
81 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime(); 86 return;
87 }
88 const base::Time now = clock_->Now();
82 // Copy pending reports and clear the retry list. 89 // Copy pending reports and clear the retry list.
83 std::vector<Report> items = retry_list_->items(); 90 std::vector<Report> items = retry_list_->items();
84 retry_list_->Clear(); 91 retry_list_->Clear();
85 for (const Report& report : items) { 92 for (const Report& report : items) {
86 if (report.creation_time < now - report_ttl_) { 93 if (report.creation_time < now - report_ttl_) {
87 // Report too old, ignore. 94 // Report too old, ignore.
88 continue; 95 continue;
89 } 96 }
90 SendInternal(report); 97 SendInternal(report);
91 } 98 }
(...skipping 19 matching lines...) Expand all
111 base::Bind(&CertificateReportingService::Reporter::SuccessCallback, 118 base::Bind(&CertificateReportingService::Reporter::SuccessCallback,
112 weak_factory_.GetWeakPtr(), report.report_id), 119 weak_factory_.GetWeakPtr(), report.report_id),
113 base::Bind(&CertificateReportingService::Reporter::ErrorCallback, 120 base::Bind(&CertificateReportingService::Reporter::ErrorCallback,
114 weak_factory_.GetWeakPtr(), report.report_id)); 121 weak_factory_.GetWeakPtr(), report.report_id));
115 } 122 }
116 123
117 void CertificateReportingService::Reporter::ErrorCallback(int report_id, 124 void CertificateReportingService::Reporter::ErrorCallback(int report_id,
118 const GURL& url, 125 const GURL& url,
119 int error) { 126 int error) {
120 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 127 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
121 auto it = inflight_reports_.find(report_id); 128 if (retries_enabled_) {
122 DCHECK(it != inflight_reports_.end()); 129 auto it = inflight_reports_.find(report_id);
123 retry_list_->Add(it->second); 130 DCHECK(it != inflight_reports_.end());
131 retry_list_->Add(it->second);
132 }
124 CHECK_GT(inflight_reports_.erase(report_id), 0u); 133 CHECK_GT(inflight_reports_.erase(report_id), 0u);
125 } 134 }
126 135
127 void CertificateReportingService::Reporter::SuccessCallback(int report_id) { 136 void CertificateReportingService::Reporter::SuccessCallback(int report_id) {
128 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 137 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
129 CHECK_GT(inflight_reports_.erase(report_id), 0u); 138 CHECK_GT(inflight_reports_.erase(report_id), 0u);
130 } 139 }
140
141 CertificateReportingService::CertificateReportingService(
142 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
143 uint8_t server_public_key[/* 32 */],
144 uint32_t server_public_key_version,
145 size_t max_queued_report_count,
146 base::TimeDelta max_report_age,
147 std::unique_ptr<base::Clock> clock)
148 : enabled_(true),
149 url_request_context_(nullptr),
150 max_queued_report_count_(max_queued_report_count),
151 max_report_age_(max_report_age),
152 clock_(std::move(clock)),
153 made_send_attempt_(false),
154 server_public_key_(server_public_key),
155 server_public_key_version_(server_public_key_version) {
156 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
157 content::BrowserThread::PostTask(
158 content::BrowserThread::IO, FROM_HERE,
159 base::Bind(&CertificateReportingService::InitializeOnIOThread,
160 base::Unretained(this), enabled_, url_request_context_getter,
estark 2016/12/07 00:42:55 Are we sure it's safe to pass this as Unretained?
meacer 2016/12/07 21:37:33 CertificateReportingService is only destructed dur
161 max_queued_report_count_, max_report_age_, clock_.get(),
162 server_public_key_, server_public_key_version_));
163 }
164
165 CertificateReportingService::~CertificateReportingService() {
166 DCHECK(!reporter_);
167 }
168
169 void CertificateReportingService::Shutdown() {
170 // Shutdown will be called twice: Once after SafeBrowsing shuts down, and once
171 // when all KeyedServices shut down. All calls after the first one are no-op.
172 enabled_ = false;
173 Reset();
174 }
175
176 void CertificateReportingService::Send(const std::string& serialized_report) {
177 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
178 made_send_attempt_ = true;
179 if (!reporter_) {
180 return;
181 }
182 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
estark 2016/12/07 00:42:55 redundant with line 177
meacer 2016/12/07 21:37:33 Done.
183 content::BrowserThread::PostTask(
184 content::BrowserThread::IO, FROM_HERE,
185 base::Bind(&CertificateReportingService::Reporter::Send,
186 base::Unretained(reporter_.get()), serialized_report));
187 }
188
189 void CertificateReportingService::SendPending() {
190 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
191 made_send_attempt_ = true;
192 if (!reporter_) {
193 return;
194 }
195 content::BrowserThread::PostTask(
196 content::BrowserThread::IO, FROM_HERE,
197 base::Bind(&CertificateReportingService::Reporter::SendPending,
198 base::Unretained(reporter_.get())));
199 }
200
201 void CertificateReportingService::InitializeOnIOThread(
202 bool enabled,
203 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
204 size_t max_queued_report_count,
205 base::TimeDelta max_report_age,
206 base::Clock* clock,
207 uint8_t* server_public_key,
208 uint32_t server_public_key_version) {
209 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
210 DCHECK(!url_request_context_);
211 url_request_context_ = url_request_context_getter->GetURLRequestContext();
212 ResetOnIOThread(enabled, url_request_context_, max_queued_report_count,
213 max_report_age, clock, server_public_key,
214 server_public_key_version);
215 }
216
217 void CertificateReportingService::SetEnabled(bool enabled) {
218 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
219 enabled_ = enabled;
220 Reset();
221 }
222
223 CertificateReportingService::Reporter*
224 CertificateReportingService::get_reporter_for_testing() const {
225 return reporter_.get();
226 }
227
228 void CertificateReportingService::SetMaxQueuedReportCountForTesting(
229 size_t count) {
230 DCHECK(!made_send_attempt_);
231 max_queued_report_count_ = count;
232 Reset();
233 }
234
235 void CertificateReportingService::SetClockForTesting(
236 std::unique_ptr<base::Clock> clock) {
237 DCHECK(!made_send_attempt_);
238 clock_ = std::move(clock);
239 Reset();
240 }
241
242 void CertificateReportingService::SetMaxReportAgeForTesting(
243 base::TimeDelta max_report_age) {
244 DCHECK(!made_send_attempt_);
245 max_report_age_ = max_report_age;
246 Reset();
247 }
248
249 void CertificateReportingService::Reset() {
250 content::BrowserThread::PostTask(
251 content::BrowserThread::IO, FROM_HERE,
252 base::Bind(&CertificateReportingService::ResetOnIOThread,
253 base::Unretained(this), enabled_, url_request_context_,
254 max_queued_report_count_, max_report_age_, clock_.get(),
255 server_public_key_, server_public_key_version_));
256 }
257
258 void CertificateReportingService::ResetOnIOThread(
259 bool enabled,
260 net::URLRequestContext* url_request_context,
261 size_t max_queued_report_count,
262 base::TimeDelta max_report_age,
263 base::Clock* clock,
264 uint8_t* const server_public_key,
265 uint32_t server_public_key_version) {
266 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
267 // url_request_context_ is null during shutdown.
268 if (!enabled || !url_request_context) {
269 reporter_.reset(nullptr);
270 return;
271 }
272 std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter;
273 if (server_public_key) {
274 // Only used in tests.
275 std::unique_ptr<net::ReportSender> report_sender(new net::ReportSender(
276 url_request_context, net::ReportSender::DO_NOT_SEND_COOKIES));
277 error_reporter.reset(new certificate_reporting::ErrorReporter(
278 GURL(kExtendedReportingUploadUrlInsecure), server_public_key,
279 server_public_key_version, std::move(report_sender)));
280 } else {
281 error_reporter.reset(new certificate_reporting::ErrorReporter(
282 url_request_context, GURL(kExtendedReportingUploadUrlInsecure),
283 net::ReportSender::DO_NOT_SEND_COOKIES));
284 }
285
286 reporter_.reset(
287 new Reporter(std::move(error_reporter),
288 std::unique_ptr<BoundedReportList>(
289 new BoundedReportList(max_queued_report_count)),
290 clock, max_report_age, true /* retries_enabled */));
291 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698