| 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
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..52a20c7501cdc040239c5295ddf3d94269295877
|
| --- /dev/null
|
| +++ b/chrome/browser/safe_browsing/certificate_reporting_service.cc
|
| @@ -0,0 +1,130 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/time/clock.h"
|
| +#include "base/time/default_clock.h"
|
| +#include "chrome/browser/safe_browsing/certificate_reporting_service.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +
|
| +namespace {
|
| +// Compare function that orders Reports in reverse chronological order (i.e.
|
| +// oldest item is last).
|
| +bool ReportCompareFunc(const CertificateReportingService::Report& item1,
|
| + const CertificateReportingService::Report& item2) {
|
| + return item1.creation_time > item2.creation_time;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +CertificateReportingService::BoundedReportList::BoundedReportList(
|
| + size_t max_size)
|
| + : max_size_(max_size) {
|
| + CHECK(max_size <= 20)
|
| + << "Current implementation is not efficient for a large list.";
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +}
|
| +
|
| +CertificateReportingService::BoundedReportList::~BoundedReportList() {}
|
| +
|
| +void CertificateReportingService::BoundedReportList::Add(const Report& item) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + DCHECK(items_.size() <= max_size_);
|
| + if (items_.size() == max_size_) {
|
| + const Report& last = items_.back();
|
| + if (item.creation_time <= last.creation_time) {
|
| + // Report older than the oldest item in the queue, ignore.
|
| + return;
|
| + }
|
| + // Reached the maximum item count, remove the oldest item.
|
| + items_.pop_back();
|
| + }
|
| + items_.push_back(item);
|
| + std::sort(items_.begin(), items_.end(), ReportCompareFunc);
|
| +}
|
| +
|
| +void CertificateReportingService::BoundedReportList::Clear() {
|
| + items_.clear();
|
| +}
|
| +
|
| +const std::vector<CertificateReportingService::Report>&
|
| +CertificateReportingService::BoundedReportList::items() const {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + return items_;
|
| +}
|
| +
|
| +CertificateReportingService::Reporter::Reporter(
|
| + std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter,
|
| + std::unique_ptr<BoundedReportList> retry_list,
|
| + base::Clock* clock,
|
| + base::TimeDelta report_ttl)
|
| + : error_reporter_(std::move(error_reporter)),
|
| + retry_list_(std::move(retry_list)),
|
| + test_clock_(clock),
|
| + report_ttl_(report_ttl),
|
| + current_report_id_(0),
|
| + weak_factory_(this) {}
|
| +
|
| +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));
|
| +}
|
| +
|
| +void CertificateReportingService::Reporter::SendPending() {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + base::Time now =
|
| + test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime();
|
| + // Copy pending reports and clear the retry list.
|
| + std::vector<Report> items = retry_list_->items();
|
| + retry_list_->Clear();
|
| + for (const Report& report : items) {
|
| + if (report.creation_time < now - report_ttl_) {
|
| + // Report too old, ignore.
|
| + continue;
|
| + }
|
| + SendInternal(report);
|
| + }
|
| +}
|
| +
|
| +size_t
|
| +CertificateReportingService::Reporter::inflight_report_count_for_testing()
|
| + const {
|
| + return inflight_reports_.size();
|
| +}
|
| +
|
| +CertificateReportingService::BoundedReportList*
|
| +CertificateReportingService::Reporter::GetQueueForTesting() const {
|
| + return retry_list_.get();
|
| +}
|
| +
|
| +void CertificateReportingService::Reporter::SendInternal(
|
| + const CertificateReportingService::Report& report) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + inflight_reports_.insert(std::make_pair(report.report_id, report));
|
| + error_reporter_->SendExtendedReportingReport(
|
| + report.serialized_report,
|
| + base::Bind(&CertificateReportingService::Reporter::SuccessCallback,
|
| + weak_factory_.GetWeakPtr(), report.report_id),
|
| + base::Bind(&CertificateReportingService::Reporter::ErrorCallback,
|
| + weak_factory_.GetWeakPtr(), report.report_id));
|
| +}
|
| +
|
| +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);
|
| + CHECK_GT(inflight_reports_.erase(report_id), 0u);
|
| +}
|
| +
|
| +void CertificateReportingService::Reporter::SuccessCallback(int report_id) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + CHECK_GT(inflight_reports_.erase(report_id), 0u);
|
| +}
|
|
|