| 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 |
| 343 bool IsCookieEligibleForEviction(CookiePriority current_priority_level, |
| 344 bool protect_secure_cookies, |
| 345 const CanonicalCookie* cookie) { |
| 346 if (!cookie->IsSecure() || !protect_secure_cookies) |
| 347 return cookie->Priority() <= current_priority_level; |
| 348 |
| 349 // Special consideration has to be given for low-priority secure cookies since |
| 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; |
| 357 |
| 358 return cookie->Priority() == COOKIE_PRIORITY_LOW; |
| 359 } |
| 360 |
| 312 } // namespace | 361 } // namespace |
| 313 | 362 |
| 314 CookieMonster::CookieMonster(PersistentCookieStore* store, | 363 CookieMonster::CookieMonster(PersistentCookieStore* store, |
| 315 CookieMonsterDelegate* delegate) | 364 CookieMonsterDelegate* delegate) |
| 316 : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) { | 365 : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) { |
| 317 } | 366 } |
| 318 | 367 |
| 319 CookieMonster::CookieMonster(PersistentCookieStore* store, | 368 CookieMonster::CookieMonster(PersistentCookieStore* store, |
| 320 CookieMonsterDelegate* delegate, | 369 CookieMonsterDelegate* delegate, |
| 321 int last_access_threshold_milliseconds) | 370 int last_access_threshold_milliseconds) |
| (...skipping 1540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1862 if (cookies_.count(key) > kDomainMaxCookies) { | 1911 if (cookies_.count(key) > kDomainMaxCookies) { |
| 1863 VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key; | 1912 VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key; |
| 1864 | 1913 |
| 1865 CookieItVector* cookie_its; | 1914 CookieItVector* cookie_its; |
| 1866 | 1915 |
| 1867 CookieItVector non_expired_cookie_its; | 1916 CookieItVector non_expired_cookie_its; |
| 1868 cookie_its = &non_expired_cookie_its; | 1917 cookie_its = &non_expired_cookie_its; |
| 1869 num_deleted += | 1918 num_deleted += |
| 1870 GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its); | 1919 GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its); |
| 1871 | 1920 |
| 1872 // TODO(mkwst): Soften this. | |
| 1873 CookieItVector secure_cookie_its; | |
| 1874 if (enforce_strict_secure && cookie_its->size() > kDomainMaxCookies) { | |
| 1875 VLOG(kVlogGarbageCollection) << "Garbage collecting non-Secure cookies."; | |
| 1876 num_deleted += | |
| 1877 GarbageCollectNonSecure(non_expired_cookie_its, &secure_cookie_its); | |
| 1878 cookie_its = &secure_cookie_its; | |
| 1879 } | |
| 1880 | |
| 1881 if (cookie_its->size() > kDomainMaxCookies) { | 1921 if (cookie_its->size() > kDomainMaxCookies) { |
| 1882 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain."; | 1922 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain."; |
| 1883 size_t purge_goal = | 1923 size_t purge_goal = |
| 1884 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies); | 1924 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies); |
| 1885 DCHECK(purge_goal > kDomainPurgeCookies); | 1925 DCHECK(purge_goal > kDomainPurgeCookies); |
| 1886 | 1926 |
| 1887 // Sort the cookies by access date, from least-recent to most-recent. | 1927 // Sort the cookies by access date, from least-recent to most-recent. |
| 1888 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter); | 1928 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter); |
| 1889 | 1929 |
| 1930 size_t additional_quota_low = kDomainCookiesQuotaLow; |
| 1931 size_t additional_quota_medium = kDomainCookiesQuotaMedium; |
| 1932 size_t additional_quota_high = kDomainCookiesQuotaHigh; |
| 1933 |
| 1890 // Remove all but the kDomainCookiesQuotaLow most-recently accessed | 1934 // Remove all but the kDomainCookiesQuotaLow most-recently accessed |
| 1891 // cookies with low-priority. Then, if cookies still need to be removed, | 1935 // cookies with low-priority. Then, if cookies still need to be removed, |
| 1892 // bump the quota and remove low- and medium-priority. Then, if cookies | 1936 // bump the quota and remove low- and medium-priority. Then, if cookies |
| 1893 // _still_ need to be removed, bump the quota and remove cookies with | 1937 // _still_ need to be removed, bump the quota and remove cookies with |
| 1894 // any priority. | 1938 // any priority. |
| 1895 const size_t kQuotas[3] = {kDomainCookiesQuotaLow, | 1939 // |
| 1896 kDomainCookiesQuotaMedium, | 1940 // 1. Low-priority non-secure cookies. |
| 1897 kDomainCookiesQuotaHigh}; | 1941 // 2. Low-priority secure cookies. |
| 1942 // 3. Medium-priority non-secure cookies. |
| 1943 // 4. High-priority non-secure cookies. |
| 1944 // 5. Medium-priority secure cookies. |
| 1945 // 6. High-priority secure cookies. |
| 1946 const static struct { |
| 1947 CookiePriority priority; |
| 1948 bool protect_secure_cookies; |
| 1949 } purge_rounds[] = { |
| 1950 // 1. Low-priority non-secure cookies. |
| 1951 {COOKIE_PRIORITY_LOW, true}, |
| 1952 // 2. Low-priority secure cookies. |
| 1953 {COOKIE_PRIORITY_LOW, false}, |
| 1954 // 3. Medium-priority non-secure cookies. |
| 1955 {COOKIE_PRIORITY_MEDIUM, true}, |
| 1956 // 4. High-priority non-secure cookies. |
| 1957 {COOKIE_PRIORITY_HIGH, true}, |
| 1958 // 5. Medium-priority secure cookies. |
| 1959 {COOKIE_PRIORITY_MEDIUM, false}, |
| 1960 // 6. High-priority secure cookies. |
| 1961 {COOKIE_PRIORITY_HIGH, false}, |
| 1962 }; |
| 1963 |
| 1898 size_t quota = 0; | 1964 size_t quota = 0; |
| 1899 for (size_t i = 0; i < arraysize(kQuotas) && purge_goal > 0; i++) { | 1965 for (const auto& purge_round : purge_rounds) { |
| 1900 quota += kQuotas[i]; | 1966 // Only observe the non-secure purge rounds if strict secure cookies is |
| 1901 size_t just_deleted = PurgeLeastRecentMatches( | 1967 // enabled. |
| 1902 cookie_its, static_cast<CookiePriority>(i), quota, purge_goal); | 1968 if (!enforce_strict_secure && purge_round.protect_secure_cookies) |
| 1903 DCHECK_LE(just_deleted, purge_goal); | 1969 continue; |
| 1904 purge_goal -= just_deleted; | 1970 |
| 1905 num_deleted += just_deleted; | 1971 // Only adjust the quota if the round is executing, otherwise it is |
| 1972 // necesary to delay quota adjustments until a later round. This is |
| 1973 // because if the high priority, non-secure round is skipped, its quota |
| 1974 // should not count until the later high priority, full round later. |
| 1975 size_t* additional_quota = nullptr; |
| 1976 switch (purge_round.priority) { |
| 1977 case COOKIE_PRIORITY_LOW: |
| 1978 additional_quota = &additional_quota_low; |
| 1979 break; |
| 1980 case COOKIE_PRIORITY_MEDIUM: |
| 1981 additional_quota = &additional_quota_medium; |
| 1982 break; |
| 1983 case COOKIE_PRIORITY_HIGH: |
| 1984 additional_quota = &additional_quota_high; |
| 1985 break; |
| 1986 } |
| 1987 quota += *additional_quota; |
| 1988 *additional_quota = 0u; |
| 1989 size_t just_deleted = 0u; |
| 1990 |
| 1991 // 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 |
| 1993 // |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 |
| 1995 // initial non-secure purge did not evict enough cookies. |
| 1996 if (purge_goal > 0) { |
| 1997 just_deleted = PurgeLeastRecentMatches( |
| 1998 cookie_its, purge_round.priority, quota, purge_goal, |
| 1999 purge_round.protect_secure_cookies); |
| 2000 DCHECK_LE(just_deleted, purge_goal); |
| 2001 purge_goal -= just_deleted; |
| 2002 num_deleted += just_deleted; |
| 2003 } |
| 1906 } | 2004 } |
| 1907 | 2005 |
| 1908 DCHECK_EQ(0U, purge_goal); | 2006 DCHECK_EQ(0u, purge_goal); |
| 1909 } | 2007 } |
| 1910 } | 2008 } |
| 1911 | 2009 |
| 1912 // Collect garbage for everything. With firefox style we want to preserve | 2010 // Collect garbage for everything. With firefox style we want to preserve |
| 1913 // cookies accessed in kSafeFromGlobalPurgeDays, otherwise evict. | 2011 // cookies accessed in kSafeFromGlobalPurgeDays, otherwise evict. |
| 1914 if (cookies_.size() > kMaxCookies && earliest_access_time_ < safe_date) { | 2012 if (cookies_.size() > kMaxCookies && earliest_access_time_ < safe_date) { |
| 1915 VLOG(kVlogGarbageCollection) << "GarbageCollect() everything"; | 2013 VLOG(kVlogGarbageCollection) << "GarbageCollect() everything"; |
| 1916 CookieItVector cookie_its; | 2014 CookieItVector cookie_its; |
| 1917 | 2015 |
| 1918 num_deleted += GarbageCollectExpired( | 2016 num_deleted += GarbageCollectExpired( |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1948 } | 2046 } |
| 1949 } | 2047 } |
| 1950 } | 2048 } |
| 1951 | 2049 |
| 1952 return num_deleted; | 2050 return num_deleted; |
| 1953 } | 2051 } |
| 1954 | 2052 |
| 1955 size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, | 2053 size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, |
| 1956 CookiePriority priority, | 2054 CookiePriority priority, |
| 1957 size_t to_protect, | 2055 size_t to_protect, |
| 1958 size_t purge_goal) { | 2056 size_t purge_goal, |
| 2057 bool protect_secure_cookies) { |
| 1959 DCHECK(thread_checker_.CalledOnValidThread()); | 2058 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1960 | 2059 |
| 1961 // Find the first protected cookie by walking down from the end of the list | 2060 // Find the first protected cookie by walking down from the end of the list |
| 1962 // cookie list (most-recently accessed) until |to_protect| cookies that match | 2061 // cookie list (most-recently accessed) until |to_protect| cookies that match |
| 1963 // |priority| are found. | 2062 // |priority| are found. |
| 2063 // |
| 2064 // If |protect_secure_cookies| is true, do a first pass that counts eligible |
| 2065 // secure cookies at the specified priority as protected. |
| 2066 if (protect_secure_cookies) { |
| 2067 to_protect -= std::min( |
| 2068 to_protect, CountProtectedSecureCookiesAtPriority(priority, cookies)); |
| 2069 } |
| 2070 |
| 1964 size_t protection_boundary = cookies->size(); | 2071 size_t protection_boundary = cookies->size(); |
| 1965 while (to_protect > 0 && protection_boundary > 0) { | 2072 while (to_protect > 0 && protection_boundary > 0) { |
| 1966 protection_boundary--; | 2073 protection_boundary--; |
| 1967 if (cookies->at(protection_boundary)->second->Priority() <= priority) | 2074 if (cookies->at(protection_boundary)->second->Priority() <= priority) |
| 1968 to_protect--; | 2075 to_protect--; |
| 1969 } | 2076 } |
| 1970 | 2077 |
| 1971 // Now, walk up from the beginning of the list (least-recently accessed) until | 2078 // Now, walk up from the beginning of the list (least-recently accessed) until |
| 1972 // |purge_goal| cookies are removed, or the iterator hits | 2079 // |purge_goal| cookies are removed, or the iterator hits |
| 1973 // |protection_boundary|. | 2080 // |protection_boundary|. |
| 1974 size_t removed = 0; | 2081 size_t removed = 0; |
| 1975 size_t current = 0; | 2082 size_t current = 0; |
| 1976 while (removed < purge_goal && current < protection_boundary) { | 2083 while (removed < purge_goal && current < protection_boundary) { |
| 1977 if (cookies->at(current)->second->Priority() <= priority) { | 2084 const CanonicalCookie* current_cookie = cookies->at(current)->second; |
| 2085 // Only delete the current cookie if the priority is less than or equal to |
| 2086 // the current level. If it is equal to the current level, and secure |
| 2087 // cookies are protected, only delete it if it is not secure. |
| 2088 if (IsCookieEligibleForEviction(priority, protect_secure_cookies, |
| 2089 current_cookie)) { |
| 1978 InternalDeleteCookie(cookies->at(current), true, | 2090 InternalDeleteCookie(cookies->at(current), true, |
| 1979 DELETE_COOKIE_EVICTED_DOMAIN); | 2091 DELETE_COOKIE_EVICTED_DOMAIN); |
| 1980 cookies->erase(cookies->begin() + current); | 2092 cookies->erase(cookies->begin() + current); |
| 1981 removed++; | 2093 removed++; |
| 1982 | 2094 |
| 1983 // The call to 'erase' above shifts the contents of the vector, but | 2095 // The call to 'erase' above shifts the contents of the vector, but |
| 1984 // doesn't shift |protection_boundary|. Decrement that here to ensure that | 2096 // doesn't shift |protection_boundary|. Decrement that here to ensure that |
| 1985 // the correct set of cookies is protected. | 2097 // the correct set of cookies is protected. |
| 1986 protection_boundary--; | 2098 protection_boundary--; |
| 1987 } else { | 2099 } else { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2005 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED); | 2117 InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED); |
| 2006 ++num_deleted; | 2118 ++num_deleted; |
| 2007 } else if (cookie_its) { | 2119 } else if (cookie_its) { |
| 2008 cookie_its->push_back(curit); | 2120 cookie_its->push_back(curit); |
| 2009 } | 2121 } |
| 2010 } | 2122 } |
| 2011 | 2123 |
| 2012 return num_deleted; | 2124 return num_deleted; |
| 2013 } | 2125 } |
| 2014 | 2126 |
| 2015 size_t CookieMonster::GarbageCollectNonSecure( | |
| 2016 const CookieItVector& valid_cookies, | |
| 2017 CookieItVector* cookie_its) { | |
| 2018 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 2019 | |
| 2020 size_t num_deleted = 0; | |
| 2021 for (const auto& curr_cookie_it : valid_cookies) { | |
| 2022 if (!curr_cookie_it->second->IsSecure()) { | |
| 2023 InternalDeleteCookie(curr_cookie_it, true, DELETE_COOKIE_NON_SECURE); | |
| 2024 ++num_deleted; | |
| 2025 } else if (cookie_its) { | |
| 2026 cookie_its->push_back(curr_cookie_it); | |
| 2027 } | |
| 2028 } | |
| 2029 | |
| 2030 return num_deleted; | |
| 2031 } | |
| 2032 | |
| 2033 size_t CookieMonster::GarbageCollectDeleteRange( | 2127 size_t CookieMonster::GarbageCollectDeleteRange( |
| 2034 const Time& current, | 2128 const Time& current, |
| 2035 DeletionCause cause, | 2129 DeletionCause cause, |
| 2036 CookieItVector::iterator it_begin, | 2130 CookieItVector::iterator it_begin, |
| 2037 CookieItVector::iterator it_end) { | 2131 CookieItVector::iterator it_end) { |
| 2038 DCHECK(thread_checker_.CalledOnValidThread()); | 2132 DCHECK(thread_checker_.CalledOnValidThread()); |
| 2039 | 2133 |
| 2040 for (CookieItVector::iterator it = it_begin; it != it_end; it++) { | 2134 for (CookieItVector::iterator it = it_begin; it != it_end; it++) { |
| 2041 histogram_evicted_last_access_minutes_->Add( | 2135 histogram_evicted_last_access_minutes_->Add( |
| 2042 (current - (*it)->second->LastAccessDate()).InMinutes()); | 2136 (current - (*it)->second->LastAccessDate()).InMinutes()); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2332 it != hook_map_.end(); ++it) { | 2426 it != hook_map_.end(); ++it) { |
| 2333 std::pair<GURL, std::string> key = it->first; | 2427 std::pair<GURL, std::string> key = it->first; |
| 2334 if (cookie.IncludeForRequestURL(key.first, opts) && | 2428 if (cookie.IncludeForRequestURL(key.first, opts) && |
| 2335 cookie.Name() == key.second) { | 2429 cookie.Name() == key.second) { |
| 2336 it->second->Notify(cookie, removed); | 2430 it->second->Notify(cookie, removed); |
| 2337 } | 2431 } |
| 2338 } | 2432 } |
| 2339 } | 2433 } |
| 2340 | 2434 |
| 2341 } // namespace net | 2435 } // namespace net |
| OLD | NEW |