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

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

Issue 2503243003: Wire up CertificateReportingService to handle report uploads (Closed)
Patch Set: jialiul, 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/bind_helpers.h"
6 #include "base/metrics/histogram_macros.h"
7 #include "base/metrics/sparse_histogram.h"
6 #include "base/time/clock.h" 8 #include "base/time/clock.h"
7 #include "base/time/default_clock.h" 9 #include "chrome/browser/profiles/profile.h"
8 #include "chrome/browser/safe_browsing/certificate_reporting_service.h" 10 #include "chrome/browser/safe_browsing/certificate_reporting_service.h"
11 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
12 #include "components/prefs/pref_service.h"
13 #include "components/safe_browsing_db/safe_browsing_prefs.h"
9 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/browser_thread.h"
10 15
11 namespace { 16 namespace {
12 17
13 // URL to upload invalid certificate chain reports. An HTTP URL is used because 18 // 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 19 // a client seeing an invalid cert might not be able to make an HTTPS connection
15 // to report it. 20 // to report it.
16 const char kExtendedReportingUploadUrl[] = 21 const char kExtendedReportingUploadUrl[] =
17 "http://safebrowsing.googleusercontent.com/safebrowsing/clientreport/"; 22 "http://safebrowsing.googleusercontent.com/safebrowsing/clientreport/";
18 23
19 // Compare function that orders Reports in reverse chronological order (i.e. 24 // Compare function that orders Reports in reverse chronological order (i.e.
20 // oldest item is last). 25 // oldest item is last).
21 bool ReportCompareFunc(const CertificateReportingService::Report& item1, 26 bool ReportCompareFunc(const CertificateReportingService::Report& item1,
22 const CertificateReportingService::Report& item2) { 27 const CertificateReportingService::Report& item2) {
23 return item1.creation_time > item2.creation_time; 28 return item1.creation_time > item2.creation_time;
24 } 29 }
25 30
31 // Records an UMA histogram of the net errors when certificate reports
32 // fail to send.
33 void RecordUMAOnFailure(int net_error) {
34 UMA_HISTOGRAM_SPARSE_SLOWLY("SSL.CertificateErrorReportFailure", -net_error);
35 }
36
37 // Observes SafeBrowsing preferences and notifies CertificateReportingService
38 // when preferences change. There is one instance of this class per
39 // CertificateReportingService and each instance is owned by the
40 // CertificateReportingService it notifies.
41 class SafeBrowsingPreferenceObserver
42 : public CertificateReportingService::PreferenceObserver {
estark 2016/12/16 23:39:04 I'm wondering if these abstractions are needed (th
meacer 2016/12/19 23:16:45 Good point, removed. This used to be created by Ch
43 public:
44 SafeBrowsingPreferenceObserver(
45 const PrefService& prefs,
46 safe_browsing::SafeBrowsingService* safe_browsing_service,
47 CertificateReportingService* certificate_reporting_service)
48 : safe_browsing_service_(safe_browsing_service),
49 prefs_(prefs),
50 certificate_reporting_service_(certificate_reporting_service),
51 safe_browsing_state_subscription_(
52 safe_browsing_service->RegisterStateCallback(
53 base::Bind(&SafeBrowsingPreferenceObserver::OnPreferenceChanged,
54 base::Unretained(this)))) {}
55
56 ~SafeBrowsingPreferenceObserver() override {}
57
58 // CertificateReportingService::PreferenceObserver implementation:
59 void OnPreferenceChanged() override {
60 const bool enabled = safe_browsing_service_ &&
61 safe_browsing_service_->enabled_by_prefs() &&
62 safe_browsing::IsExtendedReportingEnabled(prefs_);
63 certificate_reporting_service_->SetEnabled(enabled);
64 }
65
66 private:
67 const safe_browsing::SafeBrowsingService* safe_browsing_service_;
68 const PrefService& prefs_;
69 CertificateReportingService* certificate_reporting_service_;
70 std::unique_ptr<safe_browsing::SafeBrowsingService::StateSubscription>
71 safe_browsing_state_subscription_;
72 };
73
26 } // namespace 74 } // namespace
27 75
28 CertificateReportingService::BoundedReportList::BoundedReportList( 76 CertificateReportingService::BoundedReportList::BoundedReportList(
29 size_t max_size) 77 size_t max_size)
30 : max_size_(max_size) { 78 : max_size_(max_size) {
31 CHECK(max_size <= 20) 79 CHECK(max_size <= 20)
32 << "Current implementation is not efficient for a large list."; 80 << "Current implementation is not efficient for a large list.";
33 DCHECK(thread_checker_.CalledOnValidThread()); 81 DCHECK(thread_checker_.CalledOnValidThread());
34 } 82 }
35 83
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 base::Bind(&CertificateReportingService::Reporter::SuccessCallback, 169 base::Bind(&CertificateReportingService::Reporter::SuccessCallback,
122 weak_factory_.GetWeakPtr(), report.report_id), 170 weak_factory_.GetWeakPtr(), report.report_id),
123 base::Bind(&CertificateReportingService::Reporter::ErrorCallback, 171 base::Bind(&CertificateReportingService::Reporter::ErrorCallback,
124 weak_factory_.GetWeakPtr(), report.report_id)); 172 weak_factory_.GetWeakPtr(), report.report_id));
125 } 173 }
126 174
127 void CertificateReportingService::Reporter::ErrorCallback(int report_id, 175 void CertificateReportingService::Reporter::ErrorCallback(int report_id,
128 const GURL& url, 176 const GURL& url,
129 int error) { 177 int error) {
130 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 178 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
179 RecordUMAOnFailure(error);
131 if (retries_enabled_) { 180 if (retries_enabled_) {
132 auto it = inflight_reports_.find(report_id); 181 auto it = inflight_reports_.find(report_id);
133 DCHECK(it != inflight_reports_.end()); 182 DCHECK(it != inflight_reports_.end());
134 retry_list_->Add(it->second); 183 retry_list_->Add(it->second);
135 } 184 }
136 CHECK_GT(inflight_reports_.erase(report_id), 0u); 185 CHECK_GT(inflight_reports_.erase(report_id), 0u);
137 } 186 }
138 187
139 void CertificateReportingService::Reporter::SuccessCallback(int report_id) { 188 void CertificateReportingService::Reporter::SuccessCallback(int report_id) {
140 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); 189 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
141 CHECK_GT(inflight_reports_.erase(report_id), 0u); 190 CHECK_GT(inflight_reports_.erase(report_id), 0u);
142 } 191 }
143 192
144 CertificateReportingService::CertificateReportingService( 193 CertificateReportingService::CertificateReportingService(
194 safe_browsing::SafeBrowsingService* safe_browsing_service,
145 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter, 195 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
196 Profile* profile,
146 uint8_t server_public_key[/* 32 */], 197 uint8_t server_public_key[/* 32 */],
147 uint32_t server_public_key_version, 198 uint32_t server_public_key_version,
148 size_t max_queued_report_count, 199 size_t max_queued_report_count,
149 base::TimeDelta max_report_age, 200 base::TimeDelta max_report_age,
150 std::unique_ptr<base::Clock> clock) 201 base::Clock* clock)
151 : enabled_(true), 202 : enabled_(true),
152 url_request_context_(nullptr), 203 url_request_context_(nullptr),
153 max_queued_report_count_(max_queued_report_count), 204 max_queued_report_count_(max_queued_report_count),
154 max_report_age_(max_report_age), 205 max_report_age_(max_report_age),
155 clock_(std::move(clock)), 206 clock_(clock),
156 made_send_attempt_(false),
157 server_public_key_(server_public_key), 207 server_public_key_(server_public_key),
158 server_public_key_version_(server_public_key_version) { 208 server_public_key_version_(server_public_key_version) {
159 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 209 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
210 DCHECK(clock_);
211 // Observe changes in SafeBrowsing preferences.
212 preference_observer_.reset(new SafeBrowsingPreferenceObserver(
213 *profile->GetPrefs(), safe_browsing_service, this));
214
215 // Subscribe to SafeBrowsing shutdown notifications.
216 safe_browsing_service_shutdown_subscription_ =
217 safe_browsing_service->RegisterShutdownCallback(base::Bind(
218 &CertificateReportingService::Shutdown, base::Unretained(this)));
219
160 content::BrowserThread::PostTask( 220 content::BrowserThread::PostTask(
161 content::BrowserThread::IO, FROM_HERE, 221 content::BrowserThread::IO, FROM_HERE,
162 base::Bind(&CertificateReportingService::InitializeOnIOThread, 222 base::Bind(&CertificateReportingService::InitializeOnIOThread,
163 base::Unretained(this), enabled_, url_request_context_getter, 223 base::Unretained(this), enabled_, url_request_context_getter,
164 max_queued_report_count_, max_report_age_, clock_.get(), 224 max_queued_report_count_, max_report_age_, clock_,
165 server_public_key_, server_public_key_version_)); 225 server_public_key_, server_public_key_version_));
166 } 226 }
167 227
168 CertificateReportingService::~CertificateReportingService() { 228 CertificateReportingService::~CertificateReportingService() {
169 DCHECK(!reporter_); 229 DCHECK(!reporter_);
170 } 230 }
171 231
172 void CertificateReportingService::Shutdown() { 232 void CertificateReportingService::Shutdown() {
173 // Shutdown will be called twice: Once after SafeBrowsing shuts down, and once 233 // 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. 234 // when all KeyedServices shut down. All calls after the first one are no-op.
175 enabled_ = false; 235 enabled_ = false;
176 Reset(); 236 Reset();
177 } 237 }
178 238
179 void CertificateReportingService::Send(const std::string& serialized_report) { 239 void CertificateReportingService::Send(const std::string& serialized_report) {
180 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 240 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
181 made_send_attempt_ = true;
182 if (!reporter_) { 241 if (!reporter_) {
183 return; 242 return;
184 } 243 }
185 content::BrowserThread::PostTask( 244 content::BrowserThread::PostTask(
186 content::BrowserThread::IO, FROM_HERE, 245 content::BrowserThread::IO, FROM_HERE,
187 base::Bind(&CertificateReportingService::Reporter::Send, 246 base::Bind(&CertificateReportingService::Reporter::Send,
188 base::Unretained(reporter_.get()), serialized_report)); 247 base::Unretained(reporter_.get()), serialized_report));
189 } 248 }
190 249
191 void CertificateReportingService::SendPending() { 250 void CertificateReportingService::SendPending() {
192 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 251 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
193 made_send_attempt_ = true;
194 if (!reporter_) { 252 if (!reporter_) {
195 return; 253 return;
196 } 254 }
197 content::BrowserThread::PostTask( 255 content::BrowserThread::PostTask(
198 content::BrowserThread::IO, FROM_HERE, 256 content::BrowserThread::IO, FROM_HERE,
199 base::Bind(&CertificateReportingService::Reporter::SendPending, 257 base::Bind(&CertificateReportingService::Reporter::SendPending,
200 base::Unretained(reporter_.get()))); 258 base::Unretained(reporter_.get())));
201 } 259 }
202 260
203 void CertificateReportingService::InitializeOnIOThread( 261 void CertificateReportingService::InitializeOnIOThread(
(...skipping 16 matching lines...) Expand all
220 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 278 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
221 enabled_ = enabled; 279 enabled_ = enabled;
222 Reset(); 280 Reset();
223 } 281 }
224 282
225 CertificateReportingService::Reporter* 283 CertificateReportingService::Reporter*
226 CertificateReportingService::GetReporterForTesting() const { 284 CertificateReportingService::GetReporterForTesting() const {
227 return reporter_.get(); 285 return reporter_.get();
228 } 286 }
229 287
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 288 // static
252 GURL CertificateReportingService::GetReportingURLForTesting() { 289 GURL CertificateReportingService::GetReportingURLForTesting() {
253 return GURL(kExtendedReportingUploadUrl); 290 return GURL(kExtendedReportingUploadUrl);
254 } 291 }
255 292
256 void CertificateReportingService::Reset() { 293 void CertificateReportingService::Reset() {
257 content::BrowserThread::PostTask( 294 content::BrowserThread::PostTask(
258 content::BrowserThread::IO, FROM_HERE, 295 content::BrowserThread::IO, FROM_HERE,
259 base::Bind(&CertificateReportingService::ResetOnIOThread, 296 base::Bind(&CertificateReportingService::ResetOnIOThread,
260 base::Unretained(this), enabled_, url_request_context_, 297 base::Unretained(this), enabled_, url_request_context_,
261 max_queued_report_count_, max_report_age_, clock_.get(), 298 max_queued_report_count_, max_report_age_, clock_,
262 server_public_key_, server_public_key_version_)); 299 server_public_key_, server_public_key_version_));
263 } 300 }
264 301
265 void CertificateReportingService::ResetOnIOThread( 302 void CertificateReportingService::ResetOnIOThread(
266 bool enabled, 303 bool enabled,
267 net::URLRequestContext* url_request_context, 304 net::URLRequestContext* url_request_context,
268 size_t max_queued_report_count, 305 size_t max_queued_report_count,
269 base::TimeDelta max_report_age, 306 base::TimeDelta max_report_age,
270 base::Clock* clock, 307 base::Clock* clock,
271 uint8_t* const server_public_key, 308 uint8_t* const server_public_key,
(...skipping 17 matching lines...) Expand all
289 url_request_context, GURL(kExtendedReportingUploadUrl), 326 url_request_context, GURL(kExtendedReportingUploadUrl),
290 net::ReportSender::DO_NOT_SEND_COOKIES)); 327 net::ReportSender::DO_NOT_SEND_COOKIES));
291 } 328 }
292 329
293 reporter_.reset( 330 reporter_.reset(
294 new Reporter(std::move(error_reporter), 331 new Reporter(std::move(error_reporter),
295 std::unique_ptr<BoundedReportList>( 332 std::unique_ptr<BoundedReportList>(
296 new BoundedReportList(max_queued_report_count)), 333 new BoundedReportList(max_queued_report_count)),
297 clock, max_report_age, true /* retries_enabled */)); 334 clock, max_report_age, true /* retries_enabled */));
298 } 335 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698