1 // Copyright 2017 The Chromium Authors 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 "net/reporting/reporting_garbage_collector.h" 6 7 #include <utility> 8 #include <vector> 9 10 #include "base/containers/flat_set.h" 11 #include "base/functional/bind.h" 12 #include "base/memory/raw_ptr.h" 13 #include "base/time/tick_clock.h" 14 #include "base/time/time.h" 15 #include "base/timer/timer.h" 16 #include "net/reporting/reporting_cache.h" 17 #include "net/reporting/reporting_cache_observer.h" 18 #include "net/reporting/reporting_context.h" 19 #include "net/reporting/reporting_policy.h" 20 #include "net/reporting/reporting_report.h" 21 22 namespace net { 23 24 namespace { 25 26 class ReportingGarbageCollectorImpl : public ReportingGarbageCollector, 27 public ReportingCacheObserver { 28 public: ReportingGarbageCollectorImpl(ReportingContext * context)29 explicit ReportingGarbageCollectorImpl(ReportingContext* context) 30 : context_(context), timer_(std::make_unique<base::OneShotTimer>()) { 31 context_->AddCacheObserver(this); 32 } 33 34 // ReportingGarbageCollector implementation: 35 ~ReportingGarbageCollectorImpl()36 ~ReportingGarbageCollectorImpl() override { 37 context_->RemoveCacheObserver(this); 38 } 39 SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer)40 void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer) override { 41 timer_ = std::move(timer); 42 } 43 44 // ReportingObserver implementation: OnReportsUpdated()45 void OnReportsUpdated() override { EnsureTimerIsRunning(); } OnEndpointsUpdatedForOrigin(const std::vector<ReportingEndpoint> & endpoints)46 void OnEndpointsUpdatedForOrigin( 47 const std::vector<ReportingEndpoint>& endpoints) override { 48 EnsureTimerIsRunning(); 49 } 50 51 private: 52 // TODO(crbug.com/912622): Garbage collect clients, reports with no matching 53 // endpoints. CollectGarbage()54 void CollectGarbage() { 55 base::TimeTicks now = context_->tick_clock().NowTicks(); 56 const ReportingPolicy& policy = context_->policy(); 57 58 base::flat_set<base::UnguessableToken> sources_to_remove = 59 context_->cache()->GetExpiredSources(); 60 61 std::vector<raw_ptr<const ReportingReport, VectorExperimental>> all_reports; 62 context_->cache()->GetReports(&all_reports); 63 64 std::vector<raw_ptr<const ReportingReport, VectorExperimental>> 65 failed_reports; 66 std::vector<raw_ptr<const ReportingReport, VectorExperimental>> 67 expired_reports; 68 for (const ReportingReport* report : all_reports) { 69 if (report->attempts >= policy.max_report_attempts) 70 failed_reports.push_back(report); 71 else if (now - report->queued >= policy.max_report_age) 72 expired_reports.push_back(report); 73 else 74 sources_to_remove.erase(report->reporting_source); 75 } 76 77 // Don't restart the timer on the garbage collector's own updates. 78 context_->RemoveCacheObserver(this); 79 context_->cache()->RemoveReports(failed_reports); 80 context_->cache()->RemoveReports(expired_reports); 81 for (const base::UnguessableToken& reporting_source : sources_to_remove) { 82 context_->cache()->RemoveSourceAndEndpoints(reporting_source); 83 } 84 context_->AddCacheObserver(this); 85 } 86 EnsureTimerIsRunning()87 void EnsureTimerIsRunning() { 88 if (timer_->IsRunning()) 89 return; 90 91 timer_->Start(FROM_HERE, context_->policy().garbage_collection_interval, 92 base::BindOnce(&ReportingGarbageCollectorImpl::CollectGarbage, 93 base::Unretained(this))); 94 } 95 96 raw_ptr<ReportingContext> context_; 97 std::unique_ptr<base::OneShotTimer> timer_; 98 }; 99 100 } // namespace 101 102 // static Create(ReportingContext * context)103std::unique_ptr<ReportingGarbageCollector> ReportingGarbageCollector::Create( 104 ReportingContext* context) { 105 return std::make_unique<ReportingGarbageCollectorImpl>(context); 106 } 107 108 ReportingGarbageCollector::~ReportingGarbageCollector() = default; 109 110 } // namespace net 111