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

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: Rebase on ToT 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
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 bool IsCookieEligibleForEviction(CookiePriority current_priority_level,
313 bool protect_secure_cookies,
314 const CanonicalCookie* cookie) {
315 if (!cookie->IsSecure() || !protect_secure_cookies)
316 return cookie->Priority() <= current_priority_level;
317
318 // Special consideration has to be given for low-priority secure cookies since
319 // they are given lower prority than non-secure medium-priority and non-secure
320 // high-priority cookies. Thus, low-priority secure cookies may be evicted at
321 // a medium and high value of |current_priority_level|. Put another way,
322 // low-priority secure cookies are only protected when the current priority
323 // level is low.
324 if (current_priority_level == COOKIE_PRIORITY_LOW)
325 return false;
326
327 return cookie->Priority() == COOKIE_PRIORITY_LOW;
328 }
Mike West 2016/05/04 08:08:19 This is clever. It wasn't at all how I'd considere
jww 2016/05/05 18:56:26 Yay! Thanks.
329
312 } // namespace 330 } // namespace
313 331
314 CookieMonster::CookieMonster(PersistentCookieStore* store, 332 CookieMonster::CookieMonster(PersistentCookieStore* store,
315 CookieMonsterDelegate* delegate) 333 CookieMonsterDelegate* delegate)
316 : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) { 334 : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) {
317 } 335 }
318 336
319 CookieMonster::CookieMonster(PersistentCookieStore* store, 337 CookieMonster::CookieMonster(PersistentCookieStore* store,
320 CookieMonsterDelegate* delegate, 338 CookieMonsterDelegate* delegate,
321 int last_access_threshold_milliseconds) 339 int last_access_threshold_milliseconds)
(...skipping 1540 matching lines...) Expand 10 before | Expand all | Expand 10 after
1862 if (cookies_.count(key) > kDomainMaxCookies) { 1880 if (cookies_.count(key) > kDomainMaxCookies) {
1863 VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key; 1881 VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key;
1864 1882
1865 CookieItVector* cookie_its; 1883 CookieItVector* cookie_its;
1866 1884
1867 CookieItVector non_expired_cookie_its; 1885 CookieItVector non_expired_cookie_its;
1868 cookie_its = &non_expired_cookie_its; 1886 cookie_its = &non_expired_cookie_its;
1869 num_deleted += 1887 num_deleted +=
1870 GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its); 1888 GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its);
1871 1889
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);
Mike West 2016/05/04 08:08:19 Nit: I think this was the only callsite to `Garbag
jww 2016/05/05 18:56:26 Done.
1878 cookie_its = &secure_cookie_its;
1879 }
1880
1881 if (cookie_its->size() > kDomainMaxCookies) { 1890 if (cookie_its->size() > kDomainMaxCookies) {
1882 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain."; 1891 VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain.";
1883 size_t purge_goal = 1892 size_t purge_goal =
1884 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies); 1893 cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
1885 DCHECK(purge_goal > kDomainPurgeCookies); 1894 DCHECK(purge_goal > kDomainPurgeCookies);
1886 1895
1887 // Sort the cookies by access date, from least-recent to most-recent. 1896 // Sort the cookies by access date, from least-recent to most-recent.
1888 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter); 1897 std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter);
1889 1898
1890 // Remove all but the kDomainCookiesQuotaLow most-recently accessed 1899 // Remove all but the kDomainCookiesQuotaLow most-recently accessed
1891 // cookies with low-priority. Then, if cookies still need to be removed, 1900 // 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 1901 // 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 1902 // _still_ need to be removed, bump the quota and remove cookies with
1894 // any priority. 1903 // any priority.
1895 const size_t kQuotas[3] = {kDomainCookiesQuotaLow, 1904 //
1896 kDomainCookiesQuotaMedium, 1905 // 1. Low-priority non-secure cookies.
1897 kDomainCookiesQuotaHigh}; 1906 // 2. Low-priority secure cookies.
1907 // 3. Medium-priority non-secure cookies.
1908 // 4. High-priority non-secure cookies.
1909 // 5. Medium-priority secure cookies.
1910 // 6. High-priority secure cookies.
1911 const static struct {
1912 CookiePriority priority;
1913 size_t quota;
Mike West 2016/05/04 08:08:19 Nit: Maybe "additionalQuota"? I missed the `+=` bi
jww 2016/05/05 18:56:26 Done.
1914 bool protect_secure_cookies;
1915 } purge_rounds[] = {
1916 // 1. Low-priority non-secure cookies.
1917 {COOKIE_PRIORITY_LOW, kDomainCookiesQuotaLow, true},
1918 // 2. Low-priority secure cookies.
1919 {COOKIE_PRIORITY_LOW, 0U, false},
Mike West 2016/05/04 08:08:19 Tiny nit: lowercase 'u', here and below.
jww 2016/05/05 18:56:26 Done.
1920 // 3. Medium-priority non-secure cookies.
1921 {COOKIE_PRIORITY_MEDIUM, kDomainCookiesQuotaMedium, true},
1922 // 4. High-priority non-secure cookies.
1923 {COOKIE_PRIORITY_HIGH, kDomainCookiesQuotaHigh, true},
1924 // 5. Medium-priority secure cookies.
1925 {COOKIE_PRIORITY_MEDIUM, 0U, false},
1926 // 6. High-priority secure cookies.
1927 {COOKIE_PRIORITY_HIGH, 0U, false},
1928 };
1929
1898 size_t quota = 0; 1930 size_t quota = 0;
1899 for (size_t i = 0; i < arraysize(kQuotas) && purge_goal > 0; i++) { 1931 for (size_t i = 0; i < arraysize(purge_rounds) && purge_goal > 0; i++) {
Mike West 2016/05/04 08:08:19 Nit: C++11 `for`? We'd used a regular `for` loop i
jww 2016/05/05 18:56:26 Done.
1900 quota += kQuotas[i]; 1932 quota += purge_rounds[i].quota;
1901 size_t just_deleted = PurgeLeastRecentMatches( 1933 size_t just_deleted = 0u;
1902 cookie_its, static_cast<CookiePriority>(i), quota, purge_goal); 1934
1903 DCHECK_LE(just_deleted, purge_goal); 1935 // Only observe the non-secure purge rounds if strict secure cookies is
1904 purge_goal -= just_deleted; 1936 // enabled.
1905 num_deleted += just_deleted; 1937 if (!enforce_strict_secure && purge_rounds[i].protect_secure_cookies)
1938 continue;
1939
1940 // Purge up to |purge_goal| for all cookies at the given priority. This
1941 // path will always execute if strict secure cookies is disabled since
1942 // |purge_goal| must be positive because of the for-loop guard. If
1943 // strict secure cookies is enabled, this path will be taken only if the
1944 // initial non-secure purge did not evict enough cookies.
1945 if (purge_goal > 0) {
1946 just_deleted = PurgeLeastRecentMatches(
1947 cookie_its, purge_rounds[i].priority, quota, purge_goal,
1948 purge_rounds[i].protect_secure_cookies);
1949 DCHECK_LE(just_deleted, purge_goal);
1950 purge_goal -= just_deleted;
1951 num_deleted += just_deleted;
1952 }
1906 } 1953 }
1907 1954
1908 DCHECK_EQ(0U, purge_goal); 1955 DCHECK_EQ(0U, purge_goal);
1909 } 1956 }
1910 } 1957 }
1911 1958
1912 // Collect garbage for everything. With firefox style we want to preserve 1959 // Collect garbage for everything. With firefox style we want to preserve
1913 // cookies accessed in kSafeFromGlobalPurgeDays, otherwise evict. 1960 // cookies accessed in kSafeFromGlobalPurgeDays, otherwise evict.
1914 if (cookies_.size() > kMaxCookies && earliest_access_time_ < safe_date) { 1961 if (cookies_.size() > kMaxCookies && earliest_access_time_ < safe_date) {
1915 VLOG(kVlogGarbageCollection) << "GarbageCollect() everything"; 1962 VLOG(kVlogGarbageCollection) << "GarbageCollect() everything";
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1948 } 1995 }
1949 } 1996 }
1950 } 1997 }
1951 1998
1952 return num_deleted; 1999 return num_deleted;
1953 } 2000 }
1954 2001
1955 size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, 2002 size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
1956 CookiePriority priority, 2003 CookiePriority priority,
1957 size_t to_protect, 2004 size_t to_protect,
1958 size_t purge_goal) { 2005 size_t purge_goal,
2006 bool protect_secure_cookies) {
1959 DCHECK(thread_checker_.CalledOnValidThread()); 2007 DCHECK(thread_checker_.CalledOnValidThread());
1960 2008
1961 // Find the first protected cookie by walking down from the end of the list 2009 // 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 2010 // cookie list (most-recently accessed) until |to_protect| cookies that match
1963 // |priority| are found. 2011 // |priority| are found.
2012 //
2013 // If |protect_secure_cookies| is true, do a first pass that counts eligible
2014 // secure cookies at the specified priority as protected.
2015 if (protect_secure_cookies) {
2016 for (size_t i = 0; to_protect > 0 && i < cookies->size(); i++) {
2017 if (!cookies->at(i)->second->IsSecure())
2018 continue;
2019 // 1) At low-priority, only low-priority secure cookies are protected as
2020 // part of the quota.
2021 // 2) At medium-priority, only medium-priority secure cookies are
2022 // protected as part of the quota (low-priority secure cookies may be
2023 // deleted).
2024 // 3) At high-priority, medium-priority and high-priority secure cookies
2025 // are protected as part of the quota (low-priority secure cookies may
2026 // be deleted).
2027 CookiePriority cookie_priority = cookies->at(i)->second->Priority();
2028 switch (cookie_priority) {
2029 case COOKIE_PRIORITY_LOW:
2030 if (priority == COOKIE_PRIORITY_LOW)
2031 to_protect--;
2032 break;
2033 case COOKIE_PRIORITY_MEDIUM:
2034 case COOKIE_PRIORITY_HIGH:
2035 if (cookie_priority <= priority)
2036 to_protect--;
2037 break;
2038 }
2039 }
2040 }
Mike West 2016/05/04 08:08:19 Nit: This took me longer than I care to admit to w
jww 2016/05/05 18:56:26 Done.
2041
1964 size_t protection_boundary = cookies->size(); 2042 size_t protection_boundary = cookies->size();
1965 while (to_protect > 0 && protection_boundary > 0) { 2043 while (to_protect > 0 && protection_boundary > 0) {
1966 protection_boundary--; 2044 protection_boundary--;
1967 if (cookies->at(protection_boundary)->second->Priority() <= priority) 2045 if (cookies->at(protection_boundary)->second->Priority() <= priority)
1968 to_protect--; 2046 to_protect--;
1969 } 2047 }
1970 2048
1971 // Now, walk up from the beginning of the list (least-recently accessed) until 2049 // Now, walk up from the beginning of the list (least-recently accessed) until
1972 // |purge_goal| cookies are removed, or the iterator hits 2050 // |purge_goal| cookies are removed, or the iterator hits
1973 // |protection_boundary|. 2051 // |protection_boundary|.
1974 size_t removed = 0; 2052 size_t removed = 0;
1975 size_t current = 0; 2053 size_t current = 0;
1976 while (removed < purge_goal && current < protection_boundary) { 2054 while (removed < purge_goal && current < protection_boundary) {
1977 if (cookies->at(current)->second->Priority() <= priority) { 2055 const CanonicalCookie* current_cookie = cookies->at(current)->second;
2056 // Only delete the current cookie if the priority is less than or equal to
2057 // the current level. If it is equal to the current level, and secure
2058 // cookies are protected, only delete it if it is not secure.
2059 if (IsCookieEligibleForEviction(priority, protect_secure_cookies,
2060 current_cookie)) {
1978 InternalDeleteCookie(cookies->at(current), true, 2061 InternalDeleteCookie(cookies->at(current), true,
1979 DELETE_COOKIE_EVICTED_DOMAIN); 2062 DELETE_COOKIE_EVICTED_DOMAIN);
1980 cookies->erase(cookies->begin() + current); 2063 cookies->erase(cookies->begin() + current);
1981 removed++; 2064 removed++;
1982 2065
1983 // The call to 'erase' above shifts the contents of the vector, but 2066 // The call to 'erase' above shifts the contents of the vector, but
1984 // doesn't shift |protection_boundary|. Decrement that here to ensure that 2067 // doesn't shift |protection_boundary|. Decrement that here to ensure that
1985 // the correct set of cookies is protected. 2068 // the correct set of cookies is protected.
1986 protection_boundary--; 2069 protection_boundary--;
1987 } else { 2070 } else {
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
2332 it != hook_map_.end(); ++it) { 2415 it != hook_map_.end(); ++it) {
2333 std::pair<GURL, std::string> key = it->first; 2416 std::pair<GURL, std::string> key = it->first;
2334 if (cookie.IncludeForRequestURL(key.first, opts) && 2417 if (cookie.IncludeForRequestURL(key.first, opts) &&
2335 cookie.Name() == key.second) { 2418 cookie.Name() == key.second) {
2336 it->second->Notify(cookie, removed); 2419 it->second->Notify(cookie, removed);
2337 } 2420 }
2338 } 2421 }
2339 } 2422 }
2340 2423
2341 } // namespace net 2424 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698