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

Unified Diff: net/cookies/cookie_monster.cc

Issue 1767513004: Clean up cookie eviction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: mmenke@ Created 4 years, 9 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/cookies/cookie_monster.cc
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index c73e74aee7d2f4ae38e61053239b475930601e39..19a2d6ac7f81f99dca36e1ec8fc1f47e6c722b71 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -162,13 +162,10 @@ bool CookieSorter(CanonicalCookie* cc1, CanonicalCookie* cc2) {
bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1,
const CookieMonster::CookieMap::iterator& it2) {
- // Cookies accessed less recently should be deleted first.
if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
return it1->second->LastAccessDate() < it2->second->LastAccessDate();
- // In rare cases we might have two cookies with identical last access times.
- // To preserve the stability of the sort, in these cases prefer to delete
- // older cookies over newer ones. CreationDate() is guaranteed to be unique.
+ // Ensure stability for == last access times by falling back to creation.
return it1->second->CreationDate() < it2->second->CreationDate();
}
@@ -250,29 +247,6 @@ void SplitCookieVectorIntoSecureAndNonSecure(
}
}
-// Predicate to support PartitionCookieByPriority().
-struct CookiePriorityEqualsTo {
- explicit CookiePriorityEqualsTo(CookiePriority priority)
- : priority_(priority) {}
-
- bool operator()(const CookieMonster::CookieMap::iterator it) const {
- return it->second->Priority() == priority_;
- }
-
- const CookiePriority priority_;
-};
-
-// For a CookieItVector iterator range [|it_begin|, |it_end|),
-// moves all cookies with a given |priority| to the beginning of the list.
-// Returns: An iterator in [it_begin, it_end) to the first element with
-// priority != |priority|, or |it_end| if all have priority == |priority|.
-CookieMonster::CookieItVector::iterator PartitionCookieByPriority(
- CookieMonster::CookieItVector::iterator it_begin,
- CookieMonster::CookieItVector::iterator it_end,
- CookiePriority priority) {
- return std::partition(it_begin, it_end, CookiePriorityEqualsTo(priority));
-}
-
bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it,
const Time& access_date) {
return it->second->LastAccessDate() < access_date;
@@ -1898,6 +1872,7 @@ size_t CookieMonster::GarbageCollect(const Time& current,
num_deleted +=
GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its);
+ // TODO(mkwst): Soften this.
CookieItVector secure_cookie_its;
if (enforce_strict_secure && cookie_its->size() > kDomainMaxCookies) {
VLOG(kVlogGarbageCollection) << "Garbage collecting non-Secure cookies.";
@@ -1912,56 +1887,28 @@ size_t CookieMonster::GarbageCollect(const Time& current,
cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
DCHECK(purge_goal > kDomainPurgeCookies);
- // Boundary iterators into |cookie_its| for different priorities.
- CookieItVector::iterator it_bdd[4];
- // Intialize |it_bdd| while sorting |cookie_its| by priorities.
- // Schematic: [MLLHMHHLMM] => [LLL|MMMM|HHH], with 4 boundaries.
- it_bdd[0] = cookie_its->begin();
- it_bdd[3] = cookie_its->end();
- it_bdd[1] =
- PartitionCookieByPriority(it_bdd[0], it_bdd[3], COOKIE_PRIORITY_LOW);
- it_bdd[2] = PartitionCookieByPriority(it_bdd[1], it_bdd[3],
- COOKIE_PRIORITY_MEDIUM);
- size_t quota[3] = {kDomainCookiesQuotaLow,
- kDomainCookiesQuotaMedium,
- kDomainCookiesQuotaHigh};
-
- // Purge domain cookies in 3 rounds.
- // Round 1: consider low-priority cookies only: evict least-recently
- // accessed, while protecting quota[0] of these from deletion.
- // Round 2: consider {low, medium}-priority cookies, evict least-recently
- // accessed, while protecting quota[0] + quota[1].
- // Round 3: consider all cookies, evict least-recently accessed.
- size_t accumulated_quota = 0;
- CookieItVector::iterator it_purge_begin = it_bdd[0];
- for (int i = 0; i < 3 && purge_goal > 0; ++i) {
- accumulated_quota += quota[i];
-
- size_t num_considered = it_bdd[i + 1] - it_purge_begin;
- if (num_considered <= accumulated_quota)
- continue;
-
- // Number of cookies that will be purged in this round.
- size_t round_goal =
- std::min(purge_goal, num_considered - accumulated_quota);
- purge_goal -= round_goal;
-
- SortLeastRecentlyAccessed(it_purge_begin, it_bdd[i + 1], round_goal);
- // Cookies accessed on or after |safe_date| would have been safe from
- // global purge, and we want to keep track of this.
- CookieItVector::iterator it_purge_end = it_purge_begin + round_goal;
- CookieItVector::iterator it_purge_middle =
- LowerBoundAccessDate(it_purge_begin, it_purge_end, safe_date);
- // Delete cookies accessed before |safe_date|.
- num_deleted += GarbageCollectDeleteRange(
- current, DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE, it_purge_begin,
- it_purge_middle);
- // Delete cookies accessed on or after |safe_date|.
- num_deleted += GarbageCollectDeleteRange(
- current, DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE, it_purge_middle,
- it_purge_end);
- it_purge_begin = it_purge_end;
+ // Sort the cookies by access date, from least-recent to most-recent.
+ std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter);
+
+ // Remove all but the kDomainCookiesQuotaLow most-recently accessed
+ // cookies with low-priority. Then, if cookies still need to be removed,
+ // bump the quota and remove low- and medium-priority. Then, if cookies
+ // _still_ need to be removed, bump the quota and remove cookies with
+ // any priority.
+ const size_t kQuotas[3] = {kDomainCookiesQuotaLow,
+ kDomainCookiesQuotaMedium,
+ kDomainCookiesQuotaHigh};
+ size_t quota = 0;
+ for (size_t i = 0; i < arraysize(kQuotas) && purge_goal > 0; i++) {
+ quota += kQuotas[i];
+ size_t just_deleted =
+ PurgeLeastRecentMatches(cookie_its, static_cast<CookiePriority>(i),
+ quota, purge_goal, safe_date);
+ DCHECK_LE(just_deleted, purge_goal);
+ purge_goal -= just_deleted;
+ num_deleted += just_deleted;
}
+
DCHECK_EQ(0U, purge_goal);
}
}
@@ -2009,6 +1956,49 @@ size_t CookieMonster::GarbageCollect(const Time& current,
return num_deleted;
}
+size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
+ CookiePriority priority,
+ size_t to_protect,
+ size_t purge_goal,
+ const base::Time& safe_date) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Find the first protected cookie by walking down from the end of the list
+ // cookie list (most-recently accessed) until |to_protect| cookies that match
+ // |priority| are found.
+ size_t protection_boundary = cookies->size();
+ while (to_protect > 0 && protection_boundary > 0) {
+ protection_boundary--;
+ if (cookies->at(protection_boundary)->second->Priority() <= priority)
+ to_protect--;
+ }
+
+ // Now, walk up from the beginning of the list (least-recently accessed) until
+ // |purge_goal| cookies are removed, or the iterator hits
+ // |protection_boundary|.
+ size_t removed = 0;
+ size_t current = 0;
+ while (removed < purge_goal && current < protection_boundary) {
+ if (cookies->at(current)->second->Priority() <= priority) {
+ InternalDeleteCookie(
+ cookies->at(current), true,
+ cookies->at(current)->second->LastAccessDate() > safe_date
+ ? DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE
+ : DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE);
+ cookies->erase(cookies->begin() + current);
+ removed++;
+
+ // The call to 'erase' above shifts the contents of the vector, but
+ // doesn't shift |protection_boundary|. Decrement that here to ensure that
+ // the correct set of cookies is protected.
+ protection_boundary--;
+ } else {
+ current++;
+ }
+ }
+ return removed;
+}
+
size_t CookieMonster::GarbageCollectExpired(const Time& current,
const CookieMapItPair& itpair,
CookieItVector* cookie_its) {
« 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