| Index: chrome/browser/ssl/certificate_reporting_service.cc
|
| diff --git a/chrome/browser/ssl/certificate_reporting_service.cc b/chrome/browser/ssl/certificate_reporting_service.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..19b6ca2793903f48def7cd9c7bc966f78349325d
|
| --- /dev/null
|
| +++ b/chrome/browser/ssl/certificate_reporting_service.cc
|
| @@ -0,0 +1,145 @@
|
| +// 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/ssl/certificate_reporting_service.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +
|
| +namespace {
|
| +// First item is ordered before the second item if it's newer.
|
| +bool ReportCompareFunc(const CertificateReportingService::Report& item1,
|
| + const CertificateReportingService::Report& item2) {
|
| + return item1.creation_time > item2.creation_time;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +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);
|
| +}
|
| +
|
| +CertificateReportingService::BoundedReportList::BoundedReportList(
|
| + size_t max_size)
|
| + : max_size_(max_size) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +}
|
| +
|
| +void CertificateReportingService::BoundedReportList::Clear() {
|
| + items_.clear();
|
| +}
|
| +
|
| +CertificateReportingService::BoundedReportList::~BoundedReportList() {}
|
| +
|
| +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 max_item_age,
|
| + EventObserver* event_observer)
|
| + : error_reporter_(std::move(error_reporter)),
|
| + retry_list_(std::move(retry_list)),
|
| + test_clock_(clock),
|
| + max_item_age_(max_item_age),
|
| + event_observer_(event_observer),
|
| + current_report_id_(0) {}
|
| +
|
| +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 - max_item_age_) {
|
| + // Report too old, ignore.
|
| + continue;
|
| + }
|
| + SendInternal(report);
|
| + }
|
| + retry_list_->Clear();
|
| +}
|
| +
|
| +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::SetEventObserverForTesting(
|
| + EventObserver* observer) {
|
| + event_observer_ = observer;
|
| +}
|
| +
|
| +CertificateReportingService::Reporter::~Reporter() {}
|
| +
|
| +void CertificateReportingService::Reporter::SendInternal(
|
| + const CertificateReportingService::Report& report) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + inflight_reports_[report.report_id] = report;
|
| + error_reporter_->SendExtendedReportingReport(
|
| + report.serialized_report,
|
| + base::Bind(&CertificateReportingService::Reporter::SuccessCallback, this,
|
| + report.report_id),
|
| + base::Bind(&CertificateReportingService::Reporter::ErrorCallback, this,
|
| + report.report_id));
|
| +}
|
| +
|
| +void CertificateReportingService::Reporter::ErrorCallback(int report_id,
|
| + const GURL& url,
|
| + int error) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + retry_list_->Add(inflight_reports_[report_id]);
|
| + CHECK_GT(inflight_reports_.erase(report_id), 0u);
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&CertificateReportingService::Reporter::OnSendComplete, this,
|
| + false));
|
| +}
|
| +
|
| +void CertificateReportingService::Reporter::SuccessCallback(int report_id) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
| + CHECK_GT(inflight_reports_.erase(report_id), 0u);
|
| + content::BrowserThread::PostTask(
|
| + content::BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&CertificateReportingService::Reporter::OnSendComplete, this,
|
| + true));
|
| +}
|
| +
|
| +void CertificateReportingService::Reporter::OnSendComplete(bool success) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + event_observer_->OnSendComplete(success);
|
| +}
|
|
|