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

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: estark comments 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 {
12
13 // URL to upload invalid certificate chain reports. An HTTP URL is used because
14 // a client seeing an invalid cert might not be able to make an HTTPS connection
15 // to report it.
16 const char kExtendedReportingUploadUrl[] =
17 "http://safebrowsing.googleusercontent.com/safebrowsing/clientreport/";
18
11 // Compare function that orders Reports in reverse chronological order (i.e. 19 // Compare function that orders Reports in reverse chronological order (i.e.
12 // oldest item is last). 20 // oldest item is last).
13 bool ReportCompareFunc(const CertificateReportingService::Report& item1, 21 bool ReportCompareFunc(const CertificateReportingService::Report& item1,
14 const CertificateReportingService::Report& item2) { 22 const CertificateReportingService::Report& item2) {
15 return item1.creation_time > item2.creation_time; 23 return item1.creation_time > item2.creation_time;
16 } 24 }
17 25
18 } // namespace 26 } // namespace
19 27
20 CertificateReportingService::BoundedReportList::BoundedReportList( 28 CertificateReportingService::BoundedReportList::BoundedReportList(
(...skipping 29 matching lines...) Expand all
50 const std::vector<CertificateReportingService::Report>& 58 const std::vector<CertificateReportingService::Report>&
51 CertificateReportingService::BoundedReportList::items() const { 59 CertificateReportingService::BoundedReportList::items() const {
52 DCHECK(thread_checker_.CalledOnValidThread()); 60 DCHECK(thread_checker_.CalledOnValidThread());
53 return items_; 61 return items_;
54 } 62 }
55 63
56 CertificateReportingService::Reporter::Reporter( 64 CertificateReportingService::Reporter::Reporter(
57 std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter, 65 std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter,
58 std::unique_ptr<BoundedReportList> retry_list, 66 std::unique_ptr<BoundedReportList> retry_list,
59 base::Clock* clock, 67 base::Clock* clock,
60 base::TimeDelta report_ttl) 68 base::TimeDelta report_ttl,
69 bool retries_enabled)
61 : error_reporter_(std::move(error_reporter)), 70 : error_reporter_(std::move(error_reporter)),
62 retry_list_(std::move(retry_list)), 71 retry_list_(std::move(retry_list)),
63 test_clock_(clock), 72 clock_(clock),
64 report_ttl_(report_ttl), 73 report_ttl_(report_ttl),
74 retries_enabled_(retries_enabled),
65 current_report_id_(0), 75 current_report_id_(0),
66 weak_factory_(this) {} 76 weak_factory_(this) {}
67 77
68 CertificateReportingService::Reporter::~Reporter() {} 78 CertificateReportingService::Reporter::~Reporter() {}
69 79
70 void CertificateReportingService::Reporter::Send( 80 void CertificateReportingService::Reporter::Send(
71 const std::string& serialized_report) { 81 const std::string& serialized_report) {
72 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 82 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
73 base::Time now = 83 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 } 84 }
77 85
78 void CertificateReportingService::Reporter::SendPending() { 86 void CertificateReportingService::Reporter::SendPending() {
79 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 87 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
80 base::Time now = 88 if (!retries_enabled_) {
81 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime(); 89 return;
90 }
91 const base::Time now = clock_->Now();
82 // Copy pending reports and clear the retry list. 92 // Copy pending reports and clear the retry list.
83 std::vector<Report> items = retry_list_->items(); 93 std::vector<Report> items = retry_list_->items();
84 retry_list_->Clear(); 94 retry_list_->Clear();
85 for (const Report& report : items) { 95 for (const Report& report : items) {
86 if (report.creation_time < now - report_ttl_) { 96 if (report.creation_time < now - report_ttl_) {
87 // Report too old, ignore. 97 // Report too old, ignore.
88 continue; 98 continue;
89 } 99 }
90 SendInternal(report); 100 SendInternal(report);
91 } 101 }
(...skipping 19 matching lines...) Expand all
111 base::Bind(&CertificateReportingService::Reporter::SuccessCallback, 121 base::Bind(&CertificateReportingService::Reporter::SuccessCallback,
112 weak_factory_.GetWeakPtr(), report.report_id), 122 weak_factory_.GetWeakPtr(), report.report_id),
113 base::Bind(&CertificateReportingService::Reporter::ErrorCallback, 123 base::Bind(&CertificateReportingService::Reporter::ErrorCallback,
114 weak_factory_.GetWeakPtr(), report.report_id)); 124 weak_factory_.GetWeakPtr(), report.report_id));
115 } 125 }
116 126
117 void CertificateReportingService::Reporter::ErrorCallback(int report_id, 127 void CertificateReportingService::Reporter::ErrorCallback(int report_id,
118 const GURL& url, 128 const GURL& url,
119 int error) { 129 int error) {
120 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 130 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
121 auto it = inflight_reports_.find(report_id); 131 if (retries_enabled_) {
122 DCHECK(it != inflight_reports_.end()); 132 auto it = inflight_reports_.find(report_id);
123 retry_list_->Add(it->second); 133 DCHECK(it != inflight_reports_.end());
134 retry_list_->Add(it->second);
135 }
124 CHECK_GT(inflight_reports_.erase(report_id), 0u); 136 CHECK_GT(inflight_reports_.erase(report_id), 0u);
125 } 137 }
126 138
127 void CertificateReportingService::Reporter::SuccessCallback(int report_id) { 139 void CertificateReportingService::Reporter::SuccessCallback(int report_id) {
128 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 140 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
129 CHECK_GT(inflight_reports_.erase(report_id), 0u); 141 CHECK_GT(inflight_reports_.erase(report_id), 0u);
130 } 142 }
143
144 CertificateReportingService::CertificateReportingService(
145 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
146 uint8_t server_public_key[/* 32 */],
147 uint32_t server_public_key_version,
148 size_t max_queued_report_count,
149 base::TimeDelta max_report_age,
150 std::unique_ptr<base::Clock> clock)
151 : enabled_(true),
152 url_request_context_(nullptr),
153 max_queued_report_count_(max_queued_report_count),
154 max_report_age_(max_report_age),
155 clock_(std::move(clock)),
156 made_send_attempt_(false),
157 server_public_key_(server_public_key),
158 server_public_key_version_(server_public_key_version) {
159 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
160 content::BrowserThread::PostTask(
161 content::BrowserThread::IO, FROM_HERE,
162 base::Bind(&CertificateReportingService::InitializeOnIOThread,
163 base::Unretained(this), enabled_, url_request_context_getter,
164 max_queued_report_count_, max_report_age_, clock_.get(),
165 server_public_key_, server_public_key_version_));
166 }
167
168 CertificateReportingService::~CertificateReportingService() {
169 DCHECK(!reporter_);
170 }
171
172 void CertificateReportingService::Shutdown() {
173 // Shutdown will be called twice: Once after SafeBrowsing shuts down, and once
174 // when all KeyedServices shut down. All calls after the first one are no-op.
175 enabled_ = false;
176 Reset();
177 }
178
179 void CertificateReportingService::Send(const std::string& serialized_report) {
180 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
181 made_send_attempt_ = true;
182 if (!reporter_) {
183 return;
184 }
185 content::BrowserThread::PostTask(
186 content::BrowserThread::IO, FROM_HERE,
187 base::Bind(&CertificateReportingService::Reporter::Send,
188 base::Unretained(reporter_.get()), serialized_report));
189 }
190
191 void CertificateReportingService::SendPending() {
192 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
193 made_send_attempt_ = true;
194 if (!reporter_) {
195 return;
196 }
197 content::BrowserThread::PostTask(
198 content::BrowserThread::IO, FROM_HERE,
199 base::Bind(&CertificateReportingService::Reporter::SendPending,
200 base::Unretained(reporter_.get())));
201 }
202
203 void CertificateReportingService::InitializeOnIOThread(
204 bool enabled,
205 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
206 size_t max_queued_report_count,
207 base::TimeDelta max_report_age,
208 base::Clock* clock,
209 uint8_t* server_public_key,
210 uint32_t server_public_key_version) {
211 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
212 DCHECK(!url_request_context_);
213 url_request_context_ = url_request_context_getter->GetURLRequestContext();
214 ResetOnIOThread(enabled, url_request_context_, max_queued_report_count,
215 max_report_age, clock, server_public_key,
216 server_public_key_version);
217 }
218
219 void CertificateReportingService::SetEnabled(bool enabled) {
220 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
221 enabled_ = enabled;
222 Reset();
223 }
224
225 CertificateReportingService::Reporter*
226 CertificateReportingService::GetReporterForTesting() const {
227 return reporter_.get();
228 }
229
230 void CertificateReportingService::SetMaxQueuedReportCountForTesting(
231 size_t count) {
232 DCHECK(!made_send_attempt_);
233 max_queued_report_count_ = count;
234 Reset();
235 }
236
237 void CertificateReportingService::SetClockForTesting(
238 std::unique_ptr<base::Clock> clock) {
239 DCHECK(!made_send_attempt_);
240 clock_ = std::move(clock);
241 Reset();
242 }
243
244 void CertificateReportingService::SetMaxReportAgeForTesting(
245 base::TimeDelta max_report_age) {
246 DCHECK(!made_send_attempt_);
247 max_report_age_ = max_report_age;
248 Reset();
249 }
250
251 // static
252 GURL CertificateReportingService::GetReportingURLForTesting() {
253 return GURL(kExtendedReportingUploadUrl);
254 }
255
256 void CertificateReportingService::Reset() {
257 content::BrowserThread::PostTask(
258 content::BrowserThread::IO, FROM_HERE,
259 base::Bind(&CertificateReportingService::ResetOnIOThread,
260 base::Unretained(this), enabled_, url_request_context_,
261 max_queued_report_count_, max_report_age_, clock_.get(),
262 server_public_key_, server_public_key_version_));
263 }
264
265 void CertificateReportingService::ResetOnIOThread(
266 bool enabled,
267 net::URLRequestContext* url_request_context,
268 size_t max_queued_report_count,
269 base::TimeDelta max_report_age,
270 base::Clock* clock,
271 uint8_t* const server_public_key,
272 uint32_t server_public_key_version) {
273 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
274 // url_request_context_ is null during shutdown.
275 if (!enabled || !url_request_context) {
276 reporter_.reset(nullptr);
277 return;
278 }
279 std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter;
280 if (server_public_key) {
281 // Only used in tests.
282 std::unique_ptr<net::ReportSender> report_sender(new net::ReportSender(
283 url_request_context, net::ReportSender::DO_NOT_SEND_COOKIES));
284 error_reporter.reset(new certificate_reporting::ErrorReporter(
285 GURL(kExtendedReportingUploadUrl), server_public_key,
286 server_public_key_version, std::move(report_sender)));
287 } else {
288 error_reporter.reset(new certificate_reporting::ErrorReporter(
289 url_request_context, GURL(kExtendedReportingUploadUrl),
290 net::ReportSender::DO_NOT_SEND_COOKIES));
291 }
292
293 reporter_.reset(
294 new Reporter(std::move(error_reporter),
295 std::unique_ptr<BoundedReportList>(
296 new BoundedReportList(max_queued_report_count)),
297 clock, max_report_age, true /* retries_enabled */));
298 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698