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

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

Issue 1976073002: Making cookies eviction quotas match spec (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: strict cookie Created 4 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 | « no previous file | net/cookies/cookie_monster_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 (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 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 const CookieStore::CookieChangedCallback& callback, 306 const CookieStore::CookieChangedCallback& callback,
307 const CanonicalCookie& cookie, 307 const CanonicalCookie& cookie,
308 bool removed) { 308 bool removed) {
309 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed)); 309 proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed));
310 } 310 }
311 311
312 size_t CountProtectedSecureCookiesAtPriority( 312 size_t CountProtectedSecureCookiesAtPriority(
313 CookiePriority priority, 313 CookiePriority priority,
314 CookieMonster::CookieItVector* cookies) { 314 CookieMonster::CookieItVector* cookies) {
315 size_t num_protected_secure_cookies = 0; 315 size_t num_protected_secure_cookies = 0;
316 for (const auto& cookie : *cookies) { 316 for (const auto& cookie : *cookies) {
jww 2016/05/23 23:19:03 Can't this loop be simplified now to just: if (coo
maksims (do not use this acc) 2016/05/24 06:24:57 Right. Done.
317 if (!cookie->second->IsSecure()) 317 if (!cookie->second->IsSecure())
318 continue; 318 continue;
319 // 1) At low-priority, only low-priority secure cookies are protected as 319 // 1) At low-priority, only low-priority secure cookies are protected as
320 // part of the quota. 320 // part of the quota.
321 // 2) At medium-priority, only medium-priority secure cookies are protected 321 // 2) At medium-priority, only medium-priority secure cookies are protected
322 // as part of the quota (low-priority secure cookies may be deleted). 322 // as part of the quota (low-priority secure cookies may be deleted).
323 // 3) At high-priority, medium-priority and high-priority secure cookies are 323 // 3) At high-priority, medium-priority and high-priority secure cookies are
324 // protected as part of the quota (low-priority secure cookies may be 324 // protected as part of the quota (low-priority secure cookies may be
325 // deleted). 325 // deleted).
326 CookiePriority cookie_priority = cookie->second->Priority(); 326 CookiePriority cookie_priority = cookie->second->Priority();
327 switch (cookie_priority) { 327 switch (cookie_priority) {
328 case COOKIE_PRIORITY_LOW: 328 case COOKIE_PRIORITY_LOW:
329 if (priority == COOKIE_PRIORITY_LOW) 329 num_protected_secure_cookies++;
330 num_protected_secure_cookies++;
331 break; 330 break;
332 case COOKIE_PRIORITY_MEDIUM: 331 case COOKIE_PRIORITY_MEDIUM:
332 num_protected_secure_cookies++;
333 break;
333 case COOKIE_PRIORITY_HIGH: 334 case COOKIE_PRIORITY_HIGH:
334 if (cookie_priority <= priority) 335 num_protected_secure_cookies++;
335 num_protected_secure_cookies++;
336 break; 336 break;
337 } 337 }
338 } 338 }
339 339
340 return num_protected_secure_cookies; 340 return num_protected_secure_cookies;
341 } 341 }
342 342
343 bool IsCookieEligibleForEviction(CookiePriority current_priority_level, 343 bool IsCookieEligibleForEviction(CookiePriority current_priority_level,
344 bool protect_secure_cookies, 344 bool protect_secure_cookies,
345 const CanonicalCookie* cookie) { 345 const CanonicalCookie* cookie) {
346 if (!cookie->IsSecure() || !protect_secure_cookies) 346 if (cookie->Priority() == current_priority_level && cookie->IsSecure() &&
jww 2016/05/23 23:19:03 These two conditionals can be simplified to: if (
maksims (do not use this acc) 2016/05/24 06:24:57 Done.
347 return cookie->Priority() <= current_priority_level; 347 protect_secure_cookies)
348 return false;
349 if (cookie->Priority() == current_priority_level && !cookie->IsSecure() &&
350 protect_secure_cookies)
351 return true;
348 352
349 // Special consideration has to be given for low-priority secure cookies since 353 return cookie->Priority() == current_priority_level;
350 // they are given lower prority than non-secure medium-priority and non-secure 354 }
351 // high-priority cookies. Thus, low-priority secure cookies may be evicted at
352 // a medium and high value of |current_priority_level|. Put another way,
353 // low-priority secure cookies are only protected when the current priority
354 // level is low.
355 if (current_priority_level == COOKIE_PRIORITY_LOW)
356 return false;
357 355
358 return cookie->Priority() == COOKIE_PRIORITY_LOW; 356 size_t CountCookiesAtPriority(CookiePriority priority,
357 CookieMonster::CookieItVector* cookies) {
358 size_t num_of_priority_cookies = 0;
359 size_t current = 0;
360 while (current < cookies->size()) {
361 if (cookies->at(current)->second->Priority() == priority)
362 num_of_priority_cookies++;
363 current++;
364 }
365 return num_of_priority_cookies;
359 } 366 }
360 367
361 } // namespace 368 } // namespace
362 369
363 CookieMonster::CookieMonster(PersistentCookieStore* store, 370 CookieMonster::CookieMonster(PersistentCookieStore* store,
364 CookieMonsterDelegate* delegate) 371 CookieMonsterDelegate* delegate)
365 : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) { 372 : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) {
366 } 373 }
367 374
368 CookieMonster::CookieMonster(PersistentCookieStore* store, 375 CookieMonster::CookieMonster(PersistentCookieStore* store,
(...skipping 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after
1920 1927
1921 if (cookie_its->size() > kDomainMaxCookies) { 1928 if (cookie_its->size() > kDomainMaxCookies) {
1922 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain."; 1929 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain.";
1923 size_t purge_goal = 1930 size_t purge_goal =
1924 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies); 1931 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
1925 DCHECK(purge_goal > kDomainPurgeCookies); 1932 DCHECK(purge_goal > kDomainPurgeCookies);
1926 1933
1927 // Sort the cookies by access date, from least-recent to most-recent. 1934 // Sort the cookies by access date, from least-recent to most-recent.
1928 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter); 1935 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter);
1929 1936
1930 size_t additional_quota_low = kDomainCookiesQuotaLow;
1931 size_t additional_quota_medium = kDomainCookiesQuotaMedium;
1932 size_t additional_quota_high = kDomainCookiesQuotaHigh;
1933
1934 // Remove all but the kDomainCookiesQuotaLow most-recently accessed 1937 // Remove all but the kDomainCookiesQuotaLow most-recently accessed
1935 // cookies with low-priority. Then, if cookies still need to be removed, 1938 // cookies with low-priority. Then, if cookies still need to be removed,
1936 // bump the quota and remove low- and medium-priority. Then, if cookies 1939 // bump the quota and remove low- and medium-priority. Then, if cookies
1937 // _still_ need to be removed, bump the quota and remove cookies with 1940 // _still_ need to be removed, bump the quota and remove cookies with
1938 // any priority. 1941 // any priority.
1939 // 1942 //
1940 // 1. Low-priority non-secure cookies. 1943 // 1. Low-priority non-secure cookies.
1941 // 2. Low-priority secure cookies. 1944 // 2. Low-priority secure cookies.
1942 // 3. Medium-priority non-secure cookies. 1945 // 3. Medium-priority non-secure cookies.
1943 // 4. High-priority non-secure cookies. 1946 // 4. High-priority non-secure cookies.
(...skipping 21 matching lines...) Expand all
1965 for (const auto& purge_round : purge_rounds) { 1968 for (const auto& purge_round : purge_rounds) {
1966 // Only observe the non-secure purge rounds if strict secure cookies is 1969 // Only observe the non-secure purge rounds if strict secure cookies is
1967 // enabled. 1970 // enabled.
1968 if (!enforce_strict_secure && purge_round.protect_secure_cookies) 1971 if (!enforce_strict_secure && purge_round.protect_secure_cookies)
1969 continue; 1972 continue;
1970 1973
1971 // Only adjust the quota if the round is executing, otherwise it is 1974 // Only adjust the quota if the round is executing, otherwise it is
1972 // necesary to delay quota adjustments until a later round. This is 1975 // necesary to delay quota adjustments until a later round. This is
1973 // because if the high priority, non-secure round is skipped, its quota 1976 // because if the high priority, non-secure round is skipped, its quota
1974 // should not count until the later high priority, full round later. 1977 // should not count until the later high priority, full round later.
1975 size_t* additional_quota = nullptr;
1976 switch (purge_round.priority) { 1978 switch (purge_round.priority) {
1977 case COOKIE_PRIORITY_LOW: 1979 case COOKIE_PRIORITY_LOW:
1978 additional_quota = &additional_quota_low; 1980 quota = kDomainCookiesQuotaLow;
jww 2016/05/23 23:19:03 This is the change that I'm most confused about. D
maksims (do not use this acc) 2016/05/24 06:24:57 Not exactly. First, we take a quota at |priority|
jww 2016/05/26 03:46:39 Ok, I've got it. As mentioned before, can you upda
1979 break; 1981 break;
1980 case COOKIE_PRIORITY_MEDIUM: 1982 case COOKIE_PRIORITY_MEDIUM:
1981 additional_quota = &additional_quota_medium; 1983 quota = kDomainCookiesQuotaMedium;
1982 break; 1984 break;
1983 case COOKIE_PRIORITY_HIGH: 1985 case COOKIE_PRIORITY_HIGH:
1984 additional_quota = &additional_quota_high; 1986 quota = kDomainCookiesQuotaHigh;
1985 break; 1987 break;
1986 } 1988 }
1987 quota += *additional_quota;
1988 *additional_quota = 0u;
1989 size_t just_deleted = 0u; 1989 size_t just_deleted = 0u;
1990
1991 // Purge up to |purge_goal| for all cookies at the given priority. This 1990 // Purge up to |purge_goal| for all cookies at the given priority. This
1992 // path will always execute if strict secure cookies is disabled since 1991 // path will always execute if strict secure cookies is disabled since
1993 // |purge_goal| must be positive because of the for-loop guard. If 1992 // |purge_goal| must be positive because of the for-loop guard. If
1994 // strict secure cookies is enabled, this path will be taken only if the 1993 // strict secure cookies is enabled, this path will be taken only if the
1995 // initial non-secure purge did not evict enough cookies. 1994 // initial non-secure purge did not evict enough cookies.
1996 if (purge_goal > 0) { 1995 if (purge_goal > 0) {
1997 just_deleted = PurgeLeastRecentMatches( 1996 just_deleted = PurgeLeastRecentMatches(
1998 cookie_its, purge_round.priority, quota, purge_goal, 1997 cookie_its, purge_round.priority, quota, purge_goal,
1999 purge_round.protect_secure_cookies); 1998 purge_round.protect_secure_cookies);
2000 DCHECK_LE(just_deleted, purge_goal); 1999 DCHECK_LE(just_deleted, purge_goal);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2049 2048
2050 return num_deleted; 2049 return num_deleted;
2051 } 2050 }
2052 2051
2053 size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, 2052 size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
2054 CookiePriority priority, 2053 CookiePriority priority,
2055 size_t to_protect, 2054 size_t to_protect,
2056 size_t purge_goal, 2055 size_t purge_goal,
2057 bool protect_secure_cookies) { 2056 bool protect_secure_cookies) {
2058 DCHECK(thread_checker_.CalledOnValidThread()); 2057 DCHECK(thread_checker_.CalledOnValidThread());
2058 // 1. Count number of the cookies at |priority|
2059 size_t cookies_count_possibly_to_be_deleted =
jww 2016/05/23 23:19:03 While this logic is generally sound, it might be g
maksims (do not use this acc) 2016/05/24 06:24:57 Hmm, ok!
2060 CountCookiesAtPriority(priority, cookies);
2061 // 2. If |cookies_count| at |priority| is less than or equal to_protect, skip.
2062 // This involves secure and non-secure cookies at |priority|.
2063 if (cookies_count_possibly_to_be_deleted <= to_protect)
2064 return 0u;
2059 2065
2060 // Find the first protected cookie by walking down from the end of the list 2066 // 3. Calculate number of secure cookies at |priority|
2061 // cookie list (most-recently accessed) until |to_protect| cookies that match 2067 // and Count number of cookies at |priority| that can possibly be deleted.
2062 // |priority| are found. 2068 // It is guaranteed we do not delete more than |purge_goal| even if
2063 // 2069 // |priority_cookies_might_be_deleted| is higher.
jww 2016/05/26 03:46:39 This variable name changed, correct?
2064 // If |protect_secure_cookies| is true, do a first pass that counts eligible 2070 size_t secure_cookies = 0u;
2065 // secure cookies at the specified priority as protected.
2066 if (protect_secure_cookies) { 2071 if (protect_secure_cookies) {
2067 to_protect -= std::min( 2072 secure_cookies = CountProtectedSecureCookiesAtPriority(priority, cookies);
2068 to_protect, CountProtectedSecureCookiesAtPriority(priority, cookies)); 2073 cookies_count_possibly_to_be_deleted -= secure_cookies;
jww 2016/05/23 23:19:03 What if secure_cookies < to_protect? Don't you sti
maksims (do not use this acc) 2016/05/24 06:24:57 It doesn't matter. |secure_cookies| are subtracted
jww 2016/05/26 03:46:39 What if there are 90 low priority, non-secure cook
2074 } else {
2075 cookies_count_possibly_to_be_deleted -= to_protect;
2069 } 2076 }
2070 2077
2071 size_t protection_boundary = cookies->size(); 2078 size_t removed = 0u;
2072 while (to_protect > 0 && protection_boundary > 0) { 2079 size_t current = 0u;
2073 protection_boundary--; 2080 while (removed < purge_goal && current < cookies->size()) {
2074 if (cookies->at(protection_boundary)->second->Priority() <= priority)
2075 to_protect--;
2076 }
2077
2078 // Now, walk up from the beginning of the list (least-recently accessed) until
2079 // |purge_goal| cookies are removed, or the iterator hits
2080 // |protection_boundary|.
2081 size_t removed = 0;
2082 size_t current = 0;
2083 while (removed < purge_goal && current < protection_boundary) {
2084 const CanonicalCookie* current_cookie = cookies->at(current)->second; 2081 const CanonicalCookie* current_cookie = cookies->at(current)->second;
2085 // Only delete the current cookie if the priority is less than or equal to 2082 // Only delete the current cookie if the priority is equal to
2086 // the current level. If it is equal to the current level, and secure 2083 // the current level.
2087 // cookies are protected, only delete it if it is not secure.
2088 if (IsCookieEligibleForEviction(priority, protect_secure_cookies, 2084 if (IsCookieEligibleForEviction(priority, protect_secure_cookies,
2089 current_cookie)) { 2085 current_cookie) &&
2086 cookies_count_possibly_to_be_deleted > 0) {
2090 InternalDeleteCookie(cookies->at(current), true, 2087 InternalDeleteCookie(cookies->at(current), true,
2091 DELETE_COOKIE_EVICTED_DOMAIN); 2088 DELETE_COOKIE_EVICTED_DOMAIN);
2092 cookies->erase(cookies->begin() + current); 2089 cookies->erase(cookies->begin() + current);
2093 removed++; 2090 removed++;
2094 2091 cookies_count_possibly_to_be_deleted--;
2095 // The call to 'erase' above shifts the contents of the vector, but 2092 // The call to 'erase' above shifts the contents of the vector, but
2096 // doesn't shift |protection_boundary|. Decrement that here to ensure that 2093 // doesn't shift |protection_boundary|. Decrement that here to ensure that
2097 // the correct set of cookies is protected. 2094 // the correct set of cookies is protected.;
2098 protection_boundary--;
2099 } else { 2095 } else {
2100 current++; 2096 current++;
2101 } 2097 }
2102 } 2098 }
2103 return removed; 2099 return removed;
2104 } 2100 }
2105 2101
2106 size_t CookieMonster::GarbageCollectExpired(const Time& current, 2102 size_t CookieMonster::GarbageCollectExpired(const Time& current,
2107 const CookieMapItPair& itpair, 2103 const CookieMapItPair& itpair,
2108 CookieItVector* cookie_its) { 2104 CookieItVector* cookie_its) {
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
2426 it != hook_map_.end(); ++it) { 2422 it != hook_map_.end(); ++it) {
2427 std::pair<GURL, std::string> key = it->first; 2423 std::pair<GURL, std::string> key = it->first;
2428 if (cookie.IncludeForRequestURL(key.first, opts) && 2424 if (cookie.IncludeForRequestURL(key.first, opts) &&
2429 cookie.Name() == key.second) { 2425 cookie.Name() == key.second) {
2430 it->second->Notify(cookie, removed); 2426 it->second->Notify(cookie, removed);
2431 } 2427 }
2432 } 2428 }
2433 } 2429 }
2434 2430
2435 } // namespace net 2431 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/cookies/cookie_monster_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698