OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |