Chromium Code Reviews| Index: chrome/browser/safe_browsing/certificate_reporting_service.cc |
| diff --git a/chrome/browser/safe_browsing/certificate_reporting_service.cc b/chrome/browser/safe_browsing/certificate_reporting_service.cc |
| index 52a20c7501cdc040239c5295ddf3d94269295877..e01324bfc6339819a0150afa6edac6254923b4c9 100644 |
| --- a/chrome/browser/safe_browsing/certificate_reporting_service.cc |
| +++ b/chrome/browser/safe_browsing/certificate_reporting_service.cc |
| @@ -2,6 +2,7 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include "base/bind_helpers.h" |
| #include "base/time/clock.h" |
| #include "base/time/default_clock.h" |
| #include "chrome/browser/safe_browsing/certificate_reporting_service.h" |
| @@ -17,6 +18,10 @@ bool ReportCompareFunc(const CertificateReportingService::Report& item1, |
| } // namespace |
| +// static |
| +const char CertificateReportingService::kExtendedReportingUploadUrlInsecure[] = |
| + "http://safebrowsing.googleusercontent.com/safebrowsing/clientreport/"; |
| + |
| CertificateReportingService::BoundedReportList::BoundedReportList( |
| size_t max_size) |
| : max_size_(max_size) { |
| @@ -57,11 +62,13 @@ CertificateReportingService::Reporter::Reporter( |
| std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter, |
| std::unique_ptr<BoundedReportList> retry_list, |
| base::Clock* clock, |
| - base::TimeDelta report_ttl) |
| + base::TimeDelta report_ttl, |
| + bool retries_enabled) |
| : error_reporter_(std::move(error_reporter)), |
| retry_list_(std::move(retry_list)), |
| - test_clock_(clock), |
| + clock_(clock), |
| report_ttl_(report_ttl), |
| + retries_enabled_(retries_enabled), |
| current_report_id_(0), |
| weak_factory_(this) {} |
| @@ -70,15 +77,15 @@ CertificateReportingService::Reporter::~Reporter() {} |
| void CertificateReportingService::Reporter::Send( |
| const std::string& serialized_report) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| - base::Time now = |
| - test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime(); |
| - SendInternal(Report(current_report_id_++, now, serialized_report)); |
| + SendInternal(Report(current_report_id_++, clock_->Now(), serialized_report)); |
| } |
| void CertificateReportingService::Reporter::SendPending() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| - base::Time now = |
| - test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime(); |
| + if (!retries_enabled_) { |
| + return; |
| + } |
| + const base::Time now = clock_->Now(); |
| // Copy pending reports and clear the retry list. |
| std::vector<Report> items = retry_list_->items(); |
| retry_list_->Clear(); |
| @@ -118,9 +125,11 @@ void CertificateReportingService::Reporter::ErrorCallback(int report_id, |
| const GURL& url, |
| int error) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| - auto it = inflight_reports_.find(report_id); |
| - DCHECK(it != inflight_reports_.end()); |
| - retry_list_->Add(it->second); |
| + if (retries_enabled_) { |
| + auto it = inflight_reports_.find(report_id); |
| + DCHECK(it != inflight_reports_.end()); |
| + retry_list_->Add(it->second); |
| + } |
| CHECK_GT(inflight_reports_.erase(report_id), 0u); |
| } |
| @@ -128,3 +137,155 @@ void CertificateReportingService::Reporter::SuccessCallback(int report_id) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| CHECK_GT(inflight_reports_.erase(report_id), 0u); |
| } |
| + |
| +CertificateReportingService::CertificateReportingService( |
| + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter, |
| + uint8_t server_public_key[/* 32 */], |
| + uint32_t server_public_key_version, |
| + size_t max_queued_report_count, |
| + base::TimeDelta max_report_age, |
| + std::unique_ptr<base::Clock> clock) |
| + : enabled_(true), |
| + url_request_context_(nullptr), |
| + max_queued_report_count_(max_queued_report_count), |
| + max_report_age_(max_report_age), |
| + clock_(std::move(clock)), |
| + made_send_attempt_(false), |
| + server_public_key_(server_public_key), |
| + server_public_key_version_(server_public_key_version) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(&CertificateReportingService::InitializeOnIOThread, |
| + 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
|
| + max_queued_report_count_, max_report_age_, clock_.get(), |
| + server_public_key_, server_public_key_version_)); |
| +} |
| + |
| +CertificateReportingService::~CertificateReportingService() { |
| + DCHECK(!reporter_); |
| +} |
| + |
| +void CertificateReportingService::Shutdown() { |
| + // Shutdown will be called twice: Once after SafeBrowsing shuts down, and once |
| + // when all KeyedServices shut down. All calls after the first one are no-op. |
| + enabled_ = false; |
| + Reset(); |
| +} |
| + |
| +void CertificateReportingService::Send(const std::string& serialized_report) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + made_send_attempt_ = true; |
| + if (!reporter_) { |
| + return; |
| + } |
| + 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.
|
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(&CertificateReportingService::Reporter::Send, |
| + base::Unretained(reporter_.get()), serialized_report)); |
| +} |
| + |
| +void CertificateReportingService::SendPending() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + made_send_attempt_ = true; |
| + if (!reporter_) { |
| + return; |
| + } |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(&CertificateReportingService::Reporter::SendPending, |
| + base::Unretained(reporter_.get()))); |
| +} |
| + |
| +void CertificateReportingService::InitializeOnIOThread( |
| + bool enabled, |
| + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter, |
| + size_t max_queued_report_count, |
| + base::TimeDelta max_report_age, |
| + base::Clock* clock, |
| + uint8_t* server_public_key, |
| + uint32_t server_public_key_version) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| + DCHECK(!url_request_context_); |
| + url_request_context_ = url_request_context_getter->GetURLRequestContext(); |
| + ResetOnIOThread(enabled, url_request_context_, max_queued_report_count, |
| + max_report_age, clock, server_public_key, |
| + server_public_key_version); |
| +} |
| + |
| +void CertificateReportingService::SetEnabled(bool enabled) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + enabled_ = enabled; |
| + Reset(); |
| +} |
| + |
| +CertificateReportingService::Reporter* |
| +CertificateReportingService::get_reporter_for_testing() const { |
| + return reporter_.get(); |
| +} |
| + |
| +void CertificateReportingService::SetMaxQueuedReportCountForTesting( |
| + size_t count) { |
| + DCHECK(!made_send_attempt_); |
| + max_queued_report_count_ = count; |
| + Reset(); |
| +} |
| + |
| +void CertificateReportingService::SetClockForTesting( |
| + std::unique_ptr<base::Clock> clock) { |
| + DCHECK(!made_send_attempt_); |
| + clock_ = std::move(clock); |
| + Reset(); |
| +} |
| + |
| +void CertificateReportingService::SetMaxReportAgeForTesting( |
| + base::TimeDelta max_report_age) { |
| + DCHECK(!made_send_attempt_); |
| + max_report_age_ = max_report_age; |
| + Reset(); |
| +} |
| + |
| +void CertificateReportingService::Reset() { |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, FROM_HERE, |
| + base::Bind(&CertificateReportingService::ResetOnIOThread, |
| + base::Unretained(this), enabled_, url_request_context_, |
| + max_queued_report_count_, max_report_age_, clock_.get(), |
| + server_public_key_, server_public_key_version_)); |
| +} |
| + |
| +void CertificateReportingService::ResetOnIOThread( |
| + bool enabled, |
| + net::URLRequestContext* url_request_context, |
| + size_t max_queued_report_count, |
| + base::TimeDelta max_report_age, |
| + base::Clock* clock, |
| + uint8_t* const server_public_key, |
| + uint32_t server_public_key_version) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| + // url_request_context_ is null during shutdown. |
| + if (!enabled || !url_request_context) { |
| + reporter_.reset(nullptr); |
| + return; |
| + } |
| + std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter; |
| + if (server_public_key) { |
| + // Only used in tests. |
| + std::unique_ptr<net::ReportSender> report_sender(new net::ReportSender( |
| + url_request_context, net::ReportSender::DO_NOT_SEND_COOKIES)); |
| + error_reporter.reset(new certificate_reporting::ErrorReporter( |
| + GURL(kExtendedReportingUploadUrlInsecure), server_public_key, |
| + server_public_key_version, std::move(report_sender))); |
| + } else { |
| + error_reporter.reset(new certificate_reporting::ErrorReporter( |
| + url_request_context, GURL(kExtendedReportingUploadUrlInsecure), |
| + net::ReportSender::DO_NOT_SEND_COOKIES)); |
| + } |
| + |
| + reporter_.reset( |
| + new Reporter(std::move(error_reporter), |
| + std::unique_ptr<BoundedReportList>( |
| + new BoundedReportList(max_queued_report_count)), |
| + clock, max_report_age, true /* retries_enabled */)); |
| +} |