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

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

Issue 1939623002: Strict Secure Cookies re-implemented to be priority aware (Closed) Base URL: https://chromium.googlesource.com/chromium/src@master
Patch Set: Fix Windows build 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 | « net/cookies/cookie_monster.h ('k') | 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 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/cookies/cookie_monster.h ('k') | net/cookies/cookie_monster_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698