diff options
author | mkwst <mkwst@chromium.org> | 2016-03-03 09:36:23 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-03 17:37:31 +0000 |
commit | 8773435ab4441ce8f78611b694e92659e9b50a63 (patch) | |
tree | 81d8f1a8eecc1ecebafa5a51d57fa59bd5fd7aec /net/cookies | |
parent | 95fce647f4a7255235418dcad030927cc4724b78 (diff) | |
download | chromium_src-8773435ab4441ce8f78611b694e92659e9b50a63.zip chromium_src-8773435ab4441ce8f78611b694e92659e9b50a63.tar.gz chromium_src-8773435ab4441ce8f78611b694e92659e9b50a63.tar.bz2 |
Revert of Evict non-secure cookies less agressively. (patchset #4 id:60001 of https://codereview.chromium.org/1705753002/ )
Reason for revert:
Let's see if the automagical reversion thingie will work on a ~2 week old patch.
```
I updated the eviction algorithm with our initial pass at a merger between leave-secure-cookies-along and cookie-priorities, and neglected to ensure that that new algorithm was safely locked up behind the "strict secure cookies" experiment. That patch is in M50.
I think the right thing to do is to revert https://codereview.chromium.org/1705753002 on the M50 branch so that we retain the status quo behavior for beta. That means that we're going to have to wait a bit longer to start ratcheting down on cookies, which is unfortunate, but the safe choice this late in the game.
```
BUG=591720
Original issue's description:
> Evict non-secure cookies less agressively.
>
> The current implementation of strict-secure cookies wipes all non-secure
> cookies when an origin exceeds ~180. This is a bit agressive, and has
> real impact on users.
>
> This patch softens that to remove only the number of non-secure cookies
> necessary to get under the ~150 cap. If a user has 150 secure cookies,
> we'll still wipe all non-secure cookies, but that seems less likely to
> impact users than the current behavior.
>
> The patch is a bit more complicated than I expected due to interactions
> with the Chrome-only "priority" feature we shipped back in 2013. In
> short, we execute priority-driven removal of non-secure cookies first,
> and only touch secure cookies if necessary.
>
> BUG=581588
> R=mmenke@chromium.org, jww@chromium.org
>
> Committed: https://crrev.com/162d27135f2ee44ae01341de055d1b827a930767
> Cr-Commit-Position: refs/heads/master@{#376204}
TBR=jww@chromium.org,mmenke@chromium.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=581588
Review URL: https://codereview.chromium.org/1762693002
Cr-Commit-Position: refs/heads/master@{#379030}
Diffstat (limited to 'net/cookies')
-rw-r--r-- | net/cookies/cookie_monster.cc | 252 | ||||
-rw-r--r-- | net/cookies/cookie_monster.h | 31 | ||||
-rw-r--r-- | net/cookies/cookie_monster_unittest.cc | 293 |
3 files changed, 157 insertions, 419 deletions
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index e9eccd2..1d38146 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc @@ -111,10 +111,11 @@ const size_t CookieMonster::kDomainPurgeCookies = 30; const size_t CookieMonster::kMaxCookies = 3300; const size_t CookieMonster::kPurgeCookies = 300; -const double CookieMonster::kDomainCookiesQuotaLow = 0.2; -const double CookieMonster::kDomainCookiesQuotaMedium = 0.333333333333333333333; -const double CookieMonster::kDomainCookiesQuotaHigh = - 1 - kDomainCookiesQuotaLow - kDomainCookiesQuotaMedium; +const size_t CookieMonster::kDomainCookiesQuotaLow = 30; +const size_t CookieMonster::kDomainCookiesQuotaMedium = 50; +const size_t CookieMonster::kDomainCookiesQuotaHigh = + kDomainMaxCookies - kDomainPurgeCookies - kDomainCookiesQuotaLow - + kDomainCookiesQuotaMedium; const int CookieMonster::kSafeFromGlobalPurgeDays = 30; @@ -249,6 +250,19 @@ void SplitCookieVectorIntoSecureAndNonSecure( } } +// Predicate to support PartitionCookieByPriority(). +struct CookiePriorityEqualsTo + : std::unary_function<const CookieMonster::CookieMap::iterator, bool> { + 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 @@ -257,11 +271,7 @@ CookieMonster::CookieItVector::iterator PartitionCookieByPriority( CookieMonster::CookieItVector::iterator it_begin, CookieMonster::CookieItVector::iterator it_end, CookiePriority priority) { - return std::partition( - it_begin, it_end, - [priority](const CookieMonster::CookieMap::iterator& it) { - return it->second->Priority() == priority; - }); + return std::partition(it_begin, it_end, CookiePriorityEqualsTo(priority)); } bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it, @@ -1858,113 +1868,77 @@ size_t CookieMonster::GarbageCollect(const Time& current, if (cookies_.count(key) > kDomainMaxCookies) { VLOG(kVlogGarbageCollection) << "GarbageCollect() key: " << key; - CookieItVector cookie_its; + CookieItVector* cookie_its; - // First, we purge all expired cookies for this key (regardless of our - // target number of cookies, as we have no need to keep expired cookies - // around). + CookieItVector non_expired_cookie_its; + cookie_its = &non_expired_cookie_its; num_deleted += - GarbageCollectExpired(current, cookies_.equal_range(key), &cookie_its); - - if (cookie_its.size() > kDomainMaxCookies) { - // Then, if we're over the maximum allowed for this key, we'll remove - // cookies in the following order: - // - // 1. Low-priority non-secure cookies. - // 2. Medium-priority non-secure cookies. - // 3. High-priority non-secure cookies. - // 4. Low-priority secure cookies. - // 5. Medium-priority secure cookies. - // 6. High-priority secure cookies. - // - // Note that this implies that _all_ non-secure cookies will be removed - // before _any_ secure cookie is removed, in accordance with - // https://tools.ietf.org/html/draft-west-leave-secure-cookies-alone + GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its); + + CookieItVector secure_cookie_its; + if (enforce_strict_secure && cookie_its->size() > kDomainMaxCookies) { + VLOG(kVlogGarbageCollection) << "Garbage collecting non-Secure cookies."; + num_deleted += + GarbageCollectNonSecure(non_expired_cookie_its, &secure_cookie_its); + cookie_its = &secure_cookie_its; + } + if (cookie_its->size() > kDomainMaxCookies) { VLOG(kVlogGarbageCollection) << "Deep Garbage Collect domain."; size_t purge_goal = - cookie_its.size() - (kDomainMaxCookies - kDomainPurgeCookies); + cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies); DCHECK(purge_goal > kDomainPurgeCookies); - // To execute the above removals, we'll divide |cookies_its| into 6 - // partitions, using 7 boundaries (note that the last boundary is off the - // end of the list): - // - // If both non-secure and secure cookies are present, the list will look - // like this: - // - // LLLLMMMMHHHHHLLLLMMMMHHHH - // ^ ^ ^ ^ ^ ^ ^ - // 0 1 2 3 4 5 6 - // - // If only secure cookies are present, the list will look like this: - // - // LLLLMMMMHHHHH - // ^ ^ ^ ^ - // 0 4 5 6 - // 1 - // 2 - // 3 - // - // If only non-secure cookies are present, the list will look like this: - // - // LLLLMMMMHHHHH - // ^ ^ ^ ^ - // 0 1 2 3 - // 4 - // 5 - // 6 - CookieItVector::iterator it_bdd[7]; - it_bdd[0] = cookie_its.begin(); - it_bdd[1] = it_bdd[0]; - it_bdd[2] = it_bdd[0]; - it_bdd[3] = cookie_its.end(); - it_bdd[4] = it_bdd[3]; - it_bdd[5] = it_bdd[3]; - it_bdd[6] = it_bdd[3]; - - size_t num_nonsecure = 0; - - // Move all non-secure cookies to the front of the list, and set boundary - // #3 to the first secure cookie (or off the end of the list, in the case - // where no secure cookies are present). - it_bdd[3] = std::partition(it_bdd[0], it_bdd[6], - [](const CookieMap::iterator& it) { - return !it->second->IsSecure(); - }); - - // If we have non-secure cookies, partition them into priorities: - if (it_bdd[3] > it_bdd[0]) { - 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); - num_nonsecure = it_bdd[3] - it_bdd[0]; - } - - // Likewise, if we have secure cookies, partition them into priorities: - if (it_bdd[3] < it_bdd[6]) { - it_bdd[4] = PartitionCookieByPriority(it_bdd[3], it_bdd[6], - COOKIE_PRIORITY_LOW); - it_bdd[5] = PartitionCookieByPriority(it_bdd[4], it_bdd[6], - COOKIE_PRIORITY_MEDIUM); - } - - // Start with the non-secure cookies. - if (purge_goal >= num_nonsecure) { - // If we need to purge more cookies than we have non-secure, remove - // them all, update |purge_goal| then purge the new |purge_goal| from - // the secure cookies. + // 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_NON_SECURE, it_bdd[0], it_bdd[3]); - num_deleted += GarbageCollectNumFromRangeWithQuota( - current, safe_date, purge_goal - num_deleted, it_bdd, GC_SECURE); - } else { - num_deleted += GarbageCollectNumFromRangeWithQuota( - current, safe_date, purge_goal, it_bdd, GC_NONSECURE); + 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; } - purge_goal -= num_deleted; - DCHECK_EQ(0U, purge_goal); } } @@ -2012,70 +1986,6 @@ size_t CookieMonster::GarbageCollect(const Time& current, return num_deleted; } -size_t CookieMonster::GarbageCollectNumFromRangeWithQuota( - const Time& current, - const Time& safe_date, - size_t purge_goal, - CookieItVector::iterator* it_bdd, - GCType type) { - size_t num_deleted = 0; - size_t begin_partition = type == GC_SECURE ? 3 : 0; - size_t num_cookies = it_bdd[begin_partition + 3] - it_bdd[begin_partition]; - size_t num_to_keep = num_cookies - purge_goal; - size_t quota[3] = {std::floor(num_to_keep * kDomainCookiesQuotaLow), - std::floor(num_to_keep * kDomainCookiesQuotaMedium), - std::floor(num_to_keep * kDomainCookiesQuotaHigh)}; - - // The quota calculation will be up to 3 fewer than the number of - // cookies we can keep. Bump up the numbers to get the right answer: - if (quota[0] + quota[1] + quota[2] < num_to_keep) - quota[2] += 1; - if (quota[0] + quota[1] + quota[2] < num_to_keep) - quota[1] += 1; - if (quota[0] + quota[1] + quota[2] < num_to_keep) - quota[0] += 1; - DCHECK_EQ(num_to_keep, quota[0] + quota[1] + quota[2]); - - // 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[begin_partition]; - for (size_t i = 0; i < arraysize(quota) && purge_goal > 0; ++i) { - accumulated_quota += quota[i]; - - size_t num_considered = it_bdd[i + begin_partition + 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 + begin_partition + 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; - } - return num_deleted; -} - size_t CookieMonster::GarbageCollectExpired(const Time& current, const CookieMapItPair& itpair, CookieItVector* cookie_its) { diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h index 8c39440..8103b74 100644 --- a/net/cookies/cookie_monster.h +++ b/net/cookies/cookie_monster.h @@ -125,11 +125,9 @@ class NET_EXPORT CookieMonster : public CookieStore { static const size_t kPurgeCookies; // Quota for cookies with {low, medium, high} priorities within a domain. - // The quota is specified as a percentage of the total number of cookies we - // intend to retain for a domain. - static const double kDomainCookiesQuotaLow; - static const double kDomainCookiesQuotaMedium; - static const double kDomainCookiesQuotaHigh; + static const size_t kDomainCookiesQuotaLow; + static const size_t kDomainCookiesQuotaMedium; + static const size_t kDomainCookiesQuotaHigh; // The store passed in should not have had Init() called on it yet. This // class will take care of initializing it. The backing store is NOT owned by @@ -361,8 +359,6 @@ class NET_EXPORT CookieMonster : public CookieStore { COOKIE_DELETE_EQUIVALENT_LAST_ENTRY }; - enum GCType { GC_NONSECURE, GC_SECURE }; - // The strategy for fetching cookies. Controlled by Finch experiment. enum FetchStrategy { // Fetches all cookies only when they're needed. @@ -575,27 +571,6 @@ class NET_EXPORT CookieMonster : public CookieStore { size_t purge_goal, CookieItVector cookie_its); - // Helper for GarbageCollect(). Deletes |purge_goal| cookies of type |type| - // from the ranges specified in |it_bdd|. Returns the number of cookies - // deleted. - // - // |it_bdd| is a bit of a complicated beast: it must be a 7-element array - // of 'CookieItVector::Iterator' objects that demarcate the boundaries of - // a list of cookies sorted first by secure/non-secure, and then by priority, - // low to high. That is, it ought to look something like: - // - // LLLLMMMMHHHHHLLLLMMMMHHHH - // ^ ^ ^ ^ ^ ^ ^ - // 0 1 2 3 4 5 6 - // - // TODO(mkwst): This is super-complicated. We should determine whether we - // can simplify our implementation of "priority". - size_t GarbageCollectNumFromRangeWithQuota(const base::Time& current, - const base::Time& safe_date, - size_t purge_goal, - CookieItVector::iterator* it_bdd, - GCType type); - // Find the key (for lookup in cookies_) based on the given domain. // See comment on keys before the CookieMap typedef. std::string GetKey(const std::string& domain) const; diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index 4f64b2f..a92f2be 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc @@ -347,12 +347,11 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { // Instantiates a CookieMonster, adds multiple cookies (to http_www_google_) // with priorities specified by |coded_priority_str|, and tests priority-aware // domain cookie eviction. - // - // Example: |coded_priority_string| of "2MN 3LS MN 4HN" specifies sequential - // (i.e., from least- to most-recently accessed) insertion of 2 - // medium-priority non-secure cookies, 3 low-priority secure cookies, 1 - // medium-priority non-secure cookie, and 4 high-priority non-secure cookies. - // + // |coded_priority_str| specifies a run-length-encoded string of priorities. + // Example: "2M 3L M 4H" means "MMLLLMHHHH", and speicifies sequential (i.e., + // from least- to most-recently accessed) insertion of 2 medium-priority + // cookies, 3 low-priority cookies, 1 medium-priority cookie, and 4 + // high-priority cookies. // Within each priority, only the least-accessed cookies should be evicted. // Thus, to describe expected suriving cookies, it suffices to specify the // expected population of surviving cookies per priority, i.e., @@ -361,55 +360,41 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { const std::string& coded_priority_str, size_t expected_low_count, size_t expected_medium_count, - size_t expected_high_count, - size_t expected_nonsecure, - size_t expected_secure) { - SCOPED_TRACE(coded_priority_str.c_str()); + size_t expected_high_count) { this->DeleteAll(cm); int next_cookie_id = 0; - // A list of cookie IDs, indexed by secure status, then by priority. - std::vector<int> id_list[2][3]; - // A list of all the cookies stored, along with their properties. - std::vector<std::pair<bool, CookiePriority>> cookie_data; + std::vector<CookiePriority> priority_list; + std::vector<int> id_list[3]; // Indexed by CookiePriority. // Parse |coded_priority_str| and add cookies. for (const std::string& token : base::SplitString(coded_priority_str, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { DCHECK(!token.empty()); - - // Take last character as security status, then discard it. - bool is_secure = token[token.size() - 1] == 'S'; - - // The second-to-last character is the priority. Grab and discard it. - CookiePriority priority = CharToPriority(token[token.size() - 2]); - + // Take last character as priority. + CookiePriority priority = CharToPriority(token.back()); + std::string priority_str = CookiePriorityToString(priority); // The rest of the string (possibly empty) specifies repetition. int rep = 1; if (!token.empty()) { bool result = base::StringToInt( - base::StringPiece(token.begin(), token.end() - 2), &rep); + base::StringPiece(token.begin(), token.end() - 1), &rep); DCHECK(result); } for (; rep > 0; --rep, ++next_cookie_id) { - std::string cookie = - base::StringPrintf("a%d=b;priority=%s;%s", next_cookie_id, - CookiePriorityToString(priority).c_str(), - is_secure ? "secure" : ""); - EXPECT_TRUE(SetCookie(cm, https_www_google_.url(), cookie)); - cookie_data.push_back(std::make_pair(is_secure, priority)); - id_list[is_secure][priority].push_back(next_cookie_id); + std::string cookie = base::StringPrintf( + "a%d=b;priority=%s", next_cookie_id, priority_str.c_str()); + EXPECT_TRUE(SetCookie(cm, http_www_google_.url(), cookie)); + priority_list.push_back(priority); + id_list[priority].push_back(next_cookie_id); } } - int num_cookies = static_cast<int>(cookie_data.size()); - // A list of cookie IDs, indexed by secure status, then by priority. - std::vector<int> surviving_id_list[2][3]; + int num_cookies = static_cast<int>(priority_list.size()); + std::vector<int> surviving_id_list[3]; // Indexed by CookiePriority. // Parse the list of cookies - std::string cookie_str = this->GetCookies(cm, https_www_google_.url()); - size_t num_nonsecure = 0; - size_t num_secure = 0; + std::string cookie_str = this->GetCookies(cm, http_www_google_.url()); for (const std::string& token : base::SplitString( cookie_str, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) { // Assuming *it is "a#=b", so extract and parse "#" portion. @@ -419,40 +404,22 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { DCHECK(result); DCHECK_GE(id, 0); DCHECK_LT(id, num_cookies); - surviving_id_list[cookie_data[id].first][cookie_data[id].second] - .push_back(id); - if (cookie_data[id].first) - num_secure += 1; - else - num_nonsecure += 1; + surviving_id_list[priority_list[id]].push_back(id); } - EXPECT_EQ(expected_nonsecure, num_nonsecure); - EXPECT_EQ(expected_secure, num_secure); - // Validate each priority. size_t expected_count[3] = { expected_low_count, expected_medium_count, expected_high_count}; for (int i = 0; i < 3; ++i) { - size_t num_for_priority = - surviving_id_list[0][i].size() + surviving_id_list[1][i].size(); - EXPECT_EQ(expected_count[i], num_for_priority); + DCHECK_LE(surviving_id_list[i].size(), id_list[i].size()); + EXPECT_EQ(expected_count[i], surviving_id_list[i].size()); // Verify that the remaining cookies are the most recent among those // with the same priorities. - if (expected_count[i] == num_for_priority) { - // Non-secure: - std::sort(surviving_id_list[0][i].begin(), - surviving_id_list[0][i].end()); - EXPECT_TRUE(std::equal( - surviving_id_list[0][i].begin(), surviving_id_list[0][i].end(), - id_list[0][i].end() - surviving_id_list[0][i].size())); - - // Secure: - std::sort(surviving_id_list[1][i].begin(), - surviving_id_list[1][i].end()); - EXPECT_TRUE(std::equal( - surviving_id_list[1][i].begin(), surviving_id_list[1][i].end(), - id_list[1][i].end() - surviving_id_list[1][i].size())); + if (expected_count[i] == surviving_id_list[i].size()) { + std::sort(surviving_id_list[i].begin(), surviving_id_list[i].end()); + EXPECT_TRUE(std::equal(surviving_id_list[i].begin(), + surviving_id_list[i].end(), + id_list[i].end() - expected_count[i])); } } } @@ -519,158 +486,54 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { EXPECT_EQ(expected_non_secure_cookies, total_non_secure_cookies); } - void TestPriorityAwareGarbageCollectHelperNonSecure() { - // Hard-coding limits in the test, but use DCHECK_EQ to enforce constraint. - DCHECK_EQ(180U, CookieMonster::kDomainMaxCookies); - DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - - CookieMonster::kDomainPurgeCookies); - - scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); - - // Each test case adds 181 cookies, so 31 cookies are evicted. - // Cookie same priority, repeated for each priority. - TestPriorityCookieCase(cm.get(), "181LN", 150U, 0U, 0U, 150U, 0U); - TestPriorityCookieCase(cm.get(), "181MN", 0U, 150U, 0U, 150U, 0U); - TestPriorityCookieCase(cm.get(), "181HN", 0U, 0U, 150U, 150U, 0U); - - // Pairwise scenarios. - // Round 1 => none; round2 => 31M; round 3 => none. - TestPriorityCookieCase(cm.get(), "10HN 171MN", 0U, 140U, 10U, 150U, 0U); - // Round 1 => 10L; round2 => 21M; round 3 => none. - TestPriorityCookieCase(cm.get(), "141MN 40LN", 30U, 120U, 0U, 150U, 0U); - // Round 1 => none; round2 => none; round 3 => 31H. - TestPriorityCookieCase(cm.get(), "101HN 80MN", 0U, 80U, 70U, 150U, 0U); - - // For {low, medium} priorities right on quota, different orders. - // Round 1 => 1L; round 2 => none, round3 => 30L. - TestPriorityCookieCase(cm.get(), "31LN 50MN 100HN", 0U, 50U, 100U, 150U, - 0U); - // Round 1 => none; round 2 => 1M, round3 => 30M. - TestPriorityCookieCase(cm.get(), "51MN 100HN 30LN", 30U, 20U, 100U, 150U, - 0U); - // Round 1 => none; round 2 => none; round3 => 31H. - TestPriorityCookieCase(cm.get(), "101HN 50MN 30LN", 30U, 50U, 70U, 150U, - 0U); - - // Round 1 => 10L; round 2 => 10M; round3 => 11H. - TestPriorityCookieCase(cm.get(), "81HN 60MN 40LN", 30U, 50U, 70U, 150U, 0U); - - // More complex scenarios. - // Round 1 => 10L; round 2 => 10M; round 3 => 11H. - TestPriorityCookieCase(cm.get(), "21HN 60MN 40LN 60HN", 30U, 50U, 70U, 150U, - 0U); - // Round 1 => 10L; round 2 => 11M, 10L; round 3 => none. - TestPriorityCookieCase(cm.get(), "11HN 10MN 20LN 110MN 20LN 10HN", 20U, - 109U, 21U, 150U, 0U); - // Round 1 => none; round 2 => none; round 3 => 11L, 10M, 10H. - TestPriorityCookieCase(cm.get(), "11LN 10MN 140HN 10MN 10LN", 10U, 10U, - 130U, 150U, 0U); - // Round 1 => none; round 2 => 1M; round 3 => 10L, 10M, 10H. - TestPriorityCookieCase(cm.get(), "11MN 10HN 10LN 60MN 90HN", 0U, 60U, 90U, - 150U, 0U); - // Round 1 => none; round 2 => 10L, 21M; round 3 => none. - TestPriorityCookieCase(cm.get(), "11MN 10HN 10LN 90MN 60HN", 0U, 80U, 70U, - 150U, 0U); - } - - void TestPriorityAwareGarbageCollectHelperSecure() { + void TestPriorityAwareGarbageCollectHelper() { // Hard-coding limits in the test, but use DCHECK_EQ to enforce constraint. DCHECK_EQ(180U, CookieMonster::kDomainMaxCookies); DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - CookieMonster::kDomainPurgeCookies); + DCHECK_EQ(30U, CookieMonster::kDomainCookiesQuotaLow); + DCHECK_EQ(50U, CookieMonster::kDomainCookiesQuotaMedium); + DCHECK_EQ(70U, CookieMonster::kDomainCookiesQuotaHigh); scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); // Each test case adds 181 cookies, so 31 cookies are evicted. // Cookie same priority, repeated for each priority. - TestPriorityCookieCase(cm.get(), "181LS", 150U, 0U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "181MS", 0U, 150U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "181HS", 0U, 0U, 150U, 0U, 150U); + TestPriorityCookieCase(cm.get(), "181L", 150U, 0U, 0U); + TestPriorityCookieCase(cm.get(), "181M", 0U, 150U, 0U); + TestPriorityCookieCase(cm.get(), "181H", 0U, 0U, 150U); // Pairwise scenarios. // Round 1 => none; round2 => 31M; round 3 => none. - TestPriorityCookieCase(cm.get(), "10HS 171MS", 0U, 140U, 10U, 0U, 150U); + TestPriorityCookieCase(cm.get(), "10H 171M", 0U, 140U, 10U); // Round 1 => 10L; round2 => 21M; round 3 => none. - TestPriorityCookieCase(cm.get(), "141MS 40LS", 30U, 120U, 0U, 0U, 150U); + TestPriorityCookieCase(cm.get(), "141M 40L", 30U, 120U, 0U); // Round 1 => none; round2 => none; round 3 => 31H. - TestPriorityCookieCase(cm.get(), "101HS 80MS", 0U, 80U, 70U, 0U, 150U); + TestPriorityCookieCase(cm.get(), "101H 80M", 0U, 80U, 70U); // For {low, medium} priorities right on quota, different orders. // Round 1 => 1L; round 2 => none, round3 => 30L. - TestPriorityCookieCase(cm.get(), "31LS 50MS 100HS", 0U, 50U, 100U, 0U, - 150U); + TestPriorityCookieCase(cm.get(), "31L 50M 100H", 0U, 50U, 100U); // Round 1 => none; round 2 => 1M, round3 => 30M. - TestPriorityCookieCase(cm.get(), "51MS 100HS 30LS", 30U, 20U, 100U, 0U, - 150U); + TestPriorityCookieCase(cm.get(), "51M 100H 30L", 30U, 20U, 100U); // Round 1 => none; round 2 => none; round3 => 31H. - TestPriorityCookieCase(cm.get(), "101HS 50MS 30LS", 30U, 50U, 70U, 0U, - 150U); + TestPriorityCookieCase(cm.get(), "101H 50M 30L", 30U, 50U, 70U); // Round 1 => 10L; round 2 => 10M; round3 => 11H. - TestPriorityCookieCase(cm.get(), "81HS 60MS 40LS", 30U, 50U, 70U, 0U, 150U); + TestPriorityCookieCase(cm.get(), "81H 60M 40L", 30U, 50U, 70U); // More complex scenarios. // Round 1 => 10L; round 2 => 10M; round 3 => 11H. - TestPriorityCookieCase(cm.get(), "21HS 60MS 40LS 60HS", 30U, 50U, 70U, 0U, - 150U); + TestPriorityCookieCase(cm.get(), "21H 60M 40L 60H", 30U, 50U, 70U); // Round 1 => 10L; round 2 => 11M, 10L; round 3 => none. - TestPriorityCookieCase(cm.get(), "11HS 10MS 20LS 110MS 20LS 10HS", 20U, - 109U, 21U, 0U, 150U); + TestPriorityCookieCase(cm.get(), "11H 10M 20L 110M 20L 10H", 20U, 109U, + 21U); // Round 1 => none; round 2 => none; round 3 => 11L, 10M, 10H. - TestPriorityCookieCase(cm.get(), "11LS 10MS 140HS 10MS 10LS", 10U, 10U, - 130U, 0U, 150U); + TestPriorityCookieCase(cm.get(), "11L 10M 140H 10M 10L", 10U, 10U, 130U); // Round 1 => none; round 2 => 1M; round 3 => 10L, 10M, 10H. - TestPriorityCookieCase(cm.get(), "11MS 10HS 10LS 60MS 90HS", 0U, 60U, 90U, - 0U, 150U); + TestPriorityCookieCase(cm.get(), "11M 10H 10L 60M 90H", 0U, 60U, 90U); // Round 1 => none; round 2 => 10L, 21M; round 3 => none. - TestPriorityCookieCase(cm.get(), "11MS 10HS 10LS 90MS 60HS", 0U, 80U, 70U, - 0U, 150U); - } - - void TestPriorityAwareGarbageCollectHelperMixed() { - // Hard-coding limits in the test, but use DCHECK_EQ to enforce constraint. - DCHECK_EQ(180U, CookieMonster::kDomainMaxCookies); - DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies - - CookieMonster::kDomainPurgeCookies); - - scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); - - // Each test case adds 180 secure cookies, and some non-secure cookie. The - // secure cookies take priority, so the non-secure cookie is removed, along - // with 30 secure cookies. Repeated for each priority, and with the - // non-secure cookie as older and newer. - TestPriorityCookieCase(cm.get(), "1LN 180LS", 150U, 0U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "1MN 180MS", 0U, 150U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "1HN 180HS", 0U, 0U, 150U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "180LS 1LN", 150U, 0U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "180MS 1MN", 0U, 150U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "180HS 1HN", 0U, 0U, 150U, 0U, 150U); - - // Higher-priority non-secure cookies are removed before any secure cookie. - TestPriorityCookieCase(cm.get(), "180LS 1MN", 150U, 0U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "180LS 1HN", 150U, 0U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "180MS 1HN", 0U, 150U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "1MN 180LS", 150U, 0U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "1HN 180LS", 150U, 0U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "1HN 180MS", 0U, 150U, 0U, 0U, 150U); - - // Pairwise: - TestPriorityCookieCase(cm.get(), "1LS 180LN", 150U, 0U, 0U, 149U, 1U); - TestPriorityCookieCase(cm.get(), "100LS 81LN", 150U, 0U, 0U, 50U, 100U); - TestPriorityCookieCase(cm.get(), "150LS 31LN", 150U, 0U, 0U, 0U, 150U); - TestPriorityCookieCase(cm.get(), "1LS 180HN", 1U, 0U, 149U, 149U, 1U); - TestPriorityCookieCase(cm.get(), "100LS 81HN", 100U, 0U, 50U, 50U, 100U); - TestPriorityCookieCase(cm.get(), "150LS 31HN", 150U, 0U, 0U, 0U, 150U); - - // Quota calculations inside non-secure/secure blocks remain in place: - TestPriorityCookieCase(cm.get(), "50HN 50LS 81HS", 50U, 0U, 100U, 19U, - 131U); - TestPriorityCookieCase(cm.get(), "11MS 10HN 10LS 90MN 60HN", 10U, 79U, 61U, - 129U, 21U); - - // Multiple GC rounds end up with consistent behavior: - TestPriorityCookieCase(cm.get(), "100HS 100LN 100MN", 0, 76U, 100U, 76U, - 100U); + TestPriorityCookieCase(cm.get(), "11M 10H 10L 90M 60H", 0U, 80U, 70U); } // Function for creating a CM with a number of cookies in it, @@ -1400,16 +1263,8 @@ TEST_F(CookieMonsterTest, TestHostGarbageCollection) { TestHostGarbageCollectHelper(); } -TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollectionNonSecure) { - TestPriorityAwareGarbageCollectHelperNonSecure(); -} - -TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollectionSecure) { - TestPriorityAwareGarbageCollectHelperSecure(); -} - -TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollectionMixed) { - TestPriorityAwareGarbageCollectHelperMixed(); +TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollection) { + TestPriorityAwareGarbageCollectHelper(); } TEST_F(CookieMonsterTest, SetCookieableSchemes) { @@ -2798,13 +2653,13 @@ TEST_F(CookieMonsterStrictSecureTest, EvictSecureCookies) { // non-secure cookie will not evict them (and, in fact, the non-secure cookie // will be removed right after creation). const CookiesEntry test1[] = {{180U, true}, {1U, false}}; - TestSecureCookieEviction(test1, arraysize(test1), 150U, 0U, nullptr); + TestSecureCookieEviction(test1, arraysize(test1), 180U, 0U, nullptr); // If non-secure cookies for one domain hit the per domain limit (180), the - // creation of secure cookies will evict the non-secure cookies first, making - // room for the secure cookies. + // creation of secure cookies will evict all of the non-secure cookies, and + // the secure cookies will still be created. const CookiesEntry test2[] = {{180U, false}, {20U, true}}; - TestSecureCookieEviction(test2, arraysize(test2), 20U, 149U, nullptr); + TestSecureCookieEviction(test2, arraysize(test2), 20U, 0U, nullptr); // If secure cookies for one domain go past the per domain limit (180), they // will be evicted as normal by the per domain purge amount (30) down to a @@ -2816,9 +2671,9 @@ TEST_F(CookieMonsterStrictSecureTest, EvictSecureCookies) { // If a non-secure cookie is created, and a number of secure cookies exceeds // the per domain limit (18), the total cookies will be evicted down to a // lower amount (150), enforcing the eviction of the non-secure cookie, and - // the remaining secure cookies will be created (another 19 to 169). + // the remaining secure cookies will be created (another 18 to 168). const CookiesEntry test4[] = {{1U, false}, {199U, true}}; - TestSecureCookieEviction(test4, arraysize(test4), 169U, 0U, nullptr); + TestSecureCookieEviction(test4, arraysize(test4), 168U, 0U, nullptr); // If an even number of non-secure and secure cookies are created below the // per-domain limit (180), all will be created and none evicted. @@ -2827,40 +2682,38 @@ TEST_F(CookieMonsterStrictSecureTest, EvictSecureCookies) { // If the same number of secure and non-secure cookies are created (50 each) // below the per domain limit (180), and then another set of secure cookies - // are created to bring the total above the per-domain limit, all secure - // cookies will be retained, and the non-secure cookies will be culled down - // to the limit. + // are created to bring the total above the per-domain limit, all of the + // non-secure cookies will be evicted but none of the secure ones will be + // evicted. const CookiesEntry test6[] = {{50U, true}, {50U, false}, {81U, true}}; - TestSecureCookieEviction(test6, arraysize(test6), 131U, 19U, nullptr); + TestSecureCookieEviction(test6, arraysize(test6), 131U, 0U, nullptr); // If the same number of non-secure and secure cookies are created (50 each) // below the per domain limit (180), and then another set of non-secure - // cookies are created to bring the total above the per-domain limit, all - // secure cookies will be retained, and the non-secure cookies will be culled - // down to the limit. + // cookies are created to bring the total above the per-domain limit, all of + // the non-secure cookies will be evicted but none of the secure ones will be + // evicted. const CookiesEntry test7[] = {{50U, false}, {50U, true}, {81U, false}}; - TestSecureCookieEviction(test7, arraysize(test7), 50U, 100U, nullptr); + TestSecureCookieEviction(test7, arraysize(test7), 50U, 0U, nullptr); // If the same number of non-secure and secure cookies are created (50 each) // below the per domain limit (180), and then another set of non-secure - // cookies are created to bring the total above the per-domain limit, all - // secure cookies will be retained, and the non-secure cookies will be culled - // down to the limit, then the remaining non-secure cookies will be created - // (9). + // cookies are created to bring the total above the per-domain limit, all of + // the non-secure cookies will be evicted but none of the secure ones will be + // evicted, and then the remaining non-secure cookies will be created (9). const CookiesEntry test8[] = {{50U, false}, {50U, true}, {90U, false}}; - TestSecureCookieEviction(test8, arraysize(test8), 50U, 109U, nullptr); + TestSecureCookieEviction(test8, arraysize(test8), 50U, 9U, nullptr); // If a number of non-secure cookies are created on other hosts (20) and are // past the global 'safe' date, and then the number of non-secure cookies for // a single domain are brought to the per-domain limit (180), followed by - // another set of secure cookies on that same domain (20), all the secure - // cookies for that domain should be retained, while the non-secure should be - // culled down to the per-domain limit. The non-secure cookies for other - // domains should remain untouched. + // another set of secure cookies on that same domain (20), all of the + // non-secure cookies for that domain should be evicted, but the non-secure + // cookies for other domains should remain, as should the secure cookies for + // that domain. const CookiesEntry test9[] = {{180U, false}, {20U, true}}; const AltHosts test9_alt_hosts(0, 20); - TestSecureCookieEviction(test9, arraysize(test9), 20U, 169U, - &test9_alt_hosts); + TestSecureCookieEviction(test9, arraysize(test9), 20U, 20U, &test9_alt_hosts); // If a number of secure cookies are created on other hosts and hit the global // cookie limit (3300) and are past the global 'safe' date, and then a single |