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

Side by Side Diff: net/cookies/cookie_monster.cc

Issue 1052373003: Add Finch experiment to cookie monster. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Remove dcheck and rebase against top of tree. Created 5 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/cookies/cookie_monster.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // Portions of this code based on Mozilla: 5 // Portions of this code based on Mozilla:
6 // (netwerk/cookie/src/nsCookieService.cpp) 6 // (netwerk/cookie/src/nsCookieService.cpp)
7 /* ***** BEGIN LICENSE BLOCK ***** 7 /* ***** BEGIN LICENSE BLOCK *****
8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
9 * 9 *
10 * The contents of this file are subject to the Mozilla Public License Version 10 * The contents of this file are subject to the Mozilla Public License Version
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 #include <functional> 48 #include <functional>
49 #include <set> 49 #include <set>
50 50
51 #include "base/basictypes.h" 51 #include "base/basictypes.h"
52 #include "base/bind.h" 52 #include "base/bind.h"
53 #include "base/callback.h" 53 #include "base/callback.h"
54 #include "base/logging.h" 54 #include "base/logging.h"
55 #include "base/memory/scoped_ptr.h" 55 #include "base/memory/scoped_ptr.h"
56 #include "base/message_loop/message_loop.h" 56 #include "base/message_loop/message_loop.h"
57 #include "base/message_loop/message_loop_proxy.h" 57 #include "base/message_loop/message_loop_proxy.h"
58 #include "base/metrics/field_trial.h"
58 #include "base/metrics/histogram.h" 59 #include "base/metrics/histogram.h"
59 #include "base/profiler/scoped_tracker.h" 60 #include "base/profiler/scoped_tracker.h"
60 #include "base/strings/string_util.h" 61 #include "base/strings/string_util.h"
61 #include "base/strings/stringprintf.h" 62 #include "base/strings/stringprintf.h"
62 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 63 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
63 #include "net/cookies/canonical_cookie.h" 64 #include "net/cookies/canonical_cookie.h"
64 #include "net/cookies/cookie_util.h" 65 #include "net/cookies/cookie_util.h"
65 #include "net/cookies/parsed_cookie.h" 66 #include "net/cookies/parsed_cookie.h"
66 67
67 using base::Time; 68 using base::Time;
68 using base::TimeDelta; 69 using base::TimeDelta;
69 using base::TimeTicks; 70 using base::TimeTicks;
70 71
71 // In steady state, most cookie requests can be satisfied by the in memory 72 // In steady state, most cookie requests can be satisfied by the in memory
72 // cookie monster store. However, if a request comes in during the initial 73 // cookie monster store. If the cookie request cannot be satisfied by the in
73 // cookie load, it must be delayed until that load completes. That is done by 74 // memory store, the relevant cookies must be fetched from the persistent
74 // queueing it on CookieMonster::tasks_pending_ and running it when notification 75 // store. The task is queued in CookieMonster::tasks_pending_ if it requires
75 // of cookie load completion is received via CookieMonster::OnLoaded. This 76 // all cookies to be loaded from the backend, or tasks_pending_for_key_ if it
76 // callback is passed to the persistent store from CookieMonster::InitStore(), 77 // only requires all cookies associated with an eTLD+1.
77 // which is called on the first operation invoked on the CookieMonster.
78 // 78 //
79 // On the browser critical paths (e.g. for loading initial web pages in a 79 // On the browser critical paths (e.g. for loading initial web pages in a
80 // session restore) it may take too long to wait for the full load. If a cookie 80 // session restore) it may take too long to wait for the full load. If a cookie
81 // request is for a specific URL, DoCookieTaskForURL is called, which triggers a 81 // request is for a specific URL, DoCookieTaskForURL is called, which triggers a
82 // priority load if the key is not loaded yet by calling PersistentCookieStore 82 // priority load if the key is not loaded yet by calling PersistentCookieStore
83 // :: LoadCookiesForKey. The request is queued in 83 // :: LoadCookiesForKey. The request is queued in
84 // CookieMonster::tasks_pending_for_key_ and executed upon receiving 84 // CookieMonster::tasks_pending_for_key_ and executed upon receiving
85 // notification of key load completion via CookieMonster::OnKeyLoaded(). If 85 // notification of key load completion via CookieMonster::OnKeyLoaded(). If
86 // multiple requests for the same eTLD+1 are received before key load 86 // multiple requests for the same eTLD+1 are received before key load
87 // completion, only the first request calls 87 // completion, only the first request calls
88 // PersistentCookieStore::LoadCookiesForKey, all subsequent requests are queued 88 // PersistentCookieStore::LoadCookiesForKey, all subsequent requests are queued
89 // in CookieMonster::tasks_pending_for_key_ and executed upon receiving 89 // in CookieMonster::tasks_pending_for_key_ and executed upon receiving
90 // notification of key load completion triggered by the first request for the 90 // notification of key load completion triggered by the first request for the
91 // same eTLD+1. 91 // same eTLD+1.
92 92
93 static const int kMinutesInTenYears = 10 * 365 * 24 * 60; 93 static const int kMinutesInTenYears = 10 * 365 * 24 * 60;
94 94
95 namespace {
96
97 const char kFetchWhenNecessaryName[] = "FetchWhenNecessary";
98 const char kAlwaysFetchName[] = "AlwaysFetch";
99 const char kCookieMonsterFetchStrategyName[] = "CookieMonsterFetchStrategy";
100
101 } // namespace
102
95 namespace net { 103 namespace net {
96 104
97 // See comments at declaration of these variables in cookie_monster.h 105 // See comments at declaration of these variables in cookie_monster.h
98 // for details. 106 // for details.
99 const size_t CookieMonster::kDomainMaxCookies = 180; 107 const size_t CookieMonster::kDomainMaxCookies = 180;
100 const size_t CookieMonster::kDomainPurgeCookies = 30; 108 const size_t CookieMonster::kDomainPurgeCookies = 30;
101 const size_t CookieMonster::kMaxCookies = 3300; 109 const size_t CookieMonster::kMaxCookies = 3300;
102 const size_t CookieMonster::kPurgeCookies = 300; 110 const size_t CookieMonster::kPurgeCookies = 300;
103 111
104 const size_t CookieMonster::kDomainCookiesQuotaLow = 30; 112 const size_t CookieMonster::kDomainCookiesQuotaLow = 30;
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 const CanonicalCookie& cookie, 329 const CanonicalCookie& cookie,
322 bool removed) { 330 bool removed) {
323 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed)); 331 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed));
324 } 332 }
325 333
326 } // namespace 334 } // namespace
327 335
328 CookieMonster::CookieMonster(PersistentCookieStore* store, 336 CookieMonster::CookieMonster(PersistentCookieStore* store,
329 CookieMonsterDelegate* delegate) 337 CookieMonsterDelegate* delegate)
330 : initialized_(false), 338 : initialized_(false),
331 loaded_(false), 339 started_fetching_all_cookies_(false),
340 finished_fetching_all_cookies_(false),
341 fetch_strategy_(kUnknownFetch),
332 store_(store), 342 store_(store),
333 last_access_threshold_( 343 last_access_threshold_(
334 TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)), 344 TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)),
335 delegate_(delegate), 345 delegate_(delegate),
336 last_statistic_record_time_(Time::Now()), 346 last_statistic_record_time_(Time::Now()),
337 keep_expired_cookies_(false), 347 keep_expired_cookies_(false),
338 persist_session_cookies_(false) { 348 persist_session_cookies_(false) {
339 InitializeHistograms(); 349 InitializeHistograms();
340 SetDefaultCookieableSchemes(); 350 SetDefaultCookieableSchemes();
341 } 351 }
342 352
343 CookieMonster::CookieMonster(PersistentCookieStore* store, 353 CookieMonster::CookieMonster(PersistentCookieStore* store,
344 CookieMonsterDelegate* delegate, 354 CookieMonsterDelegate* delegate,
345 int last_access_threshold_milliseconds) 355 int last_access_threshold_milliseconds)
346 : initialized_(false), 356 : initialized_(false),
347 loaded_(false), 357 started_fetching_all_cookies_(false),
358 finished_fetching_all_cookies_(false),
359 fetch_strategy_(kUnknownFetch),
348 store_(store), 360 store_(store),
349 last_access_threshold_(base::TimeDelta::FromMilliseconds( 361 last_access_threshold_(base::TimeDelta::FromMilliseconds(
350 last_access_threshold_milliseconds)), 362 last_access_threshold_milliseconds)),
351 delegate_(delegate), 363 delegate_(delegate),
352 last_statistic_record_time_(base::Time::Now()), 364 last_statistic_record_time_(base::Time::Now()),
353 keep_expired_cookies_(false), 365 keep_expired_cookies_(false),
354 persist_session_cookies_(false) { 366 persist_session_cookies_(false) {
355 InitializeHistograms(); 367 InitializeHistograms();
356 SetDefaultCookieableSchemes(); 368 SetDefaultCookieableSchemes();
357 } 369 }
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 scoped_refptr<DeleteSessionCookiesTask> task = 1091 scoped_refptr<DeleteSessionCookiesTask> task =
1080 new DeleteSessionCookiesTask(this, callback); 1092 new DeleteSessionCookiesTask(this, callback);
1081 1093
1082 DoCookieTask(task); 1094 DoCookieTask(task);
1083 } 1095 }
1084 1096
1085 void CookieMonster::DoCookieTask( 1097 void CookieMonster::DoCookieTask(
1086 const scoped_refptr<CookieMonsterTask>& task_item) { 1098 const scoped_refptr<CookieMonsterTask>& task_item) {
1087 { 1099 {
1088 base::AutoLock autolock(lock_); 1100 base::AutoLock autolock(lock_);
1089 InitIfNecessary(); 1101 MarkCookieStoreAsInitialized();
1090 if (!loaded_) { 1102 FetchAllCookiesIfNecessary();
1103 if (!finished_fetching_all_cookies_ && store_.get()) {
1091 tasks_pending_.push(task_item); 1104 tasks_pending_.push(task_item);
1092 return; 1105 return;
1093 } 1106 }
1094 } 1107 }
1095 1108
1096 task_item->Run(); 1109 task_item->Run();
1097 } 1110 }
1098 1111
1099 void CookieMonster::DoCookieTaskForURL( 1112 void CookieMonster::DoCookieTaskForURL(
1100 const scoped_refptr<CookieMonsterTask>& task_item, 1113 const scoped_refptr<CookieMonsterTask>& task_item,
1101 const GURL& url) { 1114 const GURL& url) {
1102 { 1115 {
1103 base::AutoLock autolock(lock_); 1116 base::AutoLock autolock(lock_);
1104 InitIfNecessary(); 1117 MarkCookieStoreAsInitialized();
1118 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1119 FetchAllCookiesIfNecessary();
1105 // If cookies for the requested domain key (eTLD+1) have been loaded from DB 1120 // If cookies for the requested domain key (eTLD+1) have been loaded from DB
1106 // then run the task, otherwise load from DB. 1121 // then run the task, otherwise load from DB.
1107 if (!loaded_) { 1122 if (!finished_fetching_all_cookies_ && store_.get()) {
1108 // Checks if the domain key has been loaded. 1123 // Checks if the domain key has been loaded.
1109 std::string key( 1124 std::string key(
1110 cookie_util::GetEffectiveDomain(url.scheme(), url.host())); 1125 cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
1111 if (keys_loaded_.find(key) == keys_loaded_.end()) { 1126 if (keys_loaded_.find(key) == keys_loaded_.end()) {
1112 std::map<std::string, 1127 std::map<std::string,
1113 std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it = 1128 std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
1114 tasks_pending_for_key_.find(key); 1129 tasks_pending_for_key_.find(key);
1115 if (it == tasks_pending_for_key_.end()) { 1130 if (it == tasks_pending_for_key_.end()) {
1116 store_->LoadCookiesForKey( 1131 store_->LoadCookiesForKey(
1117 key, base::Bind(&CookieMonster::OnKeyLoaded, this, key)); 1132 key, base::Bind(&CookieMonster::OnKeyLoaded, this, key));
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 return false; 1170 return false;
1156 1171
1157 CookieOptions options; 1172 CookieOptions options;
1158 options.set_include_httponly(); 1173 options.set_include_httponly();
1159 options.set_include_first_party_only(); 1174 options.set_include_first_party_only();
1160 return SetCanonicalCookie(&cc, creation_time, options); 1175 return SetCanonicalCookie(&cc, creation_time, options);
1161 } 1176 }
1162 1177
1163 bool CookieMonster::ImportCookies(const CookieList& list) { 1178 bool CookieMonster::ImportCookies(const CookieList& list) {
1164 base::AutoLock autolock(lock_); 1179 base::AutoLock autolock(lock_);
1165 InitIfNecessary(); 1180 MarkCookieStoreAsInitialized();
1181 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1182 FetchAllCookiesIfNecessary();
1166 for (CookieList::const_iterator iter = list.begin(); iter != list.end(); 1183 for (CookieList::const_iterator iter = list.begin(); iter != list.end();
1167 ++iter) { 1184 ++iter) {
1168 scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(*iter)); 1185 scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(*iter));
1169 CookieOptions options; 1186 CookieOptions options;
1170 options.set_include_httponly(); 1187 options.set_include_httponly();
1171 options.set_include_first_party_only(); 1188 options.set_include_first_party_only();
1172 if (!SetCanonicalCookie(&cookie, cookie->CreationDate(), options)) 1189 if (!SetCanonicalCookie(&cookie, cookie->CreationDate(), options))
1173 return false; 1190 return false;
1174 } 1191 }
1175 return true; 1192 return true;
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
1480 bool CookieMonster::SetCookieWithCreationTime(const GURL& url, 1497 bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
1481 const std::string& cookie_line, 1498 const std::string& cookie_line,
1482 const base::Time& creation_time) { 1499 const base::Time& creation_time) {
1483 DCHECK(!store_.get()) << "This method is only to be used by unit-tests."; 1500 DCHECK(!store_.get()) << "This method is only to be used by unit-tests.";
1484 base::AutoLock autolock(lock_); 1501 base::AutoLock autolock(lock_);
1485 1502
1486 if (!HasCookieableScheme(url)) { 1503 if (!HasCookieableScheme(url)) {
1487 return false; 1504 return false;
1488 } 1505 }
1489 1506
1490 InitIfNecessary(); 1507 MarkCookieStoreAsInitialized();
1508 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1509 FetchAllCookiesIfNecessary();
1510
1491 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time, 1511 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time,
1492 CookieOptions()); 1512 CookieOptions());
1493 } 1513 }
1494 1514
1495 void CookieMonster::InitStore() { 1515 void CookieMonster::MarkCookieStoreAsInitialized() {
1516 initialized_ = true;
1517 }
1518
1519 void CookieMonster::FetchAllCookiesIfNecessary() {
1520 if (store_.get() && !started_fetching_all_cookies_) {
1521 started_fetching_all_cookies_ = true;
1522 FetchAllCookies();
1523 }
1524 }
1525
1526 bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
1527 if (fetch_strategy_ == kUnknownFetch) {
1528 const std::string group_name =
1529 base::FieldTrialList::FindFullName(kCookieMonsterFetchStrategyName);
1530 if (group_name == kFetchWhenNecessaryName) {
1531 fetch_strategy_ = kFetchWhenNecessary;
1532 } else if (group_name == kAlwaysFetchName) {
1533 fetch_strategy_ = kAlwaysFetch;
1534 } else {
1535 // The logic in the conditional is redundant, but it makes trials of
1536 // the Finch experiment more explicit.
1537 fetch_strategy_ = kAlwaysFetch;
1538 }
1539 }
1540
1541 return fetch_strategy_ == kAlwaysFetch;
1542 }
1543
1544 void CookieMonster::FetchAllCookies() {
1496 DCHECK(store_.get()) << "Store must exist to initialize"; 1545 DCHECK(store_.get()) << "Store must exist to initialize";
1546 DCHECK(!finished_fetching_all_cookies_)
1547 << "All cookies have already been fetched.";
1497 1548
1498 // We bind in the current time so that we can report the wall-clock time for 1549 // We bind in the current time so that we can report the wall-clock time for
1499 // loading cookies. 1550 // loading cookies.
1500 store_->Load(base::Bind(&CookieMonster::OnLoaded, this, TimeTicks::Now())); 1551 store_->Load(base::Bind(&CookieMonster::OnLoaded, this, TimeTicks::Now()));
1501 } 1552 }
1502 1553
1503 void CookieMonster::OnLoaded(TimeTicks beginning_time, 1554 void CookieMonster::OnLoaded(TimeTicks beginning_time,
1504 const std::vector<CanonicalCookie*>& cookies) { 1555 const std::vector<CanonicalCookie*>& cookies) {
1505 StoreLoadedCookies(cookies); 1556 StoreLoadedCookies(cookies);
1506 histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time); 1557 histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time);
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1607 // since they are expected to be much fewer than total DB. 1658 // since they are expected to be much fewer than total DB.
1608 EnsureCookiesMapIsValid(); 1659 EnsureCookiesMapIsValid();
1609 } 1660 }
1610 1661
1611 void CookieMonster::InvokeQueue() { 1662 void CookieMonster::InvokeQueue() {
1612 while (true) { 1663 while (true) {
1613 scoped_refptr<CookieMonsterTask> request_task; 1664 scoped_refptr<CookieMonsterTask> request_task;
1614 { 1665 {
1615 base::AutoLock autolock(lock_); 1666 base::AutoLock autolock(lock_);
1616 if (tasks_pending_.empty()) { 1667 if (tasks_pending_.empty()) {
1617 loaded_ = true; 1668 finished_fetching_all_cookies_ = true;
1618 creation_times_.clear(); 1669 creation_times_.clear();
1619 keys_loaded_.clear(); 1670 keys_loaded_.clear();
1620 break; 1671 break;
1621 } 1672 }
1622 request_task = tasks_pending_.front(); 1673 request_task = tasks_pending_.front();
1623 tasks_pending_.pop(); 1674 tasks_pending_.pop();
1624 } 1675 }
1625 request_task->Run(); 1676 request_task->Run();
1626 } 1677 }
1627 } 1678 }
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
2411 it != hook_map_.end(); ++it) { 2462 it != hook_map_.end(); ++it) {
2412 std::pair<GURL, std::string> key = it->first; 2463 std::pair<GURL, std::string> key = it->first;
2413 if (cookie.IncludeForRequestURL(key.first, opts) && 2464 if (cookie.IncludeForRequestURL(key.first, opts) &&
2414 cookie.Name() == key.second) { 2465 cookie.Name() == key.second) {
2415 it->second->Notify(cookie, removed); 2466 it->second->Notify(cookie, removed);
2416 } 2467 }
2417 } 2468 }
2418 } 2469 }
2419 2470
2420 } // namespace net 2471 } // namespace net
OLDNEW
« no previous file with comments | « net/cookies/cookie_monster.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698