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

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: Created 5 years, 8 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
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 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 const CanonicalCookie& cookie, 330 const CanonicalCookie& cookie,
323 bool removed) { 331 bool removed) {
324 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed)); 332 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed));
325 } 333 }
326 334
327 } // namespace 335 } // namespace
328 336
329 CookieMonster::CookieMonster(PersistentCookieStore* store, 337 CookieMonster::CookieMonster(PersistentCookieStore* store,
330 CookieMonsterDelegate* delegate) 338 CookieMonsterDelegate* delegate)
331 : initialized_(false), 339 : initialized_(false),
332 loaded_(false), 340 started_fetching_all_cookies_(false),
341 finished_fetching_all_cookies_(false),
342 fetch_strategy_(kUnknownFetch),
333 store_(store), 343 store_(store),
334 last_access_threshold_( 344 last_access_threshold_(
335 TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)), 345 TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)),
336 delegate_(delegate), 346 delegate_(delegate),
337 last_statistic_record_time_(Time::Now()), 347 last_statistic_record_time_(Time::Now()),
338 keep_expired_cookies_(false), 348 keep_expired_cookies_(false),
339 persist_session_cookies_(false) { 349 persist_session_cookies_(false) {
340 InitializeHistograms(); 350 InitializeHistograms();
341 SetDefaultCookieableSchemes(); 351 SetDefaultCookieableSchemes();
342 } 352 }
343 353
344 CookieMonster::CookieMonster(PersistentCookieStore* store, 354 CookieMonster::CookieMonster(PersistentCookieStore* store,
345 CookieMonsterDelegate* delegate, 355 CookieMonsterDelegate* delegate,
346 int last_access_threshold_milliseconds) 356 int last_access_threshold_milliseconds)
347 : initialized_(false), 357 : initialized_(false),
348 loaded_(false), 358 started_fetching_all_cookies_(false),
359 finished_fetching_all_cookies_(false),
360 fetch_strategy_(kUnknownFetch),
349 store_(store), 361 store_(store),
350 last_access_threshold_(base::TimeDelta::FromMilliseconds( 362 last_access_threshold_(base::TimeDelta::FromMilliseconds(
351 last_access_threshold_milliseconds)), 363 last_access_threshold_milliseconds)),
352 delegate_(delegate), 364 delegate_(delegate),
353 last_statistic_record_time_(base::Time::Now()), 365 last_statistic_record_time_(base::Time::Now()),
354 keep_expired_cookies_(false), 366 keep_expired_cookies_(false),
355 persist_session_cookies_(false) { 367 persist_session_cookies_(false) {
356 InitializeHistograms(); 368 InitializeHistograms();
357 SetDefaultCookieableSchemes(); 369 SetDefaultCookieableSchemes();
358 } 370 }
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 scoped_refptr<DeleteSessionCookiesTask> task = 1096 scoped_refptr<DeleteSessionCookiesTask> task =
1085 new DeleteSessionCookiesTask(this, callback); 1097 new DeleteSessionCookiesTask(this, callback);
1086 1098
1087 DoCookieTask(task); 1099 DoCookieTask(task);
1088 } 1100 }
1089 1101
1090 void CookieMonster::DoCookieTask( 1102 void CookieMonster::DoCookieTask(
1091 const scoped_refptr<CookieMonsterTask>& task_item) { 1103 const scoped_refptr<CookieMonsterTask>& task_item) {
1092 { 1104 {
1093 base::AutoLock autolock(lock_); 1105 base::AutoLock autolock(lock_);
1094 InitIfNecessary(); 1106 MarkCookieStoreAsInitialized();
1095 if (!loaded_) { 1107 FetchAllCookiesIfNecessary();
1108 if (!finished_fetching_all_cookies_ && store_.get()) {
1096 tasks_pending_.push(task_item); 1109 tasks_pending_.push(task_item);
1097 return; 1110 return;
1098 } 1111 }
1099 } 1112 }
1100 1113
1101 task_item->Run(); 1114 task_item->Run();
1102 } 1115 }
1103 1116
1104 void CookieMonster::DoCookieTaskForURL( 1117 void CookieMonster::DoCookieTaskForURL(
1105 const scoped_refptr<CookieMonsterTask>& task_item, 1118 const scoped_refptr<CookieMonsterTask>& task_item,
1106 const GURL& url) { 1119 const GURL& url) {
1107 { 1120 {
1108 base::AutoLock autolock(lock_); 1121 base::AutoLock autolock(lock_);
1109 InitIfNecessary(); 1122 MarkCookieStoreAsInitialized();
1123 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1124 FetchAllCookiesIfNecessary();
1110 // If cookies for the requested domain key (eTLD+1) have been loaded from DB 1125 // If cookies for the requested domain key (eTLD+1) have been loaded from DB
1111 // then run the task, otherwise load from DB. 1126 // then run the task, otherwise load from DB.
1112 if (!loaded_) { 1127 if (!finished_fetching_all_cookies_ && store_.get()) {
1113 // Checks if the domain key has been loaded. 1128 // Checks if the domain key has been loaded.
1114 std::string key( 1129 std::string key(
1115 cookie_util::GetEffectiveDomain(url.scheme(), url.host())); 1130 cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
1116 if (keys_loaded_.find(key) == keys_loaded_.end()) { 1131 if (keys_loaded_.find(key) == keys_loaded_.end()) {
1117 std::map<std::string, 1132 std::map<std::string,
1118 std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it = 1133 std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
1119 tasks_pending_for_key_.find(key); 1134 tasks_pending_for_key_.find(key);
1120 if (it == tasks_pending_for_key_.end()) { 1135 if (it == tasks_pending_for_key_.end()) {
1121 store_->LoadCookiesForKey( 1136 store_->LoadCookiesForKey(
1122 key, base::Bind(&CookieMonster::OnKeyLoaded, this, key)); 1137 key, base::Bind(&CookieMonster::OnKeyLoaded, this, key));
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 return false; 1175 return false;
1161 1176
1162 CookieOptions options; 1177 CookieOptions options;
1163 options.set_include_httponly(); 1178 options.set_include_httponly();
1164 options.set_include_first_party_only(); 1179 options.set_include_first_party_only();
1165 return SetCanonicalCookie(&cc, creation_time, options); 1180 return SetCanonicalCookie(&cc, creation_time, options);
1166 } 1181 }
1167 1182
1168 bool CookieMonster::ImportCookies(const CookieList& list) { 1183 bool CookieMonster::ImportCookies(const CookieList& list) {
1169 base::AutoLock autolock(lock_); 1184 base::AutoLock autolock(lock_);
1170 InitIfNecessary(); 1185 MarkCookieStoreAsInitialized();
1186 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1187 FetchAllCookiesIfNecessary();
1171 for (net::CookieList::const_iterator iter = list.begin(); iter != list.end(); 1188 for (net::CookieList::const_iterator iter = list.begin(); iter != list.end();
1172 ++iter) { 1189 ++iter) {
1173 scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(*iter)); 1190 scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(*iter));
1174 net::CookieOptions options; 1191 net::CookieOptions options;
1175 options.set_include_httponly(); 1192 options.set_include_httponly();
1176 options.set_include_first_party_only(); 1193 options.set_include_first_party_only();
1177 if (!SetCanonicalCookie(&cookie, cookie->CreationDate(), options)) 1194 if (!SetCanonicalCookie(&cookie, cookie->CreationDate(), options))
1178 return false; 1195 return false;
1179 } 1196 }
1180 return true; 1197 return true;
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
1466 bool CookieMonster::SetCookieWithCreationTime(const GURL& url, 1483 bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
1467 const std::string& cookie_line, 1484 const std::string& cookie_line,
1468 const base::Time& creation_time) { 1485 const base::Time& creation_time) {
1469 DCHECK(!store_.get()) << "This method is only to be used by unit-tests."; 1486 DCHECK(!store_.get()) << "This method is only to be used by unit-tests.";
1470 base::AutoLock autolock(lock_); 1487 base::AutoLock autolock(lock_);
1471 1488
1472 if (!HasCookieableScheme(url)) { 1489 if (!HasCookieableScheme(url)) {
1473 return false; 1490 return false;
1474 } 1491 }
1475 1492
1476 InitIfNecessary(); 1493 MarkCookieStoreAsInitialized();
1494 if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
1495 FetchAllCookiesIfNecessary();
1496
1477 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time, 1497 return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time,
1478 CookieOptions()); 1498 CookieOptions());
1479 } 1499 }
1480 1500
1481 void CookieMonster::InitStore() { 1501 void CookieMonster::MarkCookieStoreAsInitialized() {
1502 initialized_ = true;
1503 }
1504
1505 void CookieMonster::FetchAllCookiesIfNecessary() {
1506 if (store_.get() && !started_fetching_all_cookies_) {
1507 started_fetching_all_cookies_ = true;
1508 FetchAllCookies();
1509 }
1510 }
1511
1512 bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
1513 if (fetch_strategy_ == kUnknownFetch) {
1514 const std::string group_name =
1515 base::FieldTrialList::FindFullName(kCookieMonsterFetchStrategyName);
1516 if (group_name == kFetchWhenNecessaryName) {
1517 fetch_strategy_ = kFetchWhenNecessary;
1518 } else if (group_name == kAlwaysFetchName) {
1519 fetch_strategy_ = kAlwaysFetch;
1520 } else {
1521 // The logic in the conditional is redundant, but it makes trials of
1522 // the Finch experiment more explicit.
1523 fetch_strategy_ = kAlwaysFetch;
1524 }
1525 }
1526
1527 return fetch_strategy_ == kAlwaysFetch;
1528 }
1529
1530 void CookieMonster::FetchAllCookies() {
1482 DCHECK(store_.get()) << "Store must exist to initialize"; 1531 DCHECK(store_.get()) << "Store must exist to initialize";
1532 DCHECK(!finished_fetching_all_cookies_)
1533 << "All cookies have already been fetched.";
1483 1534
1484 // We bind in the current time so that we can report the wall-clock time for 1535 // We bind in the current time so that we can report the wall-clock time for
1485 // loading cookies. 1536 // loading cookies.
1486 store_->Load(base::Bind(&CookieMonster::OnLoaded, this, TimeTicks::Now())); 1537 store_->Load(base::Bind(&CookieMonster::OnLoaded, this, TimeTicks::Now()));
1487 } 1538 }
1488 1539
1489 void CookieMonster::OnLoaded(TimeTicks beginning_time, 1540 void CookieMonster::OnLoaded(TimeTicks beginning_time,
1490 const std::vector<CanonicalCookie*>& cookies) { 1541 const std::vector<CanonicalCookie*>& cookies) {
1491 StoreLoadedCookies(cookies); 1542 StoreLoadedCookies(cookies);
1492 histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time); 1543 histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1587 // since they are expected to be much fewer than total DB. 1638 // since they are expected to be much fewer than total DB.
1588 EnsureCookiesMapIsValid(); 1639 EnsureCookiesMapIsValid();
1589 } 1640 }
1590 1641
1591 void CookieMonster::InvokeQueue() { 1642 void CookieMonster::InvokeQueue() {
1592 while (true) { 1643 while (true) {
1593 scoped_refptr<CookieMonsterTask> request_task; 1644 scoped_refptr<CookieMonsterTask> request_task;
1594 { 1645 {
1595 base::AutoLock autolock(lock_); 1646 base::AutoLock autolock(lock_);
1596 if (tasks_pending_.empty()) { 1647 if (tasks_pending_.empty()) {
1597 loaded_ = true; 1648 finished_fetching_all_cookies_ = true;
1598 creation_times_.clear(); 1649 creation_times_.clear();
1599 keys_loaded_.clear(); 1650 keys_loaded_.clear();
1600 break; 1651 break;
1601 } 1652 }
1602 request_task = tasks_pending_.front(); 1653 request_task = tasks_pending_.front();
1603 tasks_pending_.pop(); 1654 tasks_pending_.pop();
1604 } 1655 }
1605 request_task->Run(); 1656 request_task->Run();
1606 } 1657 }
1607 } 1658 }
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
2373 it != hook_map_.end(); ++it) { 2424 it != hook_map_.end(); ++it) {
2374 std::pair<GURL, std::string> key = it->first; 2425 std::pair<GURL, std::string> key = it->first;
2375 if (cookie.IncludeForRequestURL(key.first, opts) && 2426 if (cookie.IncludeForRequestURL(key.first, opts) &&
2376 cookie.Name() == key.second) { 2427 cookie.Name() == key.second) {
2377 it->second->Notify(cookie, removed); 2428 it->second->Notify(cookie, removed);
2378 } 2429 }
2379 } 2430 }
2380 } 2431 }
2381 2432
2382 } // namespace net 2433 } // namespace net
OLDNEW
« content/browser/net/sqlite_persistent_cookie_store.cc ('K') | « net/cookies/cookie_monster.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698