| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "base/time/clock.h" |
| 6 #include "base/time/default_clock.h" |
| 7 #include "chrome/browser/safe_browsing/certificate_reporting_service.h" |
| 8 #include "content/public/browser/browser_thread.h" |
| 9 |
| 10 namespace { |
| 11 // Compare function that orders Reports in reverse chronological order (i.e. |
| 12 // oldest item is last). |
| 13 bool ReportCompareFunc(const CertificateReportingService::Report& item1, |
| 14 const CertificateReportingService::Report& item2) { |
| 15 return item1.creation_time > item2.creation_time; |
| 16 } |
| 17 |
| 18 } // namespace |
| 19 |
| 20 CertificateReportingService::BoundedReportList::BoundedReportList( |
| 21 size_t max_size) |
| 22 : max_size_(max_size) { |
| 23 CHECK(max_size <= 20) |
| 24 << "Current implementation is not efficient for a large list."; |
| 25 DCHECK(thread_checker_.CalledOnValidThread()); |
| 26 } |
| 27 |
| 28 CertificateReportingService::BoundedReportList::~BoundedReportList() {} |
| 29 |
| 30 void CertificateReportingService::BoundedReportList::Add(const Report& item) { |
| 31 DCHECK(thread_checker_.CalledOnValidThread()); |
| 32 DCHECK(items_.size() <= max_size_); |
| 33 if (items_.size() == max_size_) { |
| 34 const Report& last = items_.back(); |
| 35 if (item.creation_time <= last.creation_time) { |
| 36 // Report older than the oldest item in the queue, ignore. |
| 37 return; |
| 38 } |
| 39 // Reached the maximum item count, remove the oldest item. |
| 40 items_.pop_back(); |
| 41 } |
| 42 items_.push_back(item); |
| 43 std::sort(items_.begin(), items_.end(), ReportCompareFunc); |
| 44 } |
| 45 |
| 46 void CertificateReportingService::BoundedReportList::Clear() { |
| 47 items_.clear(); |
| 48 } |
| 49 |
| 50 const std::vector<CertificateReportingService::Report>& |
| 51 CertificateReportingService::BoundedReportList::items() const { |
| 52 DCHECK(thread_checker_.CalledOnValidThread()); |
| 53 return items_; |
| 54 } |
| 55 |
| 56 CertificateReportingService::Reporter::Reporter( |
| 57 std::unique_ptr<certificate_reporting::ErrorReporter> error_reporter, |
| 58 std::unique_ptr<BoundedReportList> retry_list, |
| 59 base::Clock* clock, |
| 60 base::TimeDelta report_ttl) |
| 61 : error_reporter_(std::move(error_reporter)), |
| 62 retry_list_(std::move(retry_list)), |
| 63 test_clock_(clock), |
| 64 report_ttl_(report_ttl), |
| 65 current_report_id_(0), |
| 66 weak_factory_(this) {} |
| 67 |
| 68 CertificateReportingService::Reporter::~Reporter() {} |
| 69 |
| 70 void CertificateReportingService::Reporter::Send( |
| 71 const std::string& serialized_report) { |
| 72 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 73 base::Time now = |
| 74 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime(); |
| 75 SendInternal(Report(current_report_id_++, now, serialized_report)); |
| 76 } |
| 77 |
| 78 void CertificateReportingService::Reporter::SendPending() { |
| 79 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 80 base::Time now = |
| 81 test_clock_ ? test_clock_->Now() : base::Time::NowFromSystemTime(); |
| 82 // Copy pending reports and clear the retry list. |
| 83 std::vector<Report> items = retry_list_->items(); |
| 84 retry_list_->Clear(); |
| 85 for (const Report& report : items) { |
| 86 if (report.creation_time < now - report_ttl_) { |
| 87 // Report too old, ignore. |
| 88 continue; |
| 89 } |
| 90 SendInternal(report); |
| 91 } |
| 92 } |
| 93 |
| 94 size_t |
| 95 CertificateReportingService::Reporter::inflight_report_count_for_testing() |
| 96 const { |
| 97 return inflight_reports_.size(); |
| 98 } |
| 99 |
| 100 CertificateReportingService::BoundedReportList* |
| 101 CertificateReportingService::Reporter::GetQueueForTesting() const { |
| 102 return retry_list_.get(); |
| 103 } |
| 104 |
| 105 void CertificateReportingService::Reporter::SendInternal( |
| 106 const CertificateReportingService::Report& report) { |
| 107 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 108 inflight_reports_.insert(std::make_pair(report.report_id, report)); |
| 109 error_reporter_->SendExtendedReportingReport( |
| 110 report.serialized_report, |
| 111 base::Bind(&CertificateReportingService::Reporter::SuccessCallback, |
| 112 weak_factory_.GetWeakPtr(), report.report_id), |
| 113 base::Bind(&CertificateReportingService::Reporter::ErrorCallback, |
| 114 weak_factory_.GetWeakPtr(), report.report_id)); |
| 115 } |
| 116 |
| 117 void CertificateReportingService::Reporter::ErrorCallback(int report_id, |
| 118 const GURL& url, |
| 119 int error) { |
| 120 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 121 auto it = inflight_reports_.find(report_id); |
| 122 DCHECK(it != inflight_reports_.end()); |
| 123 retry_list_->Add(it->second); |
| 124 CHECK_GT(inflight_reports_.erase(report_id), 0u); |
| 125 } |
| 126 |
| 127 void CertificateReportingService::Reporter::SuccessCallback(int report_id) { |
| 128 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| 129 CHECK_GT(inflight_reports_.erase(report_id), 0u); |
| 130 } |
| OLD | NEW |