Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(425)

Side by Side Diff: net/reporting/reporting_cache.cc

Issue 2851603002: Reporting: Cap number of clients in cache. (Closed)
Patch Set: Make requested change. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/reporting/reporting_cache.h ('k') | net/reporting/reporting_cache_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/time/tick_clock.h"
15 #include "base/time/time.h" 16 #include "base/time/time.h"
16 #include "net/reporting/reporting_client.h" 17 #include "net/reporting/reporting_client.h"
17 #include "net/reporting/reporting_context.h" 18 #include "net/reporting/reporting_context.h"
18 #include "net/reporting/reporting_report.h" 19 #include "net/reporting/reporting_report.h"
19 #include "url/gurl.h" 20 #include "url/gurl.h"
20 21
21 namespace net { 22 namespace net {
22 23
23 namespace { 24 namespace {
24 25
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 } 185 }
185 } 186 }
186 187
187 void ReportingCache::SetClient(const url::Origin& origin, 188 void ReportingCache::SetClient(const url::Origin& origin,
188 const GURL& endpoint, 189 const GURL& endpoint,
189 ReportingClient::Subdomains subdomains, 190 ReportingClient::Subdomains subdomains,
190 const std::string& group, 191 const std::string& group,
191 base::TimeTicks expires) { 192 base::TimeTicks expires) {
192 DCHECK(endpoint.SchemeIsCryptographic()); 193 DCHECK(endpoint.SchemeIsCryptographic());
193 194
194 // Since |subdomains| may differ from a previous call to SetClient for this 195 base::TimeTicks last_used = tick_clock()->NowTicks();
195 // origin and endpoint, the cache needs to remove and re-add the client to the 196
196 // index of wildcard clients, if applicable. 197 const ReportingClient* old_client =
197 if (base::ContainsKey(clients_, origin) && 198 GetClientByOriginAndEndpoint(origin, endpoint);
198 base::ContainsKey(clients_[origin], endpoint)) { 199 if (old_client) {
199 MaybeRemoveWildcardClient(clients_[origin][endpoint].get()); 200 last_used = client_last_used_[old_client];
201 RemoveClient(old_client);
200 } 202 }
201 203
202 clients_[origin][endpoint] = base::MakeUnique<ReportingClient>( 204 AddClient(base::MakeUnique<ReportingClient>(origin, endpoint, subdomains,
203 origin, endpoint, subdomains, group, expires); 205 group, expires),
206 last_used);
204 207
205 MaybeAddWildcardClient(clients_[origin][endpoint].get()); 208 if (client_last_used_.size() > context_->policy().max_client_count) {
209 // There should only ever be one extra client, added above.
210 DCHECK_EQ(context_->policy().max_client_count + 1,
211 client_last_used_.size());
212 // And that shouldn't happen if it was replaced, not added.
213 DCHECK(!old_client);
214 const ReportingClient* to_evict =
215 FindClientToEvict(tick_clock()->NowTicks());
216 DCHECK(to_evict);
217 RemoveClient(to_evict);
218 }
206 219
207 context_->NotifyCacheUpdated(); 220 context_->NotifyCacheUpdated();
208 } 221 }
209 222
223 void ReportingCache::MarkClientUsed(const url::Origin& origin,
224 const GURL& endpoint) {
225 const ReportingClient* client =
226 GetClientByOriginAndEndpoint(origin, endpoint);
227 DCHECK(client);
228 client_last_used_[client] = tick_clock()->NowTicks();
229 }
230
210 void ReportingCache::RemoveClients( 231 void ReportingCache::RemoveClients(
211 const std::vector<const ReportingClient*>& clients_to_remove) { 232 const std::vector<const ReportingClient*>& clients_to_remove) {
212 for (const ReportingClient* client : clients_to_remove) { 233 for (const ReportingClient* client : clients_to_remove)
213 MaybeRemoveWildcardClient(client); 234 RemoveClient(client);
214 size_t erased = clients_[client->origin].erase(client->endpoint);
215 DCHECK_EQ(1u, erased);
216 }
217 235
218 context_->NotifyCacheUpdated(); 236 context_->NotifyCacheUpdated();
219 } 237 }
220 238
221 void ReportingCache::RemoveClientForOriginAndEndpoint(const url::Origin& origin, 239 void ReportingCache::RemoveClientForOriginAndEndpoint(const url::Origin& origin,
222 const GURL& endpoint) { 240 const GURL& endpoint) {
223 MaybeRemoveWildcardClient(clients_[origin][endpoint].get()); 241 const ReportingClient* client =
224 size_t erased = clients_[origin].erase(endpoint); 242 GetClientByOriginAndEndpoint(origin, endpoint);
225 DCHECK_EQ(1u, erased); 243 RemoveClient(client);
226 244
227 context_->NotifyCacheUpdated(); 245 context_->NotifyCacheUpdated();
228 } 246 }
229 247
230 void ReportingCache::RemoveClientsForEndpoint(const GURL& endpoint) { 248 void ReportingCache::RemoveClientsForEndpoint(const GURL& endpoint) {
231 for (auto& origin_and_endpoints : clients_) { 249 std::vector<const ReportingClient*> clients_to_remove;
232 if (base::ContainsKey(origin_and_endpoints.second, endpoint)) {
233 MaybeRemoveWildcardClient(origin_and_endpoints.second[endpoint].get());
234 origin_and_endpoints.second.erase(endpoint);
235 }
236 }
237 250
238 context_->NotifyCacheUpdated(); 251 for (auto& origin_and_endpoints : clients_)
252 if (base::ContainsKey(origin_and_endpoints.second, endpoint))
253 clients_to_remove.push_back(origin_and_endpoints.second[endpoint].get());
254
255 for (const ReportingClient* client : clients_to_remove)
256 RemoveClient(client);
257
258 if (!clients_to_remove.empty())
259 context_->NotifyCacheUpdated();
239 } 260 }
240 261
241 void ReportingCache::RemoveAllClients() { 262 void ReportingCache::RemoveAllClients() {
242 clients_.clear(); 263 clients_.clear();
243 wildcard_clients_.clear(); 264 wildcard_clients_.clear();
265 client_last_used_.clear();
244 266
245 context_->NotifyCacheUpdated(); 267 context_->NotifyCacheUpdated();
246 } 268 }
247 269
248 const ReportingReport* ReportingCache::FindReportToEvict() const { 270 const ReportingReport* ReportingCache::FindReportToEvict() const {
249 const ReportingReport* earliest_queued = nullptr; 271 const ReportingReport* earliest_queued = nullptr;
250 272
251 for (const auto& it : reports_) { 273 for (const auto& it : reports_) {
252 const ReportingReport* report = it.first; 274 const ReportingReport* report = it.first;
253 if (base::ContainsKey(pending_reports_, report)) 275 if (base::ContainsKey(pending_reports_, report))
254 continue; 276 continue;
255 if (!earliest_queued || report->queued < earliest_queued->queued) { 277 if (!earliest_queued || report->queued < earliest_queued->queued) {
256 earliest_queued = report; 278 earliest_queued = report;
257 } 279 }
258 } 280 }
259 281
260 return earliest_queued; 282 return earliest_queued;
261 } 283 }
262 284
263 void ReportingCache::MaybeAddWildcardClient(const ReportingClient* client) { 285 void ReportingCache::AddClient(std::unique_ptr<ReportingClient> client,
264 if (client->subdomains != ReportingClient::Subdomains::INCLUDE) 286 base::TimeTicks last_used) {
265 return; 287 DCHECK(client);
266 288
267 const std::string& domain = client->origin.host(); 289 url::Origin origin = client->origin;
268 auto inserted = wildcard_clients_[domain].insert(client); 290 GURL endpoint = client->endpoint;
269 DCHECK(inserted.second); 291
292 auto inserted_last_used =
293 client_last_used_.insert(std::make_pair(client.get(), last_used));
294 DCHECK(inserted_last_used.second);
295
296 if (client->subdomains == ReportingClient::Subdomains::INCLUDE) {
297 const std::string& domain = origin.host();
298 auto inserted_wildcard_client =
299 wildcard_clients_[domain].insert(client.get());
300 DCHECK(inserted_wildcard_client.second);
301 }
302
303 auto inserted_client =
304 clients_[origin].insert(std::make_pair(endpoint, std::move(client)));
305 DCHECK(inserted_client.second);
270 } 306 }
271 307
272 void ReportingCache::MaybeRemoveWildcardClient(const ReportingClient* client) { 308 void ReportingCache::RemoveClient(const ReportingClient* client) {
273 if (client->subdomains != ReportingClient::Subdomains::INCLUDE) 309 DCHECK(client);
274 return;
275 310
276 const std::string& domain = client->origin.host(); 311 url::Origin origin = client->origin;
277 size_t erased = wildcard_clients_[domain].erase(client); 312 GURL endpoint = client->endpoint;
278 DCHECK_EQ(1u, erased); 313
314 if (client->subdomains == ReportingClient::Subdomains::INCLUDE) {
315 const std::string& domain = origin.host();
316 size_t erased_wildcard_client = wildcard_clients_[domain].erase(client);
317 DCHECK_EQ(1u, erased_wildcard_client);
318 if (wildcard_clients_[domain].empty()) {
319 size_t erased_wildcard_domain = wildcard_clients_.erase(domain);
320 DCHECK_EQ(1u, erased_wildcard_domain);
321 }
322 }
323
324 size_t erased_last_used = client_last_used_.erase(client);
325 DCHECK_EQ(1u, erased_last_used);
326
327 size_t erased_endpoint = clients_[origin].erase(endpoint);
328 DCHECK_EQ(1u, erased_endpoint);
329 if (clients_[origin].empty()) {
330 size_t erased_origin = clients_.erase(origin);
331 DCHECK_EQ(1u, erased_origin);
332 }
333 }
334
335 const ReportingClient* ReportingCache::GetClientByOriginAndEndpoint(
336 const url::Origin& origin,
337 const GURL& endpoint) const {
338 const auto& origin_it = clients_.find(origin);
339 if (origin_it == clients_.end())
340 return nullptr;
341
342 const auto& endpoint_it = origin_it->second.find(endpoint);
343 if (endpoint_it == origin_it->second.end())
344 return nullptr;
345
346 return endpoint_it->second.get();
279 } 347 }
280 348
281 void ReportingCache::GetWildcardClientsForDomainAndGroup( 349 void ReportingCache::GetWildcardClientsForDomainAndGroup(
282 const std::string& domain, 350 const std::string& domain,
283 const std::string& group, 351 const std::string& group,
284 std::vector<const ReportingClient*>* clients_out) const { 352 std::vector<const ReportingClient*>* clients_out) const {
285 clients_out->clear(); 353 clients_out->clear();
286 354
287 auto it = wildcard_clients_.find(domain); 355 auto it = wildcard_clients_.find(domain);
288 if (it == wildcard_clients_.end()) 356 if (it == wildcard_clients_.end())
289 return; 357 return;
290 358
291 for (const ReportingClient* client : it->second) { 359 for (const ReportingClient* client : it->second) {
292 DCHECK_EQ(ReportingClient::Subdomains::INCLUDE, client->subdomains); 360 DCHECK_EQ(ReportingClient::Subdomains::INCLUDE, client->subdomains);
293 if (client->group == group) 361 if (client->group == group)
294 clients_out->push_back(client); 362 clients_out->push_back(client);
295 } 363 }
296 } 364 }
297 365
366 const ReportingClient* ReportingCache::FindClientToEvict(
367 base::TimeTicks now) const {
368 DCHECK(!client_last_used_.empty());
369
370 const ReportingClient* earliest_used = nullptr;
371 base::TimeTicks earliest_used_last_used;
372 const ReportingClient* earliest_expired = nullptr;
373
374 for (const auto& it : client_last_used_) {
375 const ReportingClient* client = it.first;
376 base::TimeTicks client_last_used = it.second;
377 if (earliest_used == nullptr ||
378 client_last_used < earliest_used_last_used) {
379 earliest_used = client;
380 earliest_used_last_used = client_last_used;
381 }
382 if (earliest_expired == nullptr ||
383 client->expires < earliest_expired->expires) {
384 earliest_expired = client;
385 }
386 }
387
388 // If there are expired clients, return the earliest-expired.
389 if (earliest_expired->expires < now)
390 return earliest_expired;
391 else
392 return earliest_used;
393 }
394
395 base::TickClock* ReportingCache::tick_clock() {
396 return context_->tick_clock();
397 }
398
298 } // namespace net 399 } // namespace net
OLDNEW
« no previous file with comments | « net/reporting/reporting_cache.h ('k') | net/reporting/reporting_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698