OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/reporting/reporting_cache.h" | 5 #include "net/reporting/reporting_cache.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <memory> | 8 #include <memory> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 | 43 |
44 return domain.substr(dot_pos + 1); | 44 return domain.substr(dot_pos + 1); |
45 } | 45 } |
46 | 46 |
47 class ReportingCacheImpl : public ReportingCache { | 47 class ReportingCacheImpl : public ReportingCache { |
48 public: | 48 public: |
49 ReportingCacheImpl(ReportingContext* context) : context_(context) { | 49 ReportingCacheImpl(ReportingContext* context) : context_(context) { |
50 DCHECK(context_); | 50 DCHECK(context_); |
51 } | 51 } |
52 | 52 |
53 ~ReportingCacheImpl() override {} | 53 ~ReportingCacheImpl() override { |
| 54 base::TimeTicks now = tick_clock()->NowTicks(); |
| 55 |
| 56 // Mark all undoomed reports as erased at shutdown, and record outcomes of |
| 57 // all remaining reports (doomed or not). |
| 58 for (auto it = reports_.begin(); it != reports_.end(); ++it) { |
| 59 ReportingReport* report = it->second.get(); |
| 60 if (!base::ContainsKey(doomed_reports_, report)) |
| 61 report->outcome = ReportingReport::Outcome::ERASED_REPORTING_SHUT_DOWN; |
| 62 report->RecordOutcome(now); |
| 63 } |
| 64 |
| 65 reports_.clear(); |
| 66 } |
54 | 67 |
55 void AddReport(const GURL& url, | 68 void AddReport(const GURL& url, |
56 const std::string& group, | 69 const std::string& group, |
57 const std::string& type, | 70 const std::string& type, |
58 std::unique_ptr<const base::Value> body, | 71 std::unique_ptr<const base::Value> body, |
59 base::TimeTicks queued, | 72 base::TimeTicks queued, |
60 int attempts) override { | 73 int attempts) override { |
61 auto report = base::MakeUnique<ReportingReport>( | 74 auto report = base::MakeUnique<ReportingReport>( |
62 url, group, type, std::move(body), queued, attempts); | 75 url, group, type, std::move(body), queued, attempts); |
63 | 76 |
64 auto inserted = | 77 auto inserted = |
65 reports_.insert(std::make_pair(report.get(), std::move(report))); | 78 reports_.insert(std::make_pair(report.get(), std::move(report))); |
66 DCHECK(inserted.second); | 79 DCHECK(inserted.second); |
67 | 80 |
68 if (reports_.size() > context_->policy().max_report_count) { | 81 if (reports_.size() > context_->policy().max_report_count) { |
69 // There should be at most one extra report (the one added above). | 82 // There should be at most one extra report (the one added above). |
70 DCHECK_EQ(context_->policy().max_report_count + 1, reports_.size()); | 83 DCHECK_EQ(context_->policy().max_report_count + 1, reports_.size()); |
71 const ReportingReport* to_evict = FindReportToEvict(); | 84 const ReportingReport* to_evict = FindReportToEvict(); |
72 DCHECK_NE(nullptr, to_evict); | 85 DCHECK_NE(nullptr, to_evict); |
73 // The newly-added report isn't pending, so even if all other reports are | 86 // The newly-added report isn't pending, so even if all other reports are |
74 // pending, the cache should have a report to evict. | 87 // pending, the cache should have a report to evict. |
75 DCHECK(!base::ContainsKey(pending_reports_, to_evict)); | 88 DCHECK(!base::ContainsKey(pending_reports_, to_evict)); |
76 size_t erased = reports_.erase(to_evict); | 89 reports_[to_evict]->outcome = ReportingReport::Outcome::ERASED_EVICTED; |
77 DCHECK_EQ(1u, erased); | 90 RemoveReportInternal(to_evict); |
78 } | 91 } |
79 | 92 |
80 context_->NotifyCacheUpdated(); | 93 context_->NotifyCacheUpdated(); |
81 } | 94 } |
82 | 95 |
83 void GetReports( | 96 void GetReports( |
84 std::vector<const ReportingReport*>* reports_out) const override { | 97 std::vector<const ReportingReport*>* reports_out) const override { |
85 reports_out->clear(); | 98 reports_out->clear(); |
86 for (const auto& it : reports_) { | 99 for (const auto& it : reports_) { |
87 if (!base::ContainsKey(doomed_reports_, it.first)) | 100 if (!base::ContainsKey(doomed_reports_, it.first)) |
(...skipping 15 matching lines...) Expand all Loading... |
103 | 116 |
104 for (const ReportingReport* report : reports) { | 117 for (const ReportingReport* report : reports) { |
105 size_t erased = pending_reports_.erase(report); | 118 size_t erased = pending_reports_.erase(report); |
106 DCHECK_EQ(1u, erased); | 119 DCHECK_EQ(1u, erased); |
107 if (base::ContainsKey(doomed_reports_, report)) { | 120 if (base::ContainsKey(doomed_reports_, report)) { |
108 reports_to_remove.push_back(report); | 121 reports_to_remove.push_back(report); |
109 doomed_reports_.erase(report); | 122 doomed_reports_.erase(report); |
110 } | 123 } |
111 } | 124 } |
112 | 125 |
113 RemoveReports(reports_to_remove); | 126 for (const ReportingReport* report : reports_to_remove) |
| 127 RemoveReportInternal(report); |
114 } | 128 } |
115 | 129 |
116 void IncrementReportsAttempts( | 130 void IncrementReportsAttempts( |
117 const std::vector<const ReportingReport*>& reports) override { | 131 const std::vector<const ReportingReport*>& reports) override { |
118 for (const ReportingReport* report : reports) { | 132 for (const ReportingReport* report : reports) { |
119 DCHECK(base::ContainsKey(reports_, report)); | 133 DCHECK(base::ContainsKey(reports_, report)); |
120 reports_[report]->attempts++; | 134 reports_[report]->attempts++; |
121 } | 135 } |
122 | 136 |
123 context_->NotifyCacheUpdated(); | 137 context_->NotifyCacheUpdated(); |
124 } | 138 } |
125 | 139 |
126 void RemoveReports( | 140 void RemoveReports(const std::vector<const ReportingReport*>& reports, |
127 const std::vector<const ReportingReport*>& reports) override { | 141 ReportingReport::Outcome outcome) override { |
128 for (const ReportingReport* report : reports) { | 142 for (const ReportingReport* report : reports) { |
| 143 reports_[report]->outcome = outcome; |
129 if (base::ContainsKey(pending_reports_, report)) { | 144 if (base::ContainsKey(pending_reports_, report)) { |
130 doomed_reports_.insert(report); | 145 doomed_reports_.insert(report); |
131 } else { | 146 } else { |
132 DCHECK(!base::ContainsKey(doomed_reports_, report)); | 147 DCHECK(!base::ContainsKey(doomed_reports_, report)); |
133 size_t erased = reports_.erase(report); | 148 RemoveReportInternal(report); |
134 DCHECK_EQ(1u, erased); | |
135 } | 149 } |
136 } | 150 } |
137 | 151 |
138 context_->NotifyCacheUpdated(); | 152 context_->NotifyCacheUpdated(); |
139 } | 153 } |
140 | 154 |
141 void RemoveAllReports() override { | 155 void RemoveAllReports(ReportingReport::Outcome outcome) override { |
142 std::vector<std::unordered_map<const ReportingReport*, | 156 std::vector<const ReportingReport*> reports_to_remove; |
143 std::unique_ptr<ReportingReport>>::iterator> | |
144 reports_to_remove; | |
145 for (auto it = reports_.begin(); it != reports_.end(); ++it) { | 157 for (auto it = reports_.begin(); it != reports_.end(); ++it) { |
146 ReportingReport* report = it->second.get(); | 158 ReportingReport* report = it->second.get(); |
| 159 report->outcome = outcome; |
147 if (!base::ContainsKey(pending_reports_, report)) | 160 if (!base::ContainsKey(pending_reports_, report)) |
148 reports_to_remove.push_back(it); | 161 reports_to_remove.push_back(report); |
149 else | 162 else |
150 doomed_reports_.insert(report); | 163 doomed_reports_.insert(report); |
151 } | 164 } |
152 | 165 |
153 for (auto& it : reports_to_remove) | 166 for (const ReportingReport* report : reports_to_remove) |
154 reports_.erase(it); | 167 RemoveReportInternal(report); |
155 | 168 |
156 context_->NotifyCacheUpdated(); | 169 context_->NotifyCacheUpdated(); |
157 } | 170 } |
158 | 171 |
159 void GetClients( | 172 void GetClients( |
160 std::vector<const ReportingClient*>* clients_out) const override { | 173 std::vector<const ReportingClient*>* clients_out) const override { |
161 clients_out->clear(); | 174 clients_out->clear(); |
162 for (const auto& it : clients_) | 175 for (const auto& it : clients_) |
163 for (const auto& endpoint_and_client : it.second) | 176 for (const auto& endpoint_and_client : it.second) |
164 clients_out->push_back(endpoint_and_client.second.get()); | 177 clients_out->push_back(endpoint_and_client.second.get()); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 // References but does not own all clients with includeSubdomains set, keyed | 320 // References but does not own all clients with includeSubdomains set, keyed |
308 // by domain name. | 321 // by domain name. |
309 std::unordered_map<std::string, std::unordered_set<const ReportingClient*>> | 322 std::unordered_map<std::string, std::unordered_set<const ReportingClient*>> |
310 wildcard_clients_; | 323 wildcard_clients_; |
311 | 324 |
312 // The time that each client has last been used. | 325 // The time that each client has last been used. |
313 std::unordered_map<const ReportingClient*, base::TimeTicks> client_last_used_; | 326 std::unordered_map<const ReportingClient*, base::TimeTicks> client_last_used_; |
314 | 327 |
315 base::TickClock* tick_clock() { return context_->tick_clock(); } | 328 base::TickClock* tick_clock() { return context_->tick_clock(); } |
316 | 329 |
| 330 void RemoveReportInternal(const ReportingReport* report) { |
| 331 reports_[report]->RecordOutcome(tick_clock()->NowTicks()); |
| 332 size_t erased = reports_.erase(report); |
| 333 DCHECK_EQ(1u, erased); |
| 334 } |
| 335 |
317 const ReportingReport* FindReportToEvict() const { | 336 const ReportingReport* FindReportToEvict() const { |
318 const ReportingReport* earliest_queued = nullptr; | 337 const ReportingReport* earliest_queued = nullptr; |
319 | 338 |
320 for (const auto& it : reports_) { | 339 for (const auto& it : reports_) { |
321 const ReportingReport* report = it.first; | 340 const ReportingReport* report = it.first; |
322 if (base::ContainsKey(pending_reports_, report)) | 341 if (base::ContainsKey(pending_reports_, report)) |
323 continue; | 342 continue; |
324 if (!earliest_queued || report->queued < earliest_queued->queued) { | 343 if (!earliest_queued || report->queued < earliest_queued->queued) { |
325 earliest_queued = report; | 344 earliest_queued = report; |
326 } | 345 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 | 462 |
444 // static | 463 // static |
445 std::unique_ptr<ReportingCache> ReportingCache::Create( | 464 std::unique_ptr<ReportingCache> ReportingCache::Create( |
446 ReportingContext* context) { | 465 ReportingContext* context) { |
447 return base::MakeUnique<ReportingCacheImpl>(context); | 466 return base::MakeUnique<ReportingCacheImpl>(context); |
448 } | 467 } |
449 | 468 |
450 ReportingCache::~ReportingCache() {} | 469 ReportingCache::~ReportingCache() {} |
451 | 470 |
452 } // namespace net | 471 } // namespace net |
OLD | NEW |