| 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 30 matching lines...) Expand all Loading... |
| 41 | 41 |
| 42 return domain.substr(dot_pos + 1); | 42 return domain.substr(dot_pos + 1); |
| 43 } | 43 } |
| 44 | 44 |
| 45 } // namespace | 45 } // namespace |
| 46 | 46 |
| 47 ReportingCache::ReportingCache(ReportingContext* context) : context_(context) { | 47 ReportingCache::ReportingCache(ReportingContext* context) : context_(context) { |
| 48 DCHECK(context_); | 48 DCHECK(context_); |
| 49 } | 49 } |
| 50 | 50 |
| 51 ReportingCache::~ReportingCache() {} | 51 ReportingCache::~ReportingCache() { |
| 52 base::TimeTicks now = tick_clock()->NowTicks(); |
| 53 |
| 54 // Mark all undoomed reports as erased at shutdown, and record outcomes of |
| 55 // all remaining reports (doomed or not). |
| 56 for (auto it = reports_.begin(); it != reports_.end(); ++it) { |
| 57 ReportingReport* report = it->second.get(); |
| 58 if (!base::ContainsKey(doomed_reports_, report)) |
| 59 report->outcome = ReportingReport::Outcome::ERASED_REPORTING_SHUT_DOWN; |
| 60 report->RecordOutcome(now); |
| 61 } |
| 62 |
| 63 reports_.clear(); |
| 64 } |
| 52 | 65 |
| 53 void ReportingCache::AddReport(const GURL& url, | 66 void ReportingCache::AddReport(const GURL& url, |
| 54 const std::string& group, | 67 const std::string& group, |
| 55 const std::string& type, | 68 const std::string& type, |
| 56 std::unique_ptr<const base::Value> body, | 69 std::unique_ptr<const base::Value> body, |
| 57 base::TimeTicks queued, | 70 base::TimeTicks queued, |
| 58 int attempts) { | 71 int attempts) { |
| 59 auto report = base::MakeUnique<ReportingReport>( | 72 auto report = base::MakeUnique<ReportingReport>( |
| 60 url, group, type, std::move(body), queued, attempts); | 73 url, group, type, std::move(body), queued, attempts); |
| 61 | 74 |
| 62 auto inserted = | 75 auto inserted = |
| 63 reports_.insert(std::make_pair(report.get(), std::move(report))); | 76 reports_.insert(std::make_pair(report.get(), std::move(report))); |
| 64 DCHECK(inserted.second); | 77 DCHECK(inserted.second); |
| 65 | 78 |
| 66 if (reports_.size() > context_->policy().max_report_count) { | 79 if (reports_.size() > context_->policy().max_report_count) { |
| 67 // There should be at most one extra report (the one added above). | 80 // There should be at most one extra report (the one added above). |
| 68 DCHECK_EQ(context_->policy().max_report_count + 1, reports_.size()); | 81 DCHECK_EQ(context_->policy().max_report_count + 1, reports_.size()); |
| 69 const ReportingReport* to_evict = FindReportToEvict(); | 82 const ReportingReport* to_evict = FindReportToEvict(); |
| 70 DCHECK_NE(nullptr, to_evict); | 83 DCHECK_NE(nullptr, to_evict); |
| 71 // The newly-added report isn't pending, so even if all other reports are | 84 // The newly-added report isn't pending, so even if all other reports are |
| 72 // pending, the cache should have a report to evict. | 85 // pending, the cache should have a report to evict. |
| 73 DCHECK(!base::ContainsKey(pending_reports_, to_evict)); | 86 DCHECK(!base::ContainsKey(pending_reports_, to_evict)); |
| 74 size_t erased = reports_.erase(to_evict); | 87 reports_[to_evict]->outcome = ReportingReport::Outcome::ERASED_EVICTED; |
| 75 DCHECK_EQ(1u, erased); | 88 RemoveReportInternal(to_evict); |
| 76 } | 89 } |
| 77 | 90 |
| 78 context_->NotifyCacheUpdated(); | 91 context_->NotifyCacheUpdated(); |
| 79 } | 92 } |
| 80 | 93 |
| 81 void ReportingCache::GetReports( | 94 void ReportingCache::GetReports( |
| 82 std::vector<const ReportingReport*>* reports_out) const { | 95 std::vector<const ReportingReport*>* reports_out) const { |
| 83 reports_out->clear(); | 96 reports_out->clear(); |
| 84 for (const auto& it : reports_) { | 97 for (const auto& it : reports_) { |
| 85 if (!base::ContainsKey(doomed_reports_, it.first)) | 98 if (!base::ContainsKey(doomed_reports_, it.first)) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 101 | 114 |
| 102 for (const ReportingReport* report : reports) { | 115 for (const ReportingReport* report : reports) { |
| 103 size_t erased = pending_reports_.erase(report); | 116 size_t erased = pending_reports_.erase(report); |
| 104 DCHECK_EQ(1u, erased); | 117 DCHECK_EQ(1u, erased); |
| 105 if (base::ContainsKey(doomed_reports_, report)) { | 118 if (base::ContainsKey(doomed_reports_, report)) { |
| 106 reports_to_remove.push_back(report); | 119 reports_to_remove.push_back(report); |
| 107 doomed_reports_.erase(report); | 120 doomed_reports_.erase(report); |
| 108 } | 121 } |
| 109 } | 122 } |
| 110 | 123 |
| 111 RemoveReports(reports_to_remove); | 124 for (const ReportingReport* report : reports_to_remove) |
| 125 RemoveReportInternal(report); |
| 112 } | 126 } |
| 113 | 127 |
| 114 void ReportingCache::IncrementReportsAttempts( | 128 void ReportingCache::IncrementReportsAttempts( |
| 115 const std::vector<const ReportingReport*>& reports) { | 129 const std::vector<const ReportingReport*>& reports) { |
| 116 for (const ReportingReport* report : reports) { | 130 for (const ReportingReport* report : reports) { |
| 117 DCHECK(base::ContainsKey(reports_, report)); | 131 DCHECK(base::ContainsKey(reports_, report)); |
| 118 reports_[report]->attempts++; | 132 reports_[report]->attempts++; |
| 119 } | 133 } |
| 120 | 134 |
| 121 context_->NotifyCacheUpdated(); | 135 context_->NotifyCacheUpdated(); |
| 122 } | 136 } |
| 123 | 137 |
| 124 void ReportingCache::RemoveReports( | 138 void ReportingCache::RemoveReports( |
| 125 const std::vector<const ReportingReport*>& reports) { | 139 const std::vector<const ReportingReport*>& reports, |
| 140 ReportingReport::Outcome outcome) { |
| 126 for (const ReportingReport* report : reports) { | 141 for (const ReportingReport* report : reports) { |
| 142 reports_[report]->outcome = outcome; |
| 127 if (base::ContainsKey(pending_reports_, report)) { | 143 if (base::ContainsKey(pending_reports_, report)) { |
| 128 doomed_reports_.insert(report); | 144 doomed_reports_.insert(report); |
| 129 } else { | 145 } else { |
| 130 DCHECK(!base::ContainsKey(doomed_reports_, report)); | 146 DCHECK(!base::ContainsKey(doomed_reports_, report)); |
| 131 size_t erased = reports_.erase(report); | 147 RemoveReportInternal(report); |
| 132 DCHECK_EQ(1u, erased); | |
| 133 } | 148 } |
| 134 } | 149 } |
| 135 | 150 |
| 136 context_->NotifyCacheUpdated(); | 151 context_->NotifyCacheUpdated(); |
| 137 } | 152 } |
| 138 | 153 |
| 139 void ReportingCache::RemoveAllReports() { | 154 void ReportingCache::RemoveAllReports(ReportingReport::Outcome outcome) { |
| 140 std::vector<std::unordered_map<const ReportingReport*, | 155 std::vector<const ReportingReport*> reports_to_remove; |
| 141 std::unique_ptr<ReportingReport>>::iterator> | |
| 142 reports_to_remove; | |
| 143 for (auto it = reports_.begin(); it != reports_.end(); ++it) { | 156 for (auto it = reports_.begin(); it != reports_.end(); ++it) { |
| 144 ReportingReport* report = it->second.get(); | 157 ReportingReport* report = it->second.get(); |
| 158 report->outcome = outcome; |
| 145 if (!base::ContainsKey(pending_reports_, report)) | 159 if (!base::ContainsKey(pending_reports_, report)) |
| 146 reports_to_remove.push_back(it); | 160 reports_to_remove.push_back(report); |
| 147 else | 161 else |
| 148 doomed_reports_.insert(report); | 162 doomed_reports_.insert(report); |
| 149 } | 163 } |
| 150 | 164 |
| 151 for (auto& it : reports_to_remove) | 165 for (const ReportingReport* report : reports_to_remove) |
| 152 reports_.erase(it); | 166 RemoveReportInternal(report); |
| 153 | 167 |
| 154 context_->NotifyCacheUpdated(); | 168 context_->NotifyCacheUpdated(); |
| 155 } | 169 } |
| 156 | 170 |
| 157 void ReportingCache::GetClients( | 171 void ReportingCache::GetClients( |
| 158 std::vector<const ReportingClient*>* clients_out) const { | 172 std::vector<const ReportingClient*>* clients_out) const { |
| 159 clients_out->clear(); | 173 clients_out->clear(); |
| 160 for (const auto& it : clients_) | 174 for (const auto& it : clients_) |
| 161 for (const auto& endpoint_and_client : it.second) | 175 for (const auto& endpoint_and_client : it.second) |
| 162 clients_out->push_back(endpoint_and_client.second.get()); | 176 clients_out->push_back(endpoint_and_client.second.get()); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 } | 275 } |
| 262 | 276 |
| 263 void ReportingCache::RemoveAllClients() { | 277 void ReportingCache::RemoveAllClients() { |
| 264 clients_.clear(); | 278 clients_.clear(); |
| 265 wildcard_clients_.clear(); | 279 wildcard_clients_.clear(); |
| 266 client_last_used_.clear(); | 280 client_last_used_.clear(); |
| 267 | 281 |
| 268 context_->NotifyCacheUpdated(); | 282 context_->NotifyCacheUpdated(); |
| 269 } | 283 } |
| 270 | 284 |
| 285 void ReportingCache::RemoveReportInternal(const ReportingReport* report) { |
| 286 reports_[report]->RecordOutcome(tick_clock()->NowTicks()); |
| 287 size_t erased = reports_.erase(report); |
| 288 DCHECK_EQ(1u, erased); |
| 289 } |
| 290 |
| 271 const ReportingReport* ReportingCache::FindReportToEvict() const { | 291 const ReportingReport* ReportingCache::FindReportToEvict() const { |
| 272 const ReportingReport* earliest_queued = nullptr; | 292 const ReportingReport* earliest_queued = nullptr; |
| 273 | 293 |
| 274 for (const auto& it : reports_) { | 294 for (const auto& it : reports_) { |
| 275 const ReportingReport* report = it.first; | 295 const ReportingReport* report = it.first; |
| 276 if (base::ContainsKey(pending_reports_, report)) | 296 if (base::ContainsKey(pending_reports_, report)) |
| 277 continue; | 297 continue; |
| 278 if (!earliest_queued || report->queued < earliest_queued->queued) { | 298 if (!earliest_queued || report->queued < earliest_queued->queued) { |
| 279 earliest_queued = report; | 299 earliest_queued = report; |
| 280 } | 300 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 return earliest_expired; | 411 return earliest_expired; |
| 392 else | 412 else |
| 393 return earliest_used; | 413 return earliest_used; |
| 394 } | 414 } |
| 395 | 415 |
| 396 base::TickClock* ReportingCache::tick_clock() { | 416 base::TickClock* ReportingCache::tick_clock() { |
| 397 return context_->tick_clock(); | 417 return context_->tick_clock(); |
| 398 } | 418 } |
| 399 | 419 |
| 400 } // namespace net | 420 } // namespace net |
| OLD | NEW |