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 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 // DELETE_COOKIE_LAST_ENTRY | 302 // DELETE_COOKIE_LAST_ENTRY |
303 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false}}; | 303 {CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false}}; |
304 | 304 |
305 void RunAsync(scoped_refptr<base::TaskRunner> proxy, | 305 void RunAsync(scoped_refptr<base::TaskRunner> proxy, |
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( |
| 313 CookiePriority priority, |
| 314 CookieMonster::CookieItVector* cookies) { |
| 315 size_t num_protected_secure_cookies = 0; |
| 316 for (const auto& cookie : *cookies) { |
| 317 if (!cookie->second->IsSecure()) |
| 318 continue; |
| 319 // 1) At low-priority, only low-priority secure cookies are protected as |
| 320 // part of the quota. |
| 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). |
| 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 |
| 325 // deleted). |
| 326 CookiePriority cookie_priority = cookie->second->Priority(); |
| 327 switch (cookie_priority) { |
| 328 case COOKIE_PRIORITY_LOW: |
| 329 if (priority == COOKIE_PRIORITY_LOW) |
| 330 num_protected_secure_cookies++; |
| 331 break; |
| 332 case COOKIE_PRIORITY_MEDIUM: |
| 333 case COOKIE_PRIORITY_HIGH: |
| 334 if (cookie_priority <= priority) |
| 335 num_protected_secure_cookies++; |
| 336 break; |
| 337 } |
| 338 } |
| 339 |
| 340 return num_protected_secure_cookies; |
| 341 } |
| 342 |
312 bool IsCookieEligibleForEviction(CookiePriority current_priority_level, | 343 bool IsCookieEligibleForEviction(CookiePriority current_priority_level, |
313 bool protect_secure_cookies, | 344 bool protect_secure_cookies, |
314 const CanonicalCookie* cookie) { | 345 const CanonicalCookie* cookie) { |
315 if (cookie->Priority() == current_priority_level && protect_secure_cookies) | 346 if (!cookie->IsSecure() || !protect_secure_cookies) |
316 return !cookie->IsSecure(); | 347 return cookie->Priority() <= current_priority_level; |
317 | 348 |
318 return cookie->Priority() == current_priority_level; | 349 // Special consideration has to be given for low-priority secure cookies since |
319 } | 350 // they are given lower prority than non-secure medium-priority and non-secure |
| 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; |
320 | 357 |
321 size_t CountCookiesForPossibleDeletion( | 358 return cookie->Priority() == COOKIE_PRIORITY_LOW; |
322 CookiePriority priority, | |
323 const CookieMonster::CookieItVector* cookies, | |
324 bool protect_secure_cookies) { | |
325 size_t cookies_count = 0U; | |
326 for (const auto& cookie : *cookies) { | |
327 if (cookie->second->Priority() == priority) { | |
328 if (!protect_secure_cookies || cookie->second->IsSecure()) | |
329 cookies_count++; | |
330 } | |
331 } | |
332 return cookies_count; | |
333 } | 359 } |
334 | 360 |
335 } // namespace | 361 } // namespace |
336 | 362 |
337 CookieMonster::CookieMonster(PersistentCookieStore* store, | 363 CookieMonster::CookieMonster(PersistentCookieStore* store, |
338 CookieMonsterDelegate* delegate) | 364 CookieMonsterDelegate* delegate) |
339 : CookieMonster( | 365 : CookieMonster( |
340 store, | 366 store, |
341 delegate, | 367 delegate, |
342 base::TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)) {} | 368 base::TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)) {} |
(...skipping 1552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1895 | 1921 |
1896 if (cookie_its->size() > kDomainMaxCookies) { | 1922 if (cookie_its->size() > kDomainMaxCookies) { |
1897 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain."; | 1923 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain."; |
1898 size_t purge_goal = | 1924 size_t purge_goal = |
1899 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies); | 1925 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies); |
1900 DCHECK(purge_goal > kDomainPurgeCookies); | 1926 DCHECK(purge_goal > kDomainPurgeCookies); |
1901 | 1927 |
1902 // Sort the cookies by access date, from least-recent to most-recent. | 1928 // Sort the cookies by access date, from least-recent to most-recent. |
1903 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter); | 1929 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter); |
1904 | 1930 |
| 1931 size_t additional_quota_low = kDomainCookiesQuotaLow; |
| 1932 size_t additional_quota_medium = kDomainCookiesQuotaMedium; |
| 1933 size_t additional_quota_high = kDomainCookiesQuotaHigh; |
| 1934 |
1905 // Remove all but the kDomainCookiesQuotaLow most-recently accessed | 1935 // Remove all but the kDomainCookiesQuotaLow most-recently accessed |
1906 // cookies with low-priority. Then, if cookies still need to be removed, | 1936 // cookies with low-priority. Then, if cookies still need to be removed, |
1907 // bump the quota and remove low- and medium-priority. Then, if cookies | 1937 // bump the quota and remove low- and medium-priority. Then, if cookies |
1908 // _still_ need to be removed, bump the quota and remove cookies with | 1938 // _still_ need to be removed, bump the quota and remove cookies with |
1909 // any priority. | 1939 // any priority. |
1910 // | 1940 // |
1911 // 1. Low-priority non-secure cookies. | 1941 // 1. Low-priority non-secure cookies. |
1912 // 2. Low-priority secure cookies. | 1942 // 2. Low-priority secure cookies. |
1913 // 3. Medium-priority non-secure cookies. | 1943 // 3. Medium-priority non-secure cookies. |
1914 // 4. High-priority non-secure cookies. | 1944 // 4. High-priority non-secure cookies. |
(...skipping 17 matching lines...) Expand all Loading... |
1932 {COOKIE_PRIORITY_HIGH, false}, | 1962 {COOKIE_PRIORITY_HIGH, false}, |
1933 }; | 1963 }; |
1934 | 1964 |
1935 size_t quota = 0; | 1965 size_t quota = 0; |
1936 for (const auto& purge_round : purge_rounds) { | 1966 for (const auto& purge_round : purge_rounds) { |
1937 // Only observe the non-secure purge rounds if strict secure cookies is | 1967 // Only observe the non-secure purge rounds if strict secure cookies is |
1938 // enabled. | 1968 // enabled. |
1939 if (!enforce_strict_secure && purge_round.protect_secure_cookies) | 1969 if (!enforce_strict_secure && purge_round.protect_secure_cookies) |
1940 continue; | 1970 continue; |
1941 | 1971 |
1942 // Adjust quota according to the priority of cookies. Each round should | 1972 // Only adjust the quota if the round is executing, otherwise it is |
1943 // protect certain number of cookies in order to avoid starvation. | 1973 // necesary to delay quota adjustments until a later round. This is |
1944 // For example, when each round starts to remove cookies, the number of | 1974 // because if the high priority, non-secure round is skipped, its quota |
1945 // cookies of that priority are counted and a decision whether they | 1975 // should not count until the later high priority, full round later. |
1946 // should be deleted or not is made. If yes, some number of cookies of | 1976 size_t* additional_quota = nullptr; |
1947 // that priority are deleted considering the quota. | |
1948 switch (purge_round.priority) { | 1977 switch (purge_round.priority) { |
1949 case COOKIE_PRIORITY_LOW: | 1978 case COOKIE_PRIORITY_LOW: |
1950 quota = kDomainCookiesQuotaLow; | 1979 additional_quota = &additional_quota_low; |
1951 break; | 1980 break; |
1952 case COOKIE_PRIORITY_MEDIUM: | 1981 case COOKIE_PRIORITY_MEDIUM: |
1953 quota = kDomainCookiesQuotaMedium; | 1982 additional_quota = &additional_quota_medium; |
1954 break; | 1983 break; |
1955 case COOKIE_PRIORITY_HIGH: | 1984 case COOKIE_PRIORITY_HIGH: |
1956 quota = kDomainCookiesQuotaHigh; | 1985 additional_quota = &additional_quota_high; |
1957 break; | 1986 break; |
1958 } | 1987 } |
| 1988 quota += *additional_quota; |
| 1989 *additional_quota = 0u; |
1959 size_t just_deleted = 0u; | 1990 size_t just_deleted = 0u; |
| 1991 |
1960 // Purge up to |purge_goal| for all cookies at the given priority. This | 1992 // Purge up to |purge_goal| for all cookies at the given priority. This |
1961 // path will always execute if strict secure cookies is disabled since | 1993 // path will always execute if strict secure cookies is disabled since |
1962 // |purge_goal| must be positive because of the for-loop guard. If | 1994 // |purge_goal| must be positive because of the for-loop guard. If |
1963 // strict secure cookies is enabled, this path will be taken only if the | 1995 // strict secure cookies is enabled, this path will be taken only if the |
1964 // initial non-secure purge did not evict enough cookies. | 1996 // initial non-secure purge did not evict enough cookies. |
1965 if (purge_goal > 0) { | 1997 if (purge_goal > 0) { |
1966 just_deleted = PurgeLeastRecentMatches( | 1998 just_deleted = PurgeLeastRecentMatches( |
1967 cookie_its, purge_round.priority, quota, purge_goal, | 1999 cookie_its, purge_round.priority, quota, purge_goal, |
1968 purge_round.protect_secure_cookies); | 2000 purge_round.protect_secure_cookies); |
1969 DCHECK_LE(just_deleted, purge_goal); | 2001 DCHECK_LE(just_deleted, purge_goal); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2019 return num_deleted; | 2051 return num_deleted; |
2020 } | 2052 } |
2021 | 2053 |
2022 size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, | 2054 size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, |
2023 CookiePriority priority, | 2055 CookiePriority priority, |
2024 size_t to_protect, | 2056 size_t to_protect, |
2025 size_t purge_goal, | 2057 size_t purge_goal, |
2026 bool protect_secure_cookies) { | 2058 bool protect_secure_cookies) { |
2027 DCHECK(thread_checker_.CalledOnValidThread()); | 2059 DCHECK(thread_checker_.CalledOnValidThread()); |
2028 | 2060 |
2029 // 1. Count number of the cookies at |priority| | 2061 // Find the first protected cookie by walking down from the end of the list |
2030 size_t cookies_count_possibly_to_be_deleted = CountCookiesForPossibleDeletion( | 2062 // cookie list (most-recently accessed) until |to_protect| cookies that match |
2031 priority, cookies, false /* count all cookies */); | 2063 // |priority| are found. |
2032 | 2064 // |
2033 // 2. If |cookies_count_possibly_to_be_deleted| at |priority| is less than or | 2065 // If |protect_secure_cookies| is true, do a first pass that counts eligible |
2034 // equal |to_protect|, skip round in order to preserve the quota. This | 2066 // secure cookies at the specified priority as protected. |
2035 // involves secure and non-secure cookies at |priority|. | |
2036 if (cookies_count_possibly_to_be_deleted <= to_protect) | |
2037 return 0u; | |
2038 | |
2039 // 3. Calculate number of secure cookies at |priority| | |
2040 // and number of cookies at |priority| that can possibly be deleted. | |
2041 // It is guaranteed we do not delete more than |purge_goal| even if | |
2042 // |cookies_count_possibly_to_be_deleted| is higher. | |
2043 size_t secure_cookies = 0u; | |
2044 if (protect_secure_cookies) { | 2067 if (protect_secure_cookies) { |
2045 secure_cookies = CountCookiesForPossibleDeletion( | 2068 to_protect -= std::min( |
2046 priority, cookies, protect_secure_cookies /* count secure cookies */); | 2069 to_protect, CountProtectedSecureCookiesAtPriority(priority, cookies)); |
2047 cookies_count_possibly_to_be_deleted -= | |
2048 std::max(secure_cookies, to_protect - secure_cookies); | |
2049 } else { | |
2050 cookies_count_possibly_to_be_deleted -= to_protect; | |
2051 } | 2070 } |
2052 | 2071 |
2053 size_t removed = 0u; | 2072 size_t protection_boundary = cookies->size(); |
2054 size_t current = 0u; | 2073 while (to_protect > 0 && protection_boundary > 0) { |
2055 while ((removed < purge_goal && current < cookies->size()) && | 2074 protection_boundary--; |
2056 cookies_count_possibly_to_be_deleted > 0) { | 2075 if (cookies->at(protection_boundary)->second->Priority() <= priority) |
| 2076 to_protect--; |
| 2077 } |
| 2078 |
| 2079 // Now, walk up from the beginning of the list (least-recently accessed) until |
| 2080 // |purge_goal| cookies are removed, or the iterator hits |
| 2081 // |protection_boundary|. |
| 2082 size_t removed = 0; |
| 2083 size_t current = 0; |
| 2084 while (removed < purge_goal && current < protection_boundary) { |
2057 const CanonicalCookie* current_cookie = cookies->at(current)->second; | 2085 const CanonicalCookie* current_cookie = cookies->at(current)->second; |
2058 // Only delete the current cookie if the priority is equal to | 2086 // Only delete the current cookie if the priority is less than or equal to |
2059 // the current level. | 2087 // the current level. If it is equal to the current level, and secure |
| 2088 // cookies are protected, only delete it if it is not secure. |
2060 if (IsCookieEligibleForEviction(priority, protect_secure_cookies, | 2089 if (IsCookieEligibleForEviction(priority, protect_secure_cookies, |
2061 current_cookie)) { | 2090 current_cookie)) { |
2062 InternalDeleteCookie(cookies->at(current), true, | 2091 InternalDeleteCookie(cookies->at(current), true, |
2063 DELETE_COOKIE_EVICTED_DOMAIN); | 2092 DELETE_COOKIE_EVICTED_DOMAIN); |
2064 cookies->erase(cookies->begin() + current); | 2093 cookies->erase(cookies->begin() + current); |
2065 removed++; | 2094 removed++; |
2066 cookies_count_possibly_to_be_deleted--; | 2095 |
| 2096 // The call to 'erase' above shifts the contents of the vector, but |
| 2097 // doesn't shift |protection_boundary|. Decrement that here to ensure that |
| 2098 // the correct set of cookies is protected. |
| 2099 protection_boundary--; |
2067 } else { | 2100 } else { |
2068 current++; | 2101 current++; |
2069 } | 2102 } |
2070 } | 2103 } |
2071 return removed; | 2104 return removed; |
2072 } | 2105 } |
2073 | 2106 |
2074 size_t CookieMonster::GarbageCollectExpired(const Time& current, | 2107 size_t CookieMonster::GarbageCollectExpired(const Time& current, |
2075 const CookieMapItPair& itpair, | 2108 const CookieMapItPair& itpair, |
2076 CookieItVector* cookie_its) { | 2109 CookieItVector* cookie_its) { |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2394 it != hook_map_.end(); ++it) { | 2427 it != hook_map_.end(); ++it) { |
2395 std::pair<GURL, std::string> key = it->first; | 2428 std::pair<GURL, std::string> key = it->first; |
2396 if (cookie.IncludeForRequestURL(key.first, opts) && | 2429 if (cookie.IncludeForRequestURL(key.first, opts) && |
2397 cookie.Name() == key.second) { | 2430 cookie.Name() == key.second) { |
2398 it->second->Notify(cookie, removed); | 2431 it->second->Notify(cookie, removed); |
2399 } | 2432 } |
2400 } | 2433 } |
2401 } | 2434 } |
2402 | 2435 |
2403 } // namespace net | 2436 } // namespace net |
OLD | NEW |