diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-07-14 17:41:05 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2016-08-04 12:37:36 +0000 |
commit | 399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (patch) | |
tree | 6b06b60ff365abef0e13b3503d593a0df48d20e8 /chromium/net/cookies | |
parent | 7366110654eec46f21b6824f302356426f48cd74 (diff) | |
download | qtwebengine-chromium-399c965b6064c440ddcf4015f5f8e9d131c7a0a6.tar.gz |
BASELINE: Update Chromium to 52.0.2743.76 and Ninja to 1.7.1
Change-Id: I382f51b959689505a60f8b707255ecb344f7d8b4
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/net/cookies')
-rw-r--r-- | chromium/net/cookies/OWNERS | 1 | ||||
-rw-r--r-- | chromium/net/cookies/canonical_cookie.cc | 9 | ||||
-rw-r--r-- | chromium/net/cookies/canonical_cookie.h | 35 | ||||
-rw-r--r-- | chromium/net/cookies/canonical_cookie_unittest.cc | 53 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster.cc | 281 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster.h | 40 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_perftest.cc | 18 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_store_test.cc | 11 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_store_test.h | 6 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_unittest.cc | 769 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_store.cc | 2 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_store.h | 29 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_store_test_helpers.cc | 14 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_store_test_helpers.h | 17 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_store_unittest.cc | 9 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_store_unittest.h | 76 |
16 files changed, 874 insertions, 496 deletions
diff --git a/chromium/net/cookies/OWNERS b/chromium/net/cookies/OWNERS index 3f8456354bd..b8c909d7dcc 100644 --- a/chromium/net/cookies/OWNERS +++ b/chromium/net/cookies/OWNERS @@ -1 +1,2 @@ +jww@chromium.org mkwst@chromium.org diff --git a/chromium/net/cookies/canonical_cookie.cc b/chromium/net/cookies/canonical_cookie.cc index bce2b5477fa..1572cc1e793 100644 --- a/chromium/net/cookies/canonical_cookie.cc +++ b/chromium/net/cookies/canonical_cookie.cc @@ -46,6 +46,7 @@ #include "base/format_macros.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -192,7 +193,7 @@ Time CanonicalCookie::CanonExpiration(const ParsedCookie& pc, } // static -scoped_ptr<CanonicalCookie> CanonicalCookie::Create( +std::unique_ptr<CanonicalCookie> CanonicalCookie::Create( const GURL& url, const std::string& cookie_line, const base::Time& creation_time, @@ -245,7 +246,7 @@ scoped_ptr<CanonicalCookie> CanonicalCookie::Create( return nullptr; } - return make_scoped_ptr(new CanonicalCookie( + return base::WrapUnique(new CanonicalCookie( url, parsed_cookie.Name(), parsed_cookie.Value(), cookie_domain, cookie_path, creation_time, cookie_expires, creation_time, parsed_cookie.IsSecure(), parsed_cookie.IsHttpOnly(), @@ -253,7 +254,7 @@ scoped_ptr<CanonicalCookie> CanonicalCookie::Create( } // static -scoped_ptr<CanonicalCookie> CanonicalCookie::Create( +std::unique_ptr<CanonicalCookie> CanonicalCookie::Create( const GURL& url, const std::string& name, const std::string& value, @@ -304,7 +305,7 @@ scoped_ptr<CanonicalCookie> CanonicalCookie::Create( cookie_path = std::string(canon_path.data() + canon_path_component.begin, canon_path_component.len); - return make_scoped_ptr(new CanonicalCookie( + return base::WrapUnique(new CanonicalCookie( url, parsed_name, parsed_value, cookie_domain, cookie_path, creation, expiration, creation, secure, http_only, same_site, priority)); } diff --git a/chromium/net/cookies/canonical_cookie.h b/chromium/net/cookies/canonical_cookie.h index f95501c7627..254e1173574 100644 --- a/chromium/net/cookies/canonical_cookie.h +++ b/chromium/net/cookies/canonical_cookie.h @@ -5,11 +5,11 @@ #ifndef NET_COOKIES_CANONICAL_COOKIE_H_ #define NET_COOKIES_CANONICAL_COOKIE_H_ +#include <memory> #include <string> #include <vector> #include "base/gtest_prod_util.h" -#include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "net/base/net_export.h" #include "net/cookies/cookie_constants.h" @@ -50,26 +50,27 @@ class NET_EXPORT CanonicalCookie { // Creates a new |CanonicalCookie| from the |cookie_line| and the // |creation_time|. Canonicalizes and validates inputs. May return NULL if // an attribute value is invalid. - static scoped_ptr<CanonicalCookie> Create(const GURL& url, - const std::string& cookie_line, - const base::Time& creation_time, - const CookieOptions& options); + static std::unique_ptr<CanonicalCookie> Create( + const GURL& url, + const std::string& cookie_line, + const base::Time& creation_time, + const CookieOptions& options); // Creates a canonical cookie from unparsed attribute values. // Canonicalizes and validates inputs. May return NULL if an attribute // value is invalid. - static scoped_ptr<CanonicalCookie> Create(const GURL& url, - const std::string& name, - const std::string& value, - const std::string& domain, - const std::string& path, - const base::Time& creation, - const base::Time& expiration, - bool secure, - bool http_only, - CookieSameSite same_site, - bool enforce_strict_secure, - CookiePriority priority); + static std::unique_ptr<CanonicalCookie> Create(const GURL& url, + const std::string& name, + const std::string& value, + const std::string& domain, + const std::string& path, + const base::Time& creation, + const base::Time& expiration, + bool secure, + bool http_only, + CookieSameSite same_site, + bool enforce_strict_secure, + CookiePriority priority); const GURL& Source() const { return source_; } const std::string& Name() const { return name_; } diff --git a/chromium/net/cookies/canonical_cookie_unittest.cc b/chromium/net/cookies/canonical_cookie_unittest.cc index 80b772e9b2f..9bdfc16fd5c 100644 --- a/chromium/net/cookies/canonical_cookie_unittest.cc +++ b/chromium/net/cookies/canonical_cookie_unittest.cc @@ -4,7 +4,8 @@ #include "net/cookies/canonical_cookie.h" -#include "base/memory/scoped_ptr.h" +#include <memory> + #include "base/test/histogram_tester.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_options.h" @@ -49,7 +50,7 @@ TEST(CanonicalCookieTest, Create) { base::Time creation_time = base::Time::Now(); CookieOptions options; - scoped_ptr<CanonicalCookie> cookie( + std::unique_ptr<CanonicalCookie> cookie( CanonicalCookie::Create(url, "A=2", creation_time, options)); EXPECT_EQ(url.GetOrigin(), cookie->Source()); EXPECT_EQ("A", cookie->Name()); @@ -126,7 +127,7 @@ TEST(CanonicalCookieTest, Create) { TEST(CanonicalCookieTest, CreateInvalidSameSite) { GURL url("http://www.example.com/test/foo.html"); base::Time now = base::Time::Now(); - scoped_ptr<CanonicalCookie> cookie; + std::unique_ptr<CanonicalCookie> cookie; CookieOptions options; // Invalid 'SameSite' attribute values. @@ -147,7 +148,7 @@ TEST(CanonicalCookieTest, EmptyExpiry) { std::string cookie_line = "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires="; - scoped_ptr<CanonicalCookie> cookie( + std::unique_ptr<CanonicalCookie> cookie( CanonicalCookie::Create(url, cookie_line, creation_time, options)); EXPECT_TRUE(cookie.get()); EXPECT_FALSE(cookie->IsPersistent()); @@ -185,14 +186,14 @@ TEST(CanonicalCookieTest, IsEquivalent) { CookieSameSite same_site(CookieSameSite::NO_RESTRICTION); // Test that a cookie is equivalent to itself. - scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie( + std::unique_ptr<CanonicalCookie> cookie(new CanonicalCookie( url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, expiration_time, last_access_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM)); EXPECT_TRUE(cookie->IsEquivalent(*cookie)); // Test that two identical cookies are equivalent. - scoped_ptr<CanonicalCookie> other_cookie(new CanonicalCookie( + std::unique_ptr<CanonicalCookie> other_cookie(new CanonicalCookie( url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, expiration_time, last_access_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM)); @@ -275,14 +276,14 @@ TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) { CookieSameSite same_site(CookieSameSite::NO_RESTRICTION); // Test that a cookie is equivalent to itself. - scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie( + std::unique_ptr<CanonicalCookie> cookie(new CanonicalCookie( url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, expiration_time, last_access_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*cookie)); // Test that two identical cookies are equivalent. - scoped_ptr<CanonicalCookie> other_cookie(new CanonicalCookie( + std::unique_ptr<CanonicalCookie> other_cookie(new CanonicalCookie( url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, expiration_time, last_access_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM)); @@ -364,7 +365,7 @@ TEST(CanonicalCookieTest, IsDomainMatch) { base::Time creation_time = base::Time::Now(); CookieOptions options; - scoped_ptr<CanonicalCookie> cookie( + std::unique_ptr<CanonicalCookie> cookie( CanonicalCookie::Create(url, "A=2", creation_time, options)); EXPECT_TRUE(cookie->IsHostCookie()); EXPECT_TRUE(cookie->IsDomainMatch("www.example.com")); @@ -395,7 +396,7 @@ TEST(CanonicalCookieTest, IsOnPath) { base::Time creation_time = base::Time::Now(); CookieOptions options; - scoped_ptr<CanonicalCookie> cookie(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::Create( GURL("http://www.example.com"), "A=2", creation_time, options)); EXPECT_TRUE(cookie->IsOnPath("/")); EXPECT_TRUE(cookie->IsOnPath("/test")); @@ -417,7 +418,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) { base::Time creation_time = base::Time::Now(); CookieOptions options; - scoped_ptr<CanonicalCookie> cookie( + std::unique_ptr<CanonicalCookie> cookie( CanonicalCookie::Create(url, "A=2", creation_time, options)); EXPECT_TRUE(cookie->IncludeForRequestURL(url, options)); EXPECT_TRUE(cookie->IncludeForRequestURL( @@ -460,7 +461,7 @@ TEST(CanonicalCookieTest, IncludeSameSiteForSameSiteURL) { GURL url("https://example.test"); base::Time creation_time = base::Time::Now(); CookieOptions options; - scoped_ptr<CanonicalCookie> cookie; + std::unique_ptr<CanonicalCookie> cookie; // `SameSite=Strict` cookies are included for a URL only if the options' // SameSiteCookieMode is INCLUDE_STRICT_AND_LAX. @@ -497,11 +498,11 @@ TEST(CanonicalCookieTest, PartialCompare) { GURL url("http://www.example.com"); base::Time creation_time = base::Time::Now(); CookieOptions options; - scoped_ptr<CanonicalCookie> cookie( + std::unique_ptr<CanonicalCookie> cookie( CanonicalCookie::Create(url, "a=b", creation_time, options)); - scoped_ptr<CanonicalCookie> cookie_different_path( + std::unique_ptr<CanonicalCookie> cookie_different_path( CanonicalCookie::Create(url, "a=b; path=/foo", creation_time, options)); - scoped_ptr<CanonicalCookie> cookie_different_value( + std::unique_ptr<CanonicalCookie> cookie_different_value( CanonicalCookie::Create(url, "a=c", creation_time, options)); // Cookie is equivalent to itself. @@ -524,11 +525,11 @@ TEST(CanonicalCookieTest, FullCompare) { GURL url("http://www.example.com"); base::Time creation_time = base::Time::Now(); CookieOptions options; - scoped_ptr<CanonicalCookie> cookie( + std::unique_ptr<CanonicalCookie> cookie( CanonicalCookie::Create(url, "a=b", creation_time, options)); - scoped_ptr<CanonicalCookie> cookie_different_path( + std::unique_ptr<CanonicalCookie> cookie_different_path( CanonicalCookie::Create(url, "a=b; path=/foo", creation_time, options)); - scoped_ptr<CanonicalCookie> cookie_different_value( + std::unique_ptr<CanonicalCookie> cookie_different_value( CanonicalCookie::Create(url, "a=c", creation_time, options)); // Cookie is equivalent to itself. @@ -638,13 +639,13 @@ TEST(CanonicalCookieTest, EnforceSecureCookiesRequireSecureScheme) { CookieOptions options; options.set_enforce_strict_secure(); - scoped_ptr<CanonicalCookie> http_cookie_no_secure( + std::unique_ptr<CanonicalCookie> http_cookie_no_secure( CanonicalCookie::Create(http_url, "a=b", creation_time, options)); - scoped_ptr<CanonicalCookie> http_cookie_secure( + std::unique_ptr<CanonicalCookie> http_cookie_secure( CanonicalCookie::Create(http_url, "a=b; Secure", creation_time, options)); - scoped_ptr<CanonicalCookie> https_cookie_no_secure( + std::unique_ptr<CanonicalCookie> https_cookie_no_secure( CanonicalCookie::Create(https_url, "a=b", creation_time, options)); - scoped_ptr<CanonicalCookie> https_cookie_secure(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> https_cookie_secure(CanonicalCookie::Create( https_url, "a=b; Secure", creation_time, options)); EXPECT_TRUE(http_cookie_no_secure.get()); @@ -652,19 +653,19 @@ TEST(CanonicalCookieTest, EnforceSecureCookiesRequireSecureScheme) { EXPECT_TRUE(https_cookie_no_secure.get()); EXPECT_TRUE(https_cookie_secure.get()); - scoped_ptr<CanonicalCookie> http_cookie_no_secure_extended( + std::unique_ptr<CanonicalCookie> http_cookie_no_secure_extended( CanonicalCookie::Create( http_url, "a", "b", "", "", creation_time, creation_time, false, false, CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> http_cookie_secure_extended( + std::unique_ptr<CanonicalCookie> http_cookie_secure_extended( CanonicalCookie::Create( http_url, "a", "b", "", "", creation_time, creation_time, true, false, CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> https_cookie_no_secure_extended( + std::unique_ptr<CanonicalCookie> https_cookie_no_secure_extended( CanonicalCookie::Create( https_url, "a", "b", "", "", creation_time, creation_time, false, false, CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> https_cookie_secure_extended( + std::unique_ptr<CanonicalCookie> https_cookie_secure_extended( CanonicalCookie::Create( https_url, "a", "b", "", "", creation_time, creation_time, true, false, CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT)); diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc index 75c62667dda..3d7124d502e 100644 --- a/chromium/net/cookies/cookie_monster.cc +++ b/chromium/net/cookies/cookie_monster.cc @@ -46,6 +46,7 @@ #include <algorithm> #include <functional> +#include <memory> #include <set> #include "base/bind.h" @@ -53,14 +54,14 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" -#include "base/memory/scoped_ptr.h" +#include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram.h" #include "base/profiler/scoped_tracker.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_util.h" @@ -308,6 +309,55 @@ void RunAsync(scoped_refptr<base::TaskRunner> proxy, proxy->PostTask(FROM_HERE, base::Bind(callback, cookie, removed)); } +size_t CountProtectedSecureCookiesAtPriority( + CookiePriority priority, + CookieMonster::CookieItVector* cookies) { + size_t num_protected_secure_cookies = 0; + for (const auto& cookie : *cookies) { + if (!cookie->second->IsSecure()) + continue; + // 1) At low-priority, only low-priority secure cookies are protected as + // part of the quota. + // 2) At medium-priority, only medium-priority secure cookies are protected + // as part of the quota (low-priority secure cookies may be deleted). + // 3) At high-priority, medium-priority and high-priority secure cookies are + // protected as part of the quota (low-priority secure cookies may be + // deleted). + CookiePriority cookie_priority = cookie->second->Priority(); + switch (cookie_priority) { + case COOKIE_PRIORITY_LOW: + if (priority == COOKIE_PRIORITY_LOW) + num_protected_secure_cookies++; + break; + case COOKIE_PRIORITY_MEDIUM: + case COOKIE_PRIORITY_HIGH: + if (cookie_priority <= priority) + num_protected_secure_cookies++; + break; + } + } + + return num_protected_secure_cookies; +} + +bool IsCookieEligibleForEviction(CookiePriority current_priority_level, + bool protect_secure_cookies, + const CanonicalCookie* cookie) { + if (!cookie->IsSecure() || !protect_secure_cookies) + return cookie->Priority() <= current_priority_level; + + // Special consideration has to be given for low-priority secure cookies since + // they are given lower prority than non-secure medium-priority and non-secure + // high-priority cookies. Thus, low-priority secure cookies may be evicted at + // a medium and high value of |current_priority_level|. Put another way, + // low-priority secure cookies are only protected when the current priority + // level is low. + if (current_priority_level == COOKIE_PRIORITY_LOW) + return false; + + return cookie->Priority() == COOKIE_PRIORITY_LOW; +} + } // namespace CookieMonster::CookieMonster(PersistentCookieStore* store, @@ -592,37 +642,38 @@ int CookieMonster::DeleteAllCreatedBetweenTask::RunDeleteTask() { delete_end_); } -// Task class for DeleteAllCreatedBetweenForHost call. -class CookieMonster::DeleteAllCreatedBetweenForHostTask +// Task class for DeleteAllCreatedBetweenWithPredicate call. +class CookieMonster::DeleteAllCreatedBetweenWithPredicateTask : public DeleteTask<int> { public: - DeleteAllCreatedBetweenForHostTask(CookieMonster* cookie_monster, - Time delete_begin, - Time delete_end, - const GURL& url, - const DeleteCallback& callback) + DeleteAllCreatedBetweenWithPredicateTask( + CookieMonster* cookie_monster, + Time delete_begin, + Time delete_end, + base::Callback<bool(const CanonicalCookie&)> predicate, + const DeleteCallback& callback) : DeleteTask<int>(cookie_monster, callback), delete_begin_(delete_begin), delete_end_(delete_end), - url_(url) {} + predicate_(predicate) {} // DeleteTask: int RunDeleteTask() override; protected: - ~DeleteAllCreatedBetweenForHostTask() override {} + ~DeleteAllCreatedBetweenWithPredicateTask() override {} private: Time delete_begin_; Time delete_end_; - GURL url_; + base::Callback<bool(const CanonicalCookie&)> predicate_; - DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenForHostTask); + DISALLOW_COPY_AND_ASSIGN(DeleteAllCreatedBetweenWithPredicateTask); }; -int CookieMonster::DeleteAllCreatedBetweenForHostTask::RunDeleteTask() { - return this->cookie_monster()->DeleteAllCreatedBetweenForHost( - delete_begin_, delete_end_, url_); +int CookieMonster::DeleteAllCreatedBetweenWithPredicateTask::RunDeleteTask() { + return this->cookie_monster()->DeleteAllCreatedBetweenWithPredicate( + delete_begin_, delete_end_, predicate_); } // Task class for DeleteCanonicalCookie call. @@ -923,16 +974,19 @@ void CookieMonster::DeleteAllCreatedBetweenAsync( DoCookieTask(task); } -void CookieMonster::DeleteAllCreatedBetweenForHostAsync( - const Time delete_begin, - const Time delete_end, - const GURL& url, +void CookieMonster::DeleteAllCreatedBetweenWithPredicateAsync( + const Time& delete_begin, + const Time& delete_end, + const base::Callback<bool(const CanonicalCookie&)>& predicate, const DeleteCallback& callback) { - scoped_refptr<DeleteAllCreatedBetweenForHostTask> task = - new DeleteAllCreatedBetweenForHostTask(this, delete_begin, delete_end, - url, callback); - - DoCookieTaskForURL(task, url); + if (predicate.is_null()) { + callback.Run(0); + return; + } + scoped_refptr<DeleteAllCreatedBetweenWithPredicateTask> task = + new DeleteAllCreatedBetweenWithPredicateTask( + this, delete_begin, delete_end, predicate, callback); + DoCookieTask(task); } void CookieMonster::DeleteSessionCookiesAsync( @@ -974,7 +1028,7 @@ const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https", const int CookieMonster::kDefaultCookieableSchemesCount = arraysize(kDefaultCookieableSchemes); -scoped_ptr<CookieStore::CookieChangedSubscription> +std::unique_ptr<CookieStore::CookieChangedSubscription> CookieMonster::AddCallbackForCookie(const GURL& gurl, const std::string& name, const CookieChangedCallback& callback) { @@ -1033,7 +1087,7 @@ bool CookieMonster::SetCookieWithDetails(const GURL& url, last_time_seen_ = actual_creation_time; } - scoped_ptr<CanonicalCookie> cc(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cc(CanonicalCookie::Create( url, name, value, domain, path, actual_creation_time, expiration_time, secure, http_only, same_site, enforce_strict_secure, priority)); @@ -1125,42 +1179,30 @@ int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin, return num_deleted; } -int CookieMonster::DeleteAllCreatedBetweenForHost(const Time delete_begin, - const Time delete_end, - const GURL& url) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!HasCookieableScheme(url)) - return 0; - - const std::string host(url.host()); - - // We store host cookies in the store by their canonical host name; - // domain cookies are stored with a leading ".". So this is a pretty - // simple lookup and per-cookie delete. +int CookieMonster::DeleteAllCreatedBetweenWithPredicate( + const base::Time& delete_begin, + const base::Time& delete_end, + const base::Callback<bool(const CanonicalCookie&)>& predicate) { int num_deleted = 0; - for (CookieMapItPair its = cookies_.equal_range(GetKey(host)); - its.first != its.second;) { - CookieMap::iterator curit = its.first; - ++its.first; - - const CanonicalCookie* const cc = curit->second; + for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { + CookieMap::iterator curit = it; + CanonicalCookie* cc = curit->second; + ++it; - // Delete only on a match as a host cookie. - if (cc->IsHostCookie() && cc->IsDomainMatch(host) && - cc->CreationDate() >= delete_begin && + if (cc->CreationDate() >= delete_begin && // The assumption that null |delete_end| is equivalent to // Time::Max() is confusing. - (delete_end.is_null() || cc->CreationDate() < delete_end)) { - num_deleted++; - - InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT); + (delete_end.is_null() || cc->CreationDate() < delete_end) && + predicate.Run(*cc)) { + InternalDeleteCookie(curit, true, /*sync_to_store*/ + DELETE_COOKIE_EXPLICIT); + ++num_deleted; } } + return num_deleted; } - bool CookieMonster::SetCookieWithOptions(const GURL& url, const std::string& cookie_line, const CookieOptions& options) { @@ -1727,7 +1769,7 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions( last_time_seen_ = creation_time; } - scoped_ptr<CanonicalCookie> cc( + std::unique_ptr<CanonicalCookie> cc( CanonicalCookie::Create(url, cookie_line, creation_time, options)); if (!cc.get()) { @@ -1737,7 +1779,7 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions( return SetCanonicalCookie(std::move(cc), options); } -bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie> cc, +bool CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc, const CookieOptions& options) { DCHECK(thread_checker_.CalledOnValidThread()); @@ -1795,7 +1837,7 @@ bool CookieMonster::SetCanonicalCookies(const CookieList& list) { options.set_include_httponly(); for (const auto& cookie : list) { - if (!SetCanonicalCookie(make_scoped_ptr(new CanonicalCookie(cookie)), + if (!SetCanonicalCookie(base::WrapUnique(new CanonicalCookie(cookie)), options)) { return false; } @@ -1877,15 +1919,6 @@ 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."; - 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 = @@ -1895,25 +1928,83 @@ size_t CookieMonster::GarbageCollect(const Time& current, // Sort the cookies by access date, from least-recent to most-recent. std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter); + size_t additional_quota_low = kDomainCookiesQuotaLow; + size_t additional_quota_medium = kDomainCookiesQuotaMedium; + size_t additional_quota_high = kDomainCookiesQuotaHigh; + // 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}; + // + // 1. Low-priority non-secure cookies. + // 2. Low-priority secure cookies. + // 3. Medium-priority non-secure cookies. + // 4. High-priority non-secure cookies. + // 5. Medium-priority secure cookies. + // 6. High-priority secure cookies. + const static struct { + CookiePriority priority; + bool protect_secure_cookies; + } purge_rounds[] = { + // 1. Low-priority non-secure cookies. + {COOKIE_PRIORITY_LOW, true}, + // 2. Low-priority secure cookies. + {COOKIE_PRIORITY_LOW, false}, + // 3. Medium-priority non-secure cookies. + {COOKIE_PRIORITY_MEDIUM, true}, + // 4. High-priority non-secure cookies. + {COOKIE_PRIORITY_HIGH, true}, + // 5. Medium-priority secure cookies. + {COOKIE_PRIORITY_MEDIUM, false}, + // 6. High-priority secure cookies. + {COOKIE_PRIORITY_HIGH, false}, + }; + 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); - DCHECK_LE(just_deleted, purge_goal); - purge_goal -= just_deleted; - num_deleted += just_deleted; + for (const auto& purge_round : purge_rounds) { + // Only observe the non-secure purge rounds if strict secure cookies is + // enabled. + if (!enforce_strict_secure && purge_round.protect_secure_cookies) + continue; + + // Only adjust the quota if the round is executing, otherwise it is + // necesary to delay quota adjustments until a later round. This is + // because if the high priority, non-secure round is skipped, its quota + // should not count until the later high priority, full round later. + size_t* additional_quota = nullptr; + switch (purge_round.priority) { + case COOKIE_PRIORITY_LOW: + additional_quota = &additional_quota_low; + break; + case COOKIE_PRIORITY_MEDIUM: + additional_quota = &additional_quota_medium; + break; + case COOKIE_PRIORITY_HIGH: + additional_quota = &additional_quota_high; + break; + } + quota += *additional_quota; + *additional_quota = 0u; + size_t just_deleted = 0u; + + // Purge up to |purge_goal| for all cookies at the given priority. This + // path will always execute if strict secure cookies is disabled since + // |purge_goal| must be positive because of the for-loop guard. If + // strict secure cookies is enabled, this path will be taken only if the + // initial non-secure purge did not evict enough cookies. + if (purge_goal > 0) { + just_deleted = PurgeLeastRecentMatches( + cookie_its, purge_round.priority, quota, purge_goal, + purge_round.protect_secure_cookies); + DCHECK_LE(just_deleted, purge_goal); + purge_goal -= just_deleted; + num_deleted += just_deleted; + } } - DCHECK_EQ(0U, purge_goal); + DCHECK_EQ(0u, purge_goal); } } @@ -1963,12 +2054,21 @@ size_t CookieMonster::GarbageCollect(const Time& current, size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, CookiePriority priority, size_t to_protect, - size_t purge_goal) { + size_t purge_goal, + bool protect_secure_cookies) { 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. + // + // If |protect_secure_cookies| is true, do a first pass that counts eligible + // secure cookies at the specified priority as protected. + if (protect_secure_cookies) { + to_protect -= std::min( + to_protect, CountProtectedSecureCookiesAtPriority(priority, cookies)); + } + size_t protection_boundary = cookies->size(); while (to_protect > 0 && protection_boundary > 0) { protection_boundary--; @@ -1982,7 +2082,12 @@ size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, size_t removed = 0; size_t current = 0; while (removed < purge_goal && current < protection_boundary) { - if (cookies->at(current)->second->Priority() <= priority) { + const CanonicalCookie* current_cookie = cookies->at(current)->second; + // Only delete the current cookie if the priority is less than or equal to + // the current level. If it is equal to the current level, and secure + // cookies are protected, only delete it if it is not secure. + if (IsCookieEligibleForEviction(priority, protect_secure_cookies, + current_cookie)) { InternalDeleteCookie(cookies->at(current), true, DELETE_COOKIE_EVICTED_DOMAIN); cookies->erase(cookies->begin() + current); @@ -2020,24 +2125,6 @@ size_t CookieMonster::GarbageCollectExpired(const Time& current, return num_deleted; } -size_t CookieMonster::GarbageCollectNonSecure( - const CookieItVector& valid_cookies, - CookieItVector* cookie_its) { - DCHECK(thread_checker_.CalledOnValidThread()); - - size_t num_deleted = 0; - for (const auto& curr_cookie_it : valid_cookies) { - if (!curr_cookie_it->second->IsSecure()) { - InternalDeleteCookie(curr_cookie_it, true, DELETE_COOKIE_NON_SECURE); - ++num_deleted; - } else if (cookie_its) { - cookie_its->push_back(curr_cookie_it); - } - } - - return num_deleted; -} - size_t CookieMonster::GarbageCollectDeleteRange( const Time& current, DeletionCause cause, diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h index 747ffdd5d9b..850ad9422b8 100644 --- a/chromium/net/cookies/cookie_monster.h +++ b/chromium/net/cookies/cookie_monster.h @@ -12,6 +12,7 @@ #include <deque> #include <map> +#include <memory> #include <queue> #include <set> #include <string> @@ -23,7 +24,6 @@ #include "base/macros.h" #include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" @@ -180,10 +180,10 @@ class NET_EXPORT CookieMonster : public CookieStore { void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin, const base::Time& delete_end, const DeleteCallback& callback) override; - void DeleteAllCreatedBetweenForHostAsync( - const base::Time delete_begin, - const base::Time delete_end, - const GURL& url, + void DeleteAllCreatedBetweenWithPredicateAsync( + const base::Time& delete_begin, + const base::Time& delete_end, + const base::Callback<bool(const CanonicalCookie&)>& predicate, const DeleteCallback& callback) override; void DeleteSessionCookiesAsync(const DeleteCallback&) override; void FlushStore(const base::Closure& callback) override; @@ -207,7 +207,7 @@ class NET_EXPORT CookieMonster : public CookieStore { static const char* const kDefaultCookieableSchemes[]; static const int kDefaultCookieableSchemesCount; - scoped_ptr<CookieChangedSubscription> AddCallbackForCookie( + std::unique_ptr<CookieChangedSubscription> AddCallbackForCookie( const GURL& url, const std::string& name, const CookieChangedCallback& callback) override; @@ -220,7 +220,7 @@ class NET_EXPORT CookieMonster : public CookieStore { template <typename Result> class DeleteTask; class DeleteAllCreatedBetweenTask; - class DeleteAllCreatedBetweenForHostTask; + class DeleteAllCreatedBetweenWithPredicateTask; class DeleteCookieTask; class DeleteCanonicalCookieTask; class GetCookieListForURLWithOptionsTask; @@ -236,6 +236,9 @@ class NET_EXPORT CookieMonster : public CookieStore { // For SetCookieWithCreationTime. FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps); + FRIEND_TEST_ALL_PREFIXES( + CookieMonsterTest, + TestCookieDeleteAllCreatedBetweenTimestampsWithPredicate); // For gargage collection constants. FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestHostGarbageCollection); @@ -403,9 +406,11 @@ class NET_EXPORT CookieMonster : public CookieStore { int DeleteAllCreatedBetween(const base::Time& delete_begin, const base::Time& delete_end); - int DeleteAllCreatedBetweenForHost(const base::Time delete_begin, - const base::Time delete_end, - const GURL& url); + // Predicate will be called with the calling thread. + int DeleteAllCreatedBetweenWithPredicate( + const base::Time& delete_begin, + const base::Time& delete_end, + const base::Callback<bool(const CanonicalCookie&)>& predicate); bool SetCookieWithOptions(const GURL& url, const std::string& cookie_line, @@ -511,7 +516,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // Helper function that sets a canonical cookie, deleting equivalents and // performing garbage collection. - bool SetCanonicalCookie(scoped_ptr<CanonicalCookie> cc, + bool SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc, const CookieOptions& options); // Helper function calling SetCanonicalCookie() for all cookies in |list|. @@ -541,6 +546,8 @@ class NET_EXPORT CookieMonster : public CookieStore { // Helper for GarbageCollect(). Deletes up to |purge_goal| cookies with a // priority less than or equal to |priority| from |cookies|, while ensuring // that at least the |to_protect| most-recent cookies are retained. + // |protected_secure_cookies| specifies whether or not secure cookies should + // be protected from deletion. // // |cookies| must be sorted from least-recent to most-recent. // @@ -548,7 +555,8 @@ class NET_EXPORT CookieMonster : public CookieStore { size_t PurgeLeastRecentMatches(CookieItVector* cookies, CookiePriority priority, size_t to_protect, - size_t purge_goal); + size_t purge_goal, + bool protect_secure_cookies); // Helper for GarbageCollect(); can be called directly as well. Deletes all // expired cookies in |itpair|. If |cookie_its| is non-NULL, all the @@ -559,14 +567,6 @@ class NET_EXPORT CookieMonster : public CookieStore { const CookieMapItPair& itpair, CookieItVector* cookie_its); - // Helper for GarbageCollect(). Deletes all cookies not marked Secure in - // |valid_cookies_its|. If |cookie_its| is non-NULL, all the Secure cookies - // from |itpair| are appended to |cookie_its|. - // - // Returns the numeber of cookies deleted. - size_t GarbageCollectNonSecure(const CookieItVector& valid_cookies, - CookieItVector* cookie_its); - // Helper for GarbageCollect(). Deletes all cookies in the range specified by // [|it_begin|, |it_end|). Returns the number of cookies deleted. size_t GarbageCollectDeleteRange(const base::Time& current, diff --git a/chromium/net/cookies/cookie_monster_perftest.cc b/chromium/net/cookies/cookie_monster_perftest.cc index 1dcb2769733..c56bef6783f 100644 --- a/chromium/net/cookies/cookie_monster_perftest.cc +++ b/chromium/net/cookies/cookie_monster_perftest.cc @@ -3,10 +3,10 @@ // found in the LICENSE file. #include <algorithm> +#include <memory> #include "base/bind.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -35,7 +35,7 @@ class CookieMonsterTest : public testing::Test { CookieMonsterTest() : message_loop_(new base::MessageLoopForIO()) {} private: - scoped_ptr<base::MessageLoop> message_loop_; + std::unique_ptr<base::MessageLoop> message_loop_; }; class BaseCallback { @@ -121,7 +121,7 @@ TEST(ParsedCookieTest, TestParseBigCookies) { } TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); std::vector<std::string> cookies; for (int i = 0; i < kNumCookies; i++) { cookies.push_back(base::StringPrintf("a%03d=b", i)); @@ -154,7 +154,7 @@ TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) { } TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); std::string cookie(kCookieLine); std::vector<GURL> gurls; // just wanna have ffffuunnn for (int i = 0; i < kNumCookies; ++i) { @@ -187,7 +187,7 @@ TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) { } TEST_F(CookieMonsterTest, TestDomainTree) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); GetCookiesCallback getCookiesCallback; SetCookieCallback setCookieCallback; const char domain_cookie_format_tree[] = "a=b; domain=%s"; @@ -240,7 +240,7 @@ TEST_F(CookieMonsterTest, TestDomainTree) { } TEST_F(CookieMonsterTest, TestDomainLine) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); SetCookieCallback setCookieCallback; GetCookiesCallback getCookiesCallback; std::vector<std::string> domain_list; @@ -301,7 +301,7 @@ TEST_F(CookieMonsterTest, TestImport) { store->SetLoadExpectation(true, initial_cookies); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); // Import will happen on first access. GURL gurl("www.google.com"); @@ -315,7 +315,7 @@ TEST_F(CookieMonsterTest, TestImport) { } TEST_F(CookieMonsterTest, TestGetKey) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); base::PerfTimeLogger timer("Cookie_monster_get_key"); for (int i = 0; i < kNumCookies; i++) cm->GetKey("www.google.com"); @@ -371,7 +371,7 @@ TEST_F(CookieMonsterTest, TestGCTimes) { }; for (int ci = 0; ci < static_cast<int>(arraysize(test_cases)); ++ci) { const TestCase& test_case(test_cases[ci]); - scoped_ptr<CookieMonster> cm = CreateMonsterFromStoreForGC( + std::unique_ptr<CookieMonster> cm = CreateMonsterFromStoreForGC( test_case.num_cookies, test_case.num_old_cookies, 0, 0, CookieMonster::kSafeFromGlobalPurgeDays * 2); diff --git a/chromium/net/cookies/cookie_monster_store_test.cc b/chromium/net/cookies/cookie_monster_store_test.cc index 4573d4ad881..9d825900029 100644 --- a/chromium/net/cookies/cookie_monster_store_test.cc +++ b/chromium/net/cookies/cookie_monster_store_test.cc @@ -6,9 +6,10 @@ #include "base/bind.h" #include "base/location.h" +#include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_util.h" @@ -123,7 +124,7 @@ void MockCookieMonsterDelegate::OnCookieChanged( MockCookieMonsterDelegate::~MockCookieMonsterDelegate() { } -scoped_ptr<CanonicalCookie> BuildCanonicalCookie( +std::unique_ptr<CanonicalCookie> BuildCanonicalCookie( const GURL& url, const std::string& cookie_line, const base::Time& creation_time) { @@ -151,7 +152,7 @@ void AddCookieToList(const GURL& url, const std::string& cookie_line, const base::Time& creation_time, std::vector<CanonicalCookie*>* out_list) { - scoped_ptr<CanonicalCookie> cookie( + std::unique_ptr<CanonicalCookie> cookie( BuildCanonicalCookie(url, cookie_line, creation_time)); out_list->push_back(cookie.release()); @@ -219,7 +220,7 @@ void MockSimplePersistentCookieStore::Flush(const base::Closure& callback) { void MockSimplePersistentCookieStore::SetForceKeepSessionState() { } -scoped_ptr<CookieMonster> CreateMonsterFromStoreForGC( +std::unique_ptr<CookieMonster> CreateMonsterFromStoreForGC( int num_secure_cookies, int num_old_secure_cookies, int num_non_secure_cookies, @@ -258,7 +259,7 @@ scoped_ptr<CookieMonster> CreateMonsterFromStoreForGC( store->AddCookie(cc); } - return make_scoped_ptr(new CookieMonster(store.get(), nullptr)); + return base::WrapUnique(new CookieMonster(store.get(), nullptr)); } MockSimplePersistentCookieStore::~MockSimplePersistentCookieStore() { diff --git a/chromium/net/cookies/cookie_monster_store_test.h b/chromium/net/cookies/cookie_monster_store_test.h index aac83f82992..9145e184958 100644 --- a/chromium/net/cookies/cookie_monster_store_test.h +++ b/chromium/net/cookies/cookie_monster_store_test.h @@ -13,12 +13,12 @@ #include <stdint.h> #include <map> +#include <memory> #include <string> #include <utility> #include <vector> #include "base/macros.h" -#include "base/memory/scoped_ptr.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_monster.h" @@ -168,7 +168,7 @@ class MockCookieMonsterDelegate : public CookieMonsterDelegate { }; // Helper to build a single CanonicalCookie. -scoped_ptr<CanonicalCookie> BuildCanonicalCookie( +std::unique_ptr<CanonicalCookie> BuildCanonicalCookie( const GURL& url, const std::string& cookie_line, const base::Time& creation_time); @@ -223,7 +223,7 @@ class MockSimplePersistentCookieStore // will be marked secure and non-secure, respectively. Do two SetCookies(). // Return whether each of the two SetCookies() took longer than |gc_perf_micros| // to complete, and how many cookie were left in the store afterwards. -scoped_ptr<CookieMonster> CreateMonsterFromStoreForGC( +std::unique_ptr<CookieMonster> CreateMonsterFromStoreForGC( int num_secure_cookies, int num_old_secure_cookies, int num_non_secure_cookies, diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc index 4665a0fc2ed..ab74c667f19 100644 --- a/chromium/net/cookies/cookie_monster_unittest.cc +++ b/chromium/net/cookies/cookie_monster_unittest.cc @@ -2,16 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/cookies/cookie_store_unittest.h" +#include "net/cookies/cookie_monster.h" #include <algorithm> +#include <memory> #include <string> #include <vector> #include "base/bind.h" #include "base/location.h" +#include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" #include "base/metrics/histogram_samples.h" @@ -22,13 +23,13 @@ #include "base/strings/string_tokenizer.h" #include "base/strings/stringprintf.h" #include "base/test/histogram_tester.h" -#include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_constants.h" -#include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_monster_store_test.h" // For CookieStore mock +#include "net/cookies/cookie_store_unittest.h" #include "net/cookies/cookie_util.h" #include "net/cookies/parsed_cookie.h" #include "testing/gmock/include/gmock/gmock.h" @@ -37,6 +38,7 @@ namespace net { +using CookiePredicate = CookieStore::CookiePredicate; using base::Time; using base::TimeDelta; @@ -64,15 +66,39 @@ class NewMockPersistentCookieStore virtual ~NewMockPersistentCookieStore() {} }; +// False means 'less than or equal', so we test both ways for full equal. +MATCHER_P(CookieEquals, expected, "") { + return !(arg.FullCompare(expected) || expected.FullCompare(arg)); +} + const char kTopLevelDomainPlus1[] = "http://www.harvard.edu"; const char kTopLevelDomainPlus2[] = "http://www.math.harvard.edu"; const char kTopLevelDomainPlus2Secure[] = "https://www.math.harvard.edu"; const char kTopLevelDomainPlus3[] = "http://www.bourbaki.math.harvard.edu"; const char kOtherDomain[] = "http://www.mit.edu"; +bool AlwaysTrueCookiePredicate(CanonicalCookie* to_save, + const CanonicalCookie& cookie) { + if (to_save) + *to_save = cookie; + return true; +} + +bool AlwaysFalseCookiePredicate(CanonicalCookie* to_save, + const CanonicalCookie& cookie) { + if (to_save) + *to_save = cookie; + return false; +} + +bool CookieValuePredicate(const std::string& true_value, + const CanonicalCookie& cookie) { + return cookie.Value() == true_value; +} + struct CookieMonsterTestTraits { - static scoped_ptr<CookieStore> Create() { - return make_scoped_ptr(new CookieMonster(nullptr, nullptr)); + static std::unique_ptr<CookieStore> Create() { + return base::WrapUnique(new CookieMonster(nullptr, nullptr)); } static const bool supports_http_only = true; @@ -85,8 +111,8 @@ struct CookieMonsterTestTraits { }; struct CookieMonsterEnforcingStrictSecure { - static scoped_ptr<CookieStore> Create() { - return make_scoped_ptr(new CookieMonster(nullptr, nullptr)); + static std::unique_ptr<CookieStore> Create() { + return base::WrapUnique(new CookieMonster(nullptr, nullptr)); } static const bool supports_http_only = true; @@ -150,23 +176,23 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { return callback.result(); } - int DeleteAllCreatedBetweenForHost(CookieMonster* cm, - const base::Time delete_begin, - const base::Time delete_end, - const GURL& url) { + int DeleteAllCreatedBetweenWithPredicate(CookieMonster* cm, + const base::Time delete_begin, + const base::Time delete_end, + const CookiePredicate& predicate) { DCHECK(cm); ResultSavingCookieCallback<int> callback; - cm->DeleteAllCreatedBetweenForHostAsync( - delete_begin, delete_end, url, + cm->DeleteAllCreatedBetweenWithPredicateAsync( + delete_begin, delete_end, predicate, base::Bind(&ResultSavingCookieCallback<int>::Run, base::Unretained(&callback))); callback.WaitUntilDone(); return callback.result(); } - // Helper for DeleteAllForHost test; repopulates CM with same layout + // Helper for PredicateSeesAllCookies test; repopulates CM with same layout // each time. - void PopulateCmForDeleteAllForHost(CookieMonster* cm) { + void PopulateCmForPredicateCheck(CookieMonster* cm) { GURL url_top_level_domain_plus_1(kTopLevelDomainPlus1); GURL url_top_level_domain_plus_2(kTopLevelDomainPlus2); GURL url_top_level_domain_plus_2_secure(kTopLevelDomainPlus2Secure); @@ -186,72 +212,72 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { // Domain cookies EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_1, "dom_1", "X", ".harvard.edu", "/", + cm, url_top_level_domain_plus_1, "dom_1", "A", ".harvard.edu", "/", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2, "dom_2", "X", ".math.harvard.edu", "/", + cm, url_top_level_domain_plus_2, "dom_2", "B", ".math.harvard.edu", "/", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_3, "dom_3", "X", + cm, url_top_level_domain_plus_3, "dom_3", "C", ".bourbaki.math.harvard.edu", "/", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); // Host cookies EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_1, "host_1", "X", std::string(), "/", + cm, url_top_level_domain_plus_1, "host_1", "A", std::string(), "/", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2, "host_2", "X", std::string(), "/", + cm, url_top_level_domain_plus_2, "host_2", "B", std::string(), "/", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_3, "host_3", "X", std::string(), "/", + cm, url_top_level_domain_plus_3, "host_3", "C", std::string(), "/", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); // http_only cookie EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2, "httpo_check", "x", std::string(), "/", + cm, url_top_level_domain_plus_2, "httpo_check", "A", std::string(), "/", base::Time(), base::Time(), base::Time(), false, true, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); // same-site cookie EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2, "firstp_check", "x", std::string(), + cm, url_top_level_domain_plus_2, "firstp_check", "A", std::string(), "/", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT)); // Secure cookies EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2_secure, "sec_dom", "X", + cm, url_top_level_domain_plus_2_secure, "sec_dom", "A", ".math.harvard.edu", "/", base::Time(), base::Time(), base::Time(), true, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2_secure, "sec_host", "X", std::string(), + cm, url_top_level_domain_plus_2_secure, "sec_host", "B", std::string(), "/", base::Time(), base::Time(), base::Time(), true, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); // Domain path cookies EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2, "dom_path_1", "X", ".math.harvard.edu", + cm, url_top_level_domain_plus_2, "dom_path_1", "A", ".math.harvard.edu", "/dir1", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2, "dom_path_2", "X", ".math.harvard.edu", + cm, url_top_level_domain_plus_2, "dom_path_2", "B", ".math.harvard.edu", "/dir1/dir2", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); // Host path cookies EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2, "host_path_1", "X", std::string(), + cm, url_top_level_domain_plus_2, "host_path_1", "A", std::string(), "/dir1", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_TRUE(this->SetCookieWithDetails( - cm, url_top_level_domain_plus_2, "host_path_2", "X", std::string(), + cm, url_top_level_domain_plus_2, "host_path_2", "B", std::string(), "/dir1/dir2", base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); @@ -284,7 +310,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { (domain_max_cookies + domain_purge_cookies) * 2; // Add a bunch of cookies on a single host, should purge them. { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); for (int i = 0; i < more_than_enough_cookies; ++i) { std::string cookie = base::StringPrintf("a%03d=b", i); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), cookie)); @@ -302,7 +328,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { // between them. We shouldn't go above kDomainMaxCookies for both together. GURL url_google_specific(http_www_google_.Format("http://www.gmail.%D")); { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); for (int i = 0; i < more_than_enough_cookies; ++i) { std::string cookie_general = base::StringPrintf("a%03d=b", i); EXPECT_TRUE( @@ -348,11 +374,12 @@ 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. - // |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. + // + // 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. + // // 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,42 +388,55 @@ 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_high_count, + size_t expected_nonsecure, + size_t expected_secure) { SCOPED_TRACE(coded_priority_str); this->DeleteAll(cm); int next_cookie_id = 0; - std::vector<CookiePriority> priority_list; - std::vector<int> id_list[3]; // Indexed by CookiePriority. + // 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; // 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 priority. - CookiePriority priority = CharToPriority(token.back()); - std::string priority_str = CookiePriorityToString(priority); - // The rest of the string (possibly empty) specifies repetition. + + 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]); + + // Discard the security status and priority tokens. 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() - 1), &rep); + base::StringPiece(token.begin(), token.end() - 2), &rep); DCHECK(result); } for (; rep > 0; --rep, ++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); + 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); } } - int num_cookies = static_cast<int>(priority_list.size()); - std::vector<int> surviving_id_list[3]; // Indexed by CookiePriority. + 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]; // Parse the list of cookies - std::string cookie_str = this->GetCookies(cm, http_www_google_.url()); + std::string cookie_str = this->GetCookies(cm, https_www_google_.url()); + size_t num_nonsecure = 0; + size_t num_secure = 0; 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. @@ -406,22 +446,40 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { DCHECK(result); DCHECK_GE(id, 0); DCHECK_LT(id, num_cookies); - surviving_id_list[priority_list[id]].push_back(id); + 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; } + 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) { - DCHECK_LE(surviving_id_list[i].size(), id_list[i].size()); - EXPECT_EQ(expected_count[i], surviving_id_list[i].size()); + 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); // Verify that the remaining cookies are the most recent among those // with the same priorities. - 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])); + 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())); } } } @@ -446,7 +504,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { size_t expected_secure_cookies, size_t expected_non_secure_cookies, const AltHosts* alt_host_entries) { - scoped_ptr<CookieMonster> cm; + std::unique_ptr<CookieMonster> cm; if (alt_host_entries == nullptr) { cm.reset(new CookieMonster(nullptr, nullptr)); @@ -488,54 +546,197 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { EXPECT_EQ(expected_non_secure_cookies, total_non_secure_cookies); } - void TestPriorityAwareGarbageCollectHelper() { + 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); + + std::unique_ptr<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); + + // TODO(jww): According to + // https://tools.ietf.org/html/draft-west-cookie-priority#section-3, it + // seems that quotas are a mechanism for preventing another application on + // the same doman from DoS'ing an application by constantly evicting *all* + // lower priority cookies. + // + // Unfortunately, this has never strictly worked in our implementation. Take + // the following test as an example: + // TestPriorityCookieCase(cm.get(), "50LN 131HN", 30U, 0U, 120U, 150U, 0U); + // + // According to this theory, we would expect eviction to proceed as: + // Round 1 => 20L; round 2 => 0; round 3 => 11H + // thus resulting in 30L and 120H at the end. + // + // However, what happens in practice is that the cookies left are 19L and + // 131H. This is because the quotas are accumulated over the rounds and what + // priority they apply to is lost information. Since in the last round all + // that is known is a total quota, and the low-priority cookies are least + // recently accessed, they are evicted first to get down to 150 cookies. + // + // We should address this and uncomment the test below when it is fixed. + // + // See https://crbug.com/609550 + // + // Round 1 => 20L; round 2 => 0; round 3 => 11H + // TestPriorityCookieCase(cm.get(), "50LN 131HN", 30U, 0U, 120U, 150U, 0U); + // Round 1 => 20L; round 2 => 0; round 3 => 11H + TestPriorityCookieCase(cm.get(), "131HN 50LN", 30U, 0U, 120U, 150U, 0U); + // Round 1 => 20L; round 2 => none; round 3 => 11H. + TestPriorityCookieCase(cm.get(), "50HN 50LN 81HN", 30U, 0U, 120U, 150U, 0U); + // Round 1 => 20L; round 2 => none; round 3 => 11H. + TestPriorityCookieCase(cm.get(), "81HN 50LN 50HN", 30U, 0U, 120U, 150U, 0U); + } + + void TestPriorityAwareGarbageCollectHelperSecure() { // 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_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); // Each test case adds 181 cookies, so 31 cookies are evicted. // Cookie same priority, repeated for each priority. - TestPriorityCookieCase(cm.get(), "181L", 150U, 0U, 0U); - TestPriorityCookieCase(cm.get(), "181M", 0U, 150U, 0U); - TestPriorityCookieCase(cm.get(), "181H", 0U, 0U, 150U); + 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); // Pairwise scenarios. // Round 1 => none; round2 => 31M; round 3 => none. - TestPriorityCookieCase(cm.get(), "10H 171M", 0U, 140U, 10U); + TestPriorityCookieCase(cm.get(), "10HS 171MS", 0U, 140U, 10U, 0U, 150U); // Round 1 => 10L; round2 => 21M; round 3 => none. - TestPriorityCookieCase(cm.get(), "141M 40L", 30U, 120U, 0U); + TestPriorityCookieCase(cm.get(), "141MS 40LS", 30U, 120U, 0U, 0U, 150U); // Round 1 => none; round2 => none; round 3 => 31H. - TestPriorityCookieCase(cm.get(), "101H 80M", 0U, 80U, 70U); + TestPriorityCookieCase(cm.get(), "101HS 80MS", 0U, 80U, 70U, 0U, 150U); // For {low, medium} priorities right on quota, different orders. // Round 1 => 1L; round 2 => none, round3 => 30L. - TestPriorityCookieCase(cm.get(), "31L 50M 100H", 0U, 50U, 100U); + TestPriorityCookieCase(cm.get(), "31LS 50MS 100HS", 0U, 50U, 100U, 0U, + 150U); // Round 1 => none; round 2 => 1M, round3 => 30M. - TestPriorityCookieCase(cm.get(), "51M 100H 30L", 30U, 20U, 100U); + TestPriorityCookieCase(cm.get(), "51MS 100HS 30LS", 30U, 20U, 100U, 0U, + 150U); // Round 1 => none; round 2 => none; round3 => 31H. - TestPriorityCookieCase(cm.get(), "101H 50M 30L", 30U, 50U, 70U); + TestPriorityCookieCase(cm.get(), "101HS 50MS 30LS", 30U, 50U, 70U, 0U, + 150U); // Round 1 => 10L; round 2 => 10M; round3 => 11H. - TestPriorityCookieCase(cm.get(), "81H 60M 40L", 30U, 50U, 70U); + TestPriorityCookieCase(cm.get(), "81HS 60MS 40LS", 30U, 50U, 70U, 0U, 150U); // More complex scenarios. // Round 1 => 10L; round 2 => 10M; round 3 => 11H. - TestPriorityCookieCase(cm.get(), "21H 60M 40L 60H", 30U, 50U, 70U); + TestPriorityCookieCase(cm.get(), "21HS 60MS 40LS 60HS", 30U, 50U, 70U, 0U, + 150U); // Round 1 => 10L; round 2 => 11M, 10L; round 3 => none. - TestPriorityCookieCase(cm.get(), "11H 10M 20L 110M 20L 10H", 20U, 109U, - 21U); + TestPriorityCookieCase(cm.get(), "11HS 10MS 20LS 110MS 20LS 10HS", 20U, + 109U, 21U, 0U, 150U); // Round 1 => none; round 2 => none; round 3 => 11L, 10M, 10H. - TestPriorityCookieCase(cm.get(), "11L 10M 140H 10M 10L", 10U, 10U, 130U); + TestPriorityCookieCase(cm.get(), "11LS 10MS 140HS 10MS 10LS", 10U, 10U, + 130U, 0U, 150U); // Round 1 => none; round 2 => 1M; round 3 => 10L, 10M, 10H. - TestPriorityCookieCase(cm.get(), "11M 10H 10L 60M 90H", 0U, 60U, 90U); + TestPriorityCookieCase(cm.get(), "11MS 10HS 10LS 60MS 90HS", 0U, 60U, 90U, + 0U, 150U); // Round 1 => none; round 2 => 10L, 21M; round 3 => none. - TestPriorityCookieCase(cm.get(), "11M 10H 10L 90M 60H", 0U, 80U, 70U); + 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); + + std::unique_ptr<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); + + // Low-priority secure cookies are removed before higher priority non-secure + // cookies. + TestPriorityCookieCase(cm.get(), "180LS 1MN", 149U, 1U, 0U, 1U, 149U); + TestPriorityCookieCase(cm.get(), "180LS 1HN", 149U, 0U, 1U, 1U, 149U); + TestPriorityCookieCase(cm.get(), "1MN 180LS", 149U, 1U, 0U, 1U, 149U); + TestPriorityCookieCase(cm.get(), "1HN 180LS", 149U, 0U, 1U, 1U, 149U); + + // Higher-priority non-secure cookies are removed before any secure cookie + // with greater than low-priority. + TestPriorityCookieCase(cm.get(), "180MS 1HN", 0U, 150U, 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", 0U, 0U, 150U, 150U, 0U); + TestPriorityCookieCase(cm.get(), "100LS 81HN", 69U, 0U, 81U, 81U, 69U); + TestPriorityCookieCase(cm.get(), "150LS 31HN", 119U, 0U, 31U, 31U, 119U); + + // Quota calculations inside non-secure/secure blocks remain in place: + // Round 1 => 20LS; round 2 => none; round 3 => 11HN. + TestPriorityCookieCase(cm.get(), "50HN 50LS 81HS", 30U, 0U, 120U, 39U, + 111U); + // Round 1 => none; round 2 => 10LS, 21MN; round 3 => none. + TestPriorityCookieCase(cm.get(), "11MS 10HN 10LS 90MN 60HN", 0U, 80U, 70U, + 139U, 11U); + + // Multiple GC rounds end up with consistent behavior: + TestPriorityCookieCase(cm.get(), "100HS 100LN 100MN", 0, 76U, 100U, 76U, + 100U); } // Function for creating a CM with a number of cookies in it, @@ -667,14 +868,14 @@ ACTION_P2(GetAllCookiesAction, cookie_monster, callback) { cookie_monster->GetAllCookiesAsync(callback->AsCallback()); } -ACTION_P5(DeleteAllCreatedBetweenForHostAction, +ACTION_P5(DeleteAllCreatedBetweenWithPredicateAction, cookie_monster, delete_begin, delete_end, - url, + predicate, callback) { - cookie_monster->DeleteAllCreatedBetweenForHostAsync( - delete_begin, delete_end, url, callback->AsCallback()); + cookie_monster->DeleteAllCreatedBetweenWithPredicateAsync( + delete_begin, delete_end, predicate, callback->AsCallback()); } ACTION_P3(DeleteCanonicalCookieAction, cookie_monster, cookie, callback) { @@ -804,7 +1005,7 @@ class DeferredCookieTaskTest : public CookieMonsterTest { // Indicates whether ExpectLoadCall() has been called. bool expect_load_called_; // Stores the CookieMonster under test. - scoped_ptr<CookieMonster> cookie_monster_; + std::unique_ptr<CookieMonster> cookie_monster_; // Stores the mock PersistentCookieStore. scoped_refptr<NewMockPersistentCookieStore> persistent_store_; }; @@ -1050,20 +1251,22 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedBetweenCookies) { loop.Run(); } -TEST_F(DeferredCookieTaskTest, DeferredDeleteAllForHostCreatedBetweenCookies) { +TEST_F(DeferredCookieTaskTest, + DeferredDeleteAllWithPredicateCreatedBetweenCookies) { MockDeleteCallback delete_callback; - BeginWithForDomainKey(http_www_google_.domain(), - DeleteAllCreatedBetweenForHostAction( - &cookie_monster(), base::Time(), base::Time::Now(), - http_www_google_.url(), &delete_callback)); + CookiePredicate predicate = base::Bind(&AlwaysTrueCookiePredicate, nullptr); + + BeginWith(DeleteAllCreatedBetweenWithPredicateAction( + &cookie_monster(), base::Time(), base::Time::Now(), predicate, + &delete_callback)); WaitForLoadCall(); EXPECT_CALL(delete_callback, Invoke(false)) - .WillOnce(DeleteAllCreatedBetweenForHostAction( - &cookie_monster(), base::Time(), base::Time::Now(), - http_www_google_.url(), &delete_callback)); + .WillOnce(DeleteAllCreatedBetweenWithPredicateAction( + &cookie_monster(), base::Time(), base::Time::Now(), predicate, + &delete_callback)); base::RunLoop loop; EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop)); @@ -1073,7 +1276,7 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteAllForHostCreatedBetweenCookies) { TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) { std::vector<CanonicalCookie*> cookies; - scoped_ptr<CanonicalCookie> cookie = BuildCanonicalCookie( + std::unique_ptr<CanonicalCookie> cookie = BuildCanonicalCookie( http_www_google_.url(), "X=1; path=/", base::Time::Now()); MockDeleteCallback delete_cookie_callback; @@ -1147,7 +1350,7 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) { TEST_F(CookieMonsterTest, TestCookieDeleteAll) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); CookieOptions options; options.set_include_httponly(); @@ -1180,14 +1383,14 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAll) { } TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); Time now = Time::Now(); // Nothing has been added so nothing should be deleted. EXPECT_EQ(0, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(99), Time())); - // Create 3 cookies with creation date of today, yesterday and the day before. + // Create 5 cookies with different creation dates. EXPECT_TRUE( cm->SetCookieWithCreationTime(http_www_google_.url(), "T-0=Now", now)); EXPECT_TRUE(cm->SetCookieWithCreationTime( @@ -1219,13 +1422,97 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) { EXPECT_EQ(0, DeleteAll(cm.get())); } +TEST_F(CookieMonsterTest, + TestCookieDeleteAllCreatedBetweenTimestampsWithPredicate) { + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + Time now = Time::Now(); + + CanonicalCookie test_cookie; + CookiePredicate true_predicate = + base::Bind(&AlwaysTrueCookiePredicate, &test_cookie); + + CookiePredicate false_predicate = + base::Bind(&AlwaysFalseCookiePredicate, &test_cookie); + + // Nothing has been added so nothing should be deleted. + EXPECT_EQ( + 0, DeleteAllCreatedBetweenWithPredicate( + cm.get(), now - TimeDelta::FromDays(99), Time(), true_predicate)); + + // Create 5 cookies with different creation dates. + EXPECT_TRUE( + cm->SetCookieWithCreationTime(http_www_google_.url(), "T-0=Now", now)); + EXPECT_TRUE(cm->SetCookieWithCreationTime( + http_www_google_.url(), "T-1=Yesterday", now - TimeDelta::FromDays(1))); + EXPECT_TRUE(cm->SetCookieWithCreationTime( + http_www_google_.url(), "T-2=DayBefore", now - TimeDelta::FromDays(2))); + EXPECT_TRUE(cm->SetCookieWithCreationTime( + http_www_google_.url(), "T-3=ThreeDays", now - TimeDelta::FromDays(3))); + EXPECT_TRUE(cm->SetCookieWithCreationTime( + http_www_google_.url(), "T-7=LastWeek", now - TimeDelta::FromDays(7))); + + // Try to delete threedays and the daybefore, but we should do nothing due + // to the predicate. + EXPECT_EQ(0, DeleteAllCreatedBetweenWithPredicate( + cm.get(), now - TimeDelta::FromDays(3), + now - TimeDelta::FromDays(1), false_predicate)); + // Same as above with a null predicate, so it shouldn't delete anything. + EXPECT_EQ(0, DeleteAllCreatedBetweenWithPredicate( + cm.get(), now - TimeDelta::FromDays(3), + now - TimeDelta::FromDays(1), CookiePredicate())); + // Same as above, but we use the true_predicate, so it works. + EXPECT_EQ(2, DeleteAllCreatedBetweenWithPredicate( + cm.get(), now - TimeDelta::FromDays(3), + now - TimeDelta::FromDays(1), true_predicate)); + + // Try to delete yesterday, also make sure that delete_end is not + // inclusive. + EXPECT_EQ(0, + DeleteAllCreatedBetweenWithPredicate( + cm.get(), now - TimeDelta::FromDays(2), now, false_predicate)); + EXPECT_EQ(1, + DeleteAllCreatedBetweenWithPredicate( + cm.get(), now - TimeDelta::FromDays(2), now, true_predicate)); + // Check our cookie values. + std::unique_ptr<CanonicalCookie> expected_cookie = + CanonicalCookie::Create(http_www_google_.url(), "T-1=Yesterday", + now - TimeDelta::FromDays(1), CookieOptions()); + EXPECT_THAT(test_cookie, CookieEquals(*expected_cookie)) + << "Actual:\n" + << test_cookie.DebugString() << "\nExpected:\n" + << expected_cookie->DebugString(); + + // Make sure the delete_begin is inclusive. + EXPECT_EQ(0, + DeleteAllCreatedBetweenWithPredicate( + cm.get(), now - TimeDelta::FromDays(7), now, false_predicate)); + EXPECT_EQ(1, + DeleteAllCreatedBetweenWithPredicate( + cm.get(), now - TimeDelta::FromDays(7), now, true_predicate)); + + // Delete the last (now) item. + EXPECT_EQ(0, DeleteAllCreatedBetweenWithPredicate(cm.get(), Time(), Time(), + false_predicate)); + EXPECT_EQ(1, DeleteAllCreatedBetweenWithPredicate(cm.get(), Time(), Time(), + true_predicate)); + expected_cookie = CanonicalCookie::Create(http_www_google_.url(), "T-0=Now", + now, CookieOptions()); + EXPECT_THAT(test_cookie, CookieEquals(*expected_cookie)) + << "Actual:\n" + << test_cookie.DebugString() << "\nExpected:\n" + << expected_cookie->DebugString(); + + // Really make sure everything is gone. + EXPECT_EQ(0, DeleteAll(cm.get())); +} + static const base::TimeDelta kLastAccessThreshold = base::TimeDelta::FromMilliseconds(200); static const base::TimeDelta kAccessDelay = kLastAccessThreshold + base::TimeDelta::FromMilliseconds(20); TEST_F(CookieMonsterTest, TestLastAccess) { - scoped_ptr<CookieMonster> cm( + std::unique_ptr<CookieMonster> cm( new CookieMonster(nullptr, nullptr, kLastAccessThreshold)); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B")); @@ -1267,13 +1554,21 @@ TEST_F(CookieMonsterTest, TestHostGarbageCollection) { TestHostGarbageCollectHelper(); } -TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollection) { - TestPriorityAwareGarbageCollectHelper(); +TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollectionNonSecure) { + TestPriorityAwareGarbageCollectHelperNonSecure(); +} + +TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollectionSecure) { + TestPriorityAwareGarbageCollectHelperSecure(); +} + +TEST_F(CookieMonsterStrictSecureTest, TestPriorityAwareGarbageCollectionMixed) { + TestPriorityAwareGarbageCollectHelperMixed(); } TEST_F(CookieMonsterTest, SetCookieableSchemes) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); - scoped_ptr<CookieMonster> cm_foo(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm_foo(new CookieMonster(nullptr, nullptr)); // Only cm_foo should allow foo:// cookies. std::vector<std::string> schemes; @@ -1290,7 +1585,7 @@ TEST_F(CookieMonsterTest, SetCookieableSchemes) { } TEST_F(CookieMonsterTest, GetAllCookiesForURL) { - scoped_ptr<CookieMonster> cm( + std::unique_ptr<CookieMonster> cm( new CookieMonster(nullptr, nullptr, kLastAccessThreshold)); // Create an httponly cookie. @@ -1358,7 +1653,7 @@ TEST_F(CookieMonsterTest, GetAllCookiesForURL) { } TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); CookieOptions options; EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_google_foo_.url(), @@ -1396,7 +1691,7 @@ TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) { } TEST_F(CookieMonsterTest, CookieSorting) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B1; path=/")); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "B=B2; path=/foo")); @@ -1426,7 +1721,7 @@ TEST_F(CookieMonsterTest, CookieSorting) { } TEST_F(CookieMonsterTest, DeleteCookieByName) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A1; path=/")); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=A2; path=/foo")); @@ -1502,7 +1797,7 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) { // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, initial_cookies); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); // Verify that duplicates were not imported for path "/". // (If this had failed, GetCookies() would have also returned X=1, X=2, X=4). @@ -1558,7 +1853,7 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCreationTimes) { // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, initial_cookies); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); CookieList list(GetAllCookies(cm.get())); EXPECT_EQ(2U, list.size()); @@ -1574,7 +1869,8 @@ TEST_F(CookieMonsterTest, CookieMonsterDelegate) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); scoped_refptr<MockCookieMonsterDelegate> delegate( new MockCookieMonsterDelegate); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), delegate.get())); + std::unique_ptr<CookieMonster> cm( + new CookieMonster(store.get(), delegate.get())); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B")); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "C=D")); @@ -1652,81 +1948,29 @@ TEST_F(CookieMonsterTest, CookieMonsterDelegate) { delegate->reset(); } -TEST_F(CookieMonsterTest, DeleteAllForHost) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); - - // Test probes: - // * Non-secure URL, mid-level (http://w.c.b.a) - // * Secure URL, mid-level (https://w.c.b.a) - // * URL with path, mid-level (https:/w.c.b.a/dir1/xx) - // All three tests should nuke only the midlevel host cookie, - // the http_only cookie, the host secure cookie, and the two host - // path cookies. http_only, secure, and paths are ignored by - // this call, and domain cookies arent touched. - PopulateCmForDeleteAllForHost(cm.get()); - EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus3))); - EXPECT_EQ("dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure))); - EXPECT_EQ("dom_1=X; host_1=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus1))); - EXPECT_EQ( - "dom_path_2=X; host_path_2=X; dom_path_1=X; host_path_1=X; " - "dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure + - std::string("/dir1/dir2/xxx")))); - - EXPECT_EQ(6, DeleteAllCreatedBetweenForHost(cm.get(), base::Time(), - base::Time::Now(), - GURL(kTopLevelDomainPlus2))); - EXPECT_EQ(8U, GetAllCookies(cm.get()).size()); - - EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus3))); - EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure))); - EXPECT_EQ("dom_1=X; host_1=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus1))); - EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure + - std::string("/dir1/dir2/xxx")))); - - PopulateCmForDeleteAllForHost(cm.get()); - EXPECT_EQ(6, DeleteAllCreatedBetweenForHost( - cm.get(), base::Time(), base::Time::Now(), - GURL(kTopLevelDomainPlus2Secure))); - EXPECT_EQ(8U, GetAllCookies(cm.get()).size()); +TEST_F(CookieMonsterTest, PredicateSeesAllCookies) { + const std::string kTrueValue = "A"; + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + // We test that we can see all cookies with our predicated. This includes + // host, http_only, host secure, and all domain cookies. + CookiePredicate value_matcher = base::Bind(&CookieValuePredicate, kTrueValue); - EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus3))); - EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure))); - EXPECT_EQ("dom_1=X; host_1=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus1))); - EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure + - std::string("/dir1/dir2/xxx")))); + PopulateCmForPredicateCheck(cm.get()); + EXPECT_EQ(7, DeleteAllCreatedBetweenWithPredicate( + cm.get(), base::Time(), base::Time::Now(), value_matcher)); - PopulateCmForDeleteAllForHost(cm.get()); - EXPECT_EQ(6, - DeleteAllCreatedBetweenForHost( - cm.get(), base::Time(), base::Time::Now(), - GURL(kTopLevelDomainPlus2Secure + std::string("/dir1/xxx")))); - EXPECT_EQ(8U, GetAllCookies(cm.get()).size()); - - EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X", + EXPECT_EQ("dom_2=B; dom_3=C; host_3=C", GetCookies(cm.get(), GURL(kTopLevelDomainPlus3))); - EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X", + EXPECT_EQ("dom_2=B; host_2=B; sec_host=B", GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure))); - EXPECT_EQ("dom_1=X; host_1=X", - GetCookies(cm.get(), GURL(kTopLevelDomainPlus1))); - EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X", + EXPECT_EQ("", GetCookies(cm.get(), GURL(kTopLevelDomainPlus1))); + EXPECT_EQ("dom_path_2=B; host_path_2=B; dom_2=B; host_2=B; sec_host=B", GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure + std::string("/dir1/dir2/xxx")))); } TEST_F(CookieMonsterTest, UniqueCreationTime) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); CookieOptions options; // Add in three cookies through every public interface to the @@ -1789,7 +2033,7 @@ TEST_F(CookieMonsterTest, UniqueCreationTime) { // Mainly a test of GetEffectiveDomain, or more specifically, of the // expected behavior of GetEffectiveDomain within the CookieMonster. TEST_F(CookieMonsterTest, GetKey) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); // This test is really only interesting if GetKey() actually does something. EXPECT_EQ("google.com", cm->GetKey("www.google.com")); @@ -1833,7 +2077,8 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) { // Create new cookies and flush them to the store. { - scoped_ptr<CookieMonster> cmout(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cmout( + new CookieMonster(store.get(), nullptr)); for (const CookiesInputInfo* p = input_info; p < &input_info[arraysize(input_info)]; p++) { EXPECT_TRUE(SetCookieWithDetails( @@ -1849,7 +2094,8 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) { // Create a new cookie monster and make sure that everything is correct { - scoped_ptr<CookieMonster> cmin(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cmin( + new CookieMonster(store.get(), nullptr)); CookieList cookies(GetAllCookies(cmin.get())); ASSERT_EQ(2u, cookies.size()); // Ordering is path length, then creation time. So second cookie @@ -1879,7 +2125,7 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) { TEST_F(CookieMonsterTest, CookieListOrdering) { // Put a random set of cookies into a monster and make sure // they're returned in the right order. - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); EXPECT_TRUE( SetCookie(cm.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1")); EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.google.com/aa/bb/cc/x.html"), @@ -1936,7 +2182,7 @@ TEST_F(CookieMonsterTest, MAYBE_GarbageCollectionTriggers) { // First we check to make sure that a whole lot of recent cookies // doesn't get rid of anything after garbage collection is checked for. { - scoped_ptr<CookieMonster> cm( + std::unique_ptr<CookieMonster> cm( CreateMonsterForGC(CookieMonster::kMaxCookies * 2)); EXPECT_EQ(CookieMonster::kMaxCookies * 2, GetAllCookies(cm.get()).size()); SetCookie(cm.get(), GURL("http://newdomain.com"), "b=2"); @@ -1978,7 +2224,7 @@ TEST_F(CookieMonsterTest, MAYBE_GarbageCollectionTriggers) { for (int ci = 0; ci < static_cast<int>(arraysize(test_cases)); ++ci) { const TestCase* test_case = &test_cases[ci]; - scoped_ptr<CookieMonster> cm = CreateMonsterFromStoreForGC( + std::unique_ptr<CookieMonster> cm = CreateMonsterFromStoreForGC( test_case->num_cookies, test_case->num_old_cookies, 0, 0, CookieMonster::kSafeFromGlobalPurgeDays * 2); EXPECT_EQ(test_case->expected_initial_cookies, @@ -1999,7 +2245,7 @@ TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); store->set_store_load_commands(true); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); // Get all cookies task that queues a task to set a cookie when executed. ResultSavingCookieCallback<bool> set_cookie_callback; @@ -2051,7 +2297,7 @@ TEST_F(CookieMonsterTest, WhileLoadingDeleteAllGetForURL) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); store->set_store_load_commands(true); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); ResultSavingCookieCallback<int> delete_callback; cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run, @@ -2092,7 +2338,7 @@ TEST_F(CookieMonsterTest, WhileLoadingGetAllSetGetAll) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); store->set_store_load_commands(true); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); GetCookieListCallback get_cookie_list_callback1; cm->GetAllCookiesAsync( @@ -2144,7 +2390,7 @@ TEST_F(CookieMonsterTest, CheckOrderOfCookieTaskQueueWhenLoadingCompletes) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); store->set_store_load_commands(true); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); // Get all cookies task that queues a task to set a cookie when executed. ResultSavingCookieCallback<bool> set_cookie_callback; @@ -2246,7 +2492,7 @@ class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> { TEST_F(CookieMonsterTest, FlushStore) { scoped_refptr<CallbackCounter> counter(new CallbackCounter()); scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); ASSERT_EQ(0, store->flush_count()); ASSERT_EQ(0, counter->callback_count()); @@ -2296,7 +2542,7 @@ TEST_F(CookieMonsterTest, FlushStore) { TEST_F(CookieMonsterTest, SetAllCookies) { scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); cm->SetPersistSessionCookies(true); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "U=V; path=/")); @@ -2342,56 +2588,59 @@ TEST_F(CookieMonsterTest, SetAllCookies) { } TEST_F(CookieMonsterTest, ComputeCookieDiff) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); base::Time now = base::Time::Now(); base::Time creation_time = now - base::TimeDelta::FromSeconds(1); - scoped_ptr<CanonicalCookie> cookie1(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie1(CanonicalCookie::Create( http_www_google_.url(), "A", "B", http_www_google_.url().host(), "/", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie2(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie2(CanonicalCookie::Create( http_www_google_.url(), "C", "D", http_www_google_.url().host(), "/", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie3(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie3(CanonicalCookie::Create( http_www_google_.url(), "E", "F", http_www_google_.url().host(), "/", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie4(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie4(CanonicalCookie::Create( http_www_google_.url(), "G", "H", http_www_google_.url().host(), "/", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie4_with_new_value(CanonicalCookie::Create( - http_www_google_.url(), "G", "iamnew", http_www_google_.url().host(), "/", - creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, - false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie5(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie4_with_new_value( + CanonicalCookie::Create( + http_www_google_.url(), "G", "iamnew", http_www_google_.url().host(), + "/", creation_time, base::Time(), false, false, + CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); + std::unique_ptr<CanonicalCookie> cookie5(CanonicalCookie::Create( http_www_google_.url(), "I", "J", http_www_google_.url().host(), "/", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie5_with_new_creation_time( + std::unique_ptr<CanonicalCookie> cookie5_with_new_creation_time( CanonicalCookie::Create( http_www_google_.url(), "I", "J", http_www_google_.url().host(), "/", now, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie6(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie6(CanonicalCookie::Create( http_www_google_.url(), "K", "L", http_www_google_.url().host(), "/foo", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie6_with_new_path(CanonicalCookie::Create( - http_www_google_.url(), "K", "L", http_www_google_.url().host(), "/bar", - creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, - false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie7(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie6_with_new_path( + CanonicalCookie::Create( + http_www_google_.url(), "K", "L", http_www_google_.url().host(), + "/bar", creation_time, base::Time(), false, false, + CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); + std::unique_ptr<CanonicalCookie> cookie7(CanonicalCookie::Create( http_www_google_.url(), "M", "N", http_www_google_.url().host(), "/foo", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<CanonicalCookie> cookie7_with_new_path(CanonicalCookie::Create( - http_www_google_.url(), "M", "N", http_www_google_.url().host(), "/bar", - creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, - false, COOKIE_PRIORITY_DEFAULT)); + std::unique_ptr<CanonicalCookie> cookie7_with_new_path( + CanonicalCookie::Create( + http_www_google_.url(), "M", "N", http_www_google_.url().host(), + "/bar", creation_time, base::Time(), false, false, + CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT)); CookieList old_cookies; old_cookies.push_back(*cookie1); @@ -2461,7 +2710,7 @@ TEST_F(CookieMonsterTest, ComputeCookieDiff) { // works). TEST_F(CookieMonsterTest, DeleteAll) { scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); cm->SetPersistSessionCookies(true); EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "X=Y; path=/")); @@ -2472,7 +2721,7 @@ TEST_F(CookieMonsterTest, DeleteAll) { } TEST_F(CookieMonsterTest, HistogramCheck) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); // Should match call in InitializeHistograms, but doesn't really matter // since the histogram should have been initialized by the CM construction // above. @@ -2480,21 +2729,21 @@ TEST_F(CookieMonsterTest, HistogramCheck) { "Cookie.ExpirationDurationMinutes", 1, 10 * 365 * 24 * 60, 50, base::Histogram::kUmaTargetedHistogramFlag); - scoped_ptr<base::HistogramSamples> samples1( + std::unique_ptr<base::HistogramSamples> samples1( expired_histogram->SnapshotSamples()); ASSERT_TRUE(SetCookieWithDetails( cm.get(), GURL("http://fake.a.url"), "a", "b", "a.url", "/", base::Time(), base::Time::Now() + base::TimeDelta::FromMinutes(59), base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); - scoped_ptr<base::HistogramSamples> samples2( + std::unique_ptr<base::HistogramSamples> samples2( expired_histogram->SnapshotSamples()); EXPECT_EQ(samples1->TotalCount() + 1, samples2->TotalCount()); // kValidCookieLine creates a session cookie. ASSERT_TRUE(SetCookie(cm.get(), http_www_google_.url(), kValidCookieLine)); - scoped_ptr<base::HistogramSamples> samples3( + std::unique_ptr<base::HistogramSamples> samples3( expired_histogram->SnapshotSamples()); EXPECT_EQ(samples2->TotalCount(), samples3->TotalCount()); } @@ -2502,7 +2751,7 @@ TEST_F(CookieMonsterTest, HistogramCheck) { TEST_F(CookieMonsterTest, InvalidExpiryTime) { std::string cookie_line = std::string(kValidCookieLine) + "; expires=Blarg arg arg"; - scoped_ptr<CanonicalCookie> cookie(CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::Create( http_www_google_.url(), cookie_line, Time::Now(), CookieOptions())); ASSERT_FALSE(cookie->IsPersistent()); } @@ -2511,7 +2760,7 @@ TEST_F(CookieMonsterTest, InvalidExpiryTime) { // CookieStore if the "persist session cookies" option is on. TEST_F(CookieMonsterTest, PersistSessionCookies) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); cm->SetPersistSessionCookies(true); // All cookies set with SetCookie are session cookies. @@ -2547,7 +2796,7 @@ TEST_F(CookieMonsterTest, PersistSessionCookies) { // Test the commands sent to the persistent cookie store. TEST_F(CookieMonsterTest, PersisentCookieStorageTest) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); // Add a cookie. EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), @@ -2603,7 +2852,7 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { // We have to manually build this cookie because it contains a control // character, and our cookie line parser rejects control characters. - scoped_ptr<CanonicalCookie> cc = CanonicalCookie::Create( + std::unique_ptr<CanonicalCookie> cc = CanonicalCookie::Create( url, "baz", "\x05" "boo", @@ -2616,7 +2865,7 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, initial_cookies); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); EXPECT_EQ("foo=bar; hello=world", GetCookies(cm.get(), url)); } @@ -2627,7 +2876,7 @@ TEST_F(CookieMonsterTest, CookieSourceHistogram) { const std::string cookie_source_histogram = "Cookie.CookieSourceScheme"; scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); histograms.ExpectTotalCount(cookie_source_histogram, 0); @@ -2694,7 +2943,7 @@ TEST_F(CookieMonsterTest, CookieDeleteEquivalentHistogramTest) { const std::string cookie_source_histogram = "Cookie.CookieDeleteEquivalent"; scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); // Set a secure cookie from a secure origin EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), "A=B; Secure")); @@ -2759,7 +3008,7 @@ TEST_F(CookieMonsterTest, CookieDeleteEquivalentHistogramTest) { } TEST_F(CookieMonsterStrictSecureTest, SetSecureCookies) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); GURL http_url("http://www.google.com"); GURL http_superdomain_url("http://google.com"); GURL https_url("https://www.google.com"); @@ -2836,13 +3085,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), 180U, 0U, nullptr); + TestSecureCookieEviction(test1, arraysize(test1), 150U, 0U, nullptr); // If non-secure cookies for one domain hit the per domain limit (180), the - // creation of secure cookies will evict all of the non-secure cookies, and - // the secure cookies will still be created. + // creation of secure cookies will evict the non-secure cookies first, making + // room for the secure cookies. const CookiesEntry test2[] = {{180U, false}, {20U, true}}; - TestSecureCookieEviction(test2, arraysize(test2), 20U, 0U, nullptr); + TestSecureCookieEviction(test2, arraysize(test2), 20U, 149U, 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 @@ -2854,9 +3103,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 18 to 168). + // the remaining secure cookies will be created (another 19 to 169). const CookiesEntry test4[] = {{1U, false}, {199U, true}}; - TestSecureCookieEviction(test4, arraysize(test4), 168U, 0U, nullptr); + TestSecureCookieEviction(test4, arraysize(test4), 169U, 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. @@ -2865,38 +3114,40 @@ 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 of the - // non-secure cookies will be evicted but none of the secure ones will be - // evicted. + // 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. const CookiesEntry test6[] = {{50U, true}, {50U, false}, {81U, true}}; - TestSecureCookieEviction(test6, arraysize(test6), 131U, 0U, nullptr); + TestSecureCookieEviction(test6, arraysize(test6), 131U, 19U, 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 of - // the non-secure cookies will be evicted but none of the secure ones will be - // evicted. + // 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. const CookiesEntry test7[] = {{50U, false}, {50U, true}, {81U, false}}; - TestSecureCookieEviction(test7, arraysize(test7), 50U, 0U, nullptr); + TestSecureCookieEviction(test7, arraysize(test7), 50U, 100U, 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 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). + // 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). const CookiesEntry test8[] = {{50U, false}, {50U, true}, {90U, false}}; - TestSecureCookieEviction(test8, arraysize(test8), 50U, 9U, nullptr); + TestSecureCookieEviction(test8, arraysize(test8), 50U, 109U, 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 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. + // 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. const CookiesEntry test9[] = {{180U, false}, {20U, true}}; const AltHosts test9_alt_hosts(0, 20); - TestSecureCookieEviction(test9, arraysize(test9), 20U, 20U, &test9_alt_hosts); + TestSecureCookieEviction(test9, arraysize(test9), 20U, 169U, + &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 @@ -2952,7 +3203,7 @@ TEST_F(CookieMonsterStrictSecureTest, EvictSecureCookies) { // Tests that strict secure cookies doesn't trip equivalent cookie checks // accidentally. Regression test for https://crbug.com/569943. TEST_F(CookieMonsterStrictSecureTest, EquivalentCookies) { - scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr)); GURL http_url("http://www.google.com"); GURL http_superdomain_url("http://google.com"); GURL https_url("https://www.google.com"); @@ -2977,7 +3228,7 @@ TEST_F(CookieMonsterStrictSecureTest, CookieDeleteEquivalentHistogramTest) { const std::string cookie_source_histogram = "Cookie.CookieDeleteEquivalent"; scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); + std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); // Set a secure cookie from a secure origin EXPECT_TRUE(SetCookie(cm.get(), https_www_google_.url(), "A=B; Secure")); @@ -3063,7 +3314,7 @@ class CookieMonsterNotificationTest : public CookieMonsterTest { private: scoped_refptr<MockPersistentCookieStore> store_; - scoped_ptr<CookieMonster> monster_; + std::unique_ptr<CookieMonster> monster_; }; void RecordCookieChanges(std::vector<CanonicalCookie>* out_cookies, @@ -3078,7 +3329,7 @@ void RecordCookieChanges(std::vector<CanonicalCookie>* out_cookies, TEST_F(CookieMonsterNotificationTest, NoNotifyWithNoCookie) { std::vector<CanonicalCookie> cookies; - scoped_ptr<CookieStore::CookieChangedSubscription> sub( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( test_url_, "abc", base::Bind(&RecordCookieChanges, &cookies, nullptr))); @@ -3090,7 +3341,7 @@ TEST_F(CookieMonsterNotificationTest, NoNotifyWithInitialCookie) { std::vector<CanonicalCookie> cookies; SetCookie(monster(), test_url_, "abc=def"); base::MessageLoop::current()->RunUntilIdle(); - scoped_ptr<CookieStore::CookieChangedSubscription> sub( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( test_url_, "abc", base::Bind(&RecordCookieChanges, &cookies, nullptr))); @@ -3101,7 +3352,7 @@ TEST_F(CookieMonsterNotificationTest, NoNotifyWithInitialCookie) { TEST_F(CookieMonsterNotificationTest, NotifyOnSet) { std::vector<CanonicalCookie> cookies; std::vector<bool> removes; - scoped_ptr<CookieStore::CookieChangedSubscription> sub( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( test_url_, "abc", base::Bind(&RecordCookieChanges, &cookies, &removes))); @@ -3118,7 +3369,7 @@ TEST_F(CookieMonsterNotificationTest, NotifyOnSet) { TEST_F(CookieMonsterNotificationTest, NotifyOnDelete) { std::vector<CanonicalCookie> cookies; std::vector<bool> removes; - scoped_ptr<CookieStore::CookieChangedSubscription> sub( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( test_url_, "abc", base::Bind(&RecordCookieChanges, &cookies, &removes))); @@ -3140,7 +3391,7 @@ TEST_F(CookieMonsterNotificationTest, NotifyOnDelete) { TEST_F(CookieMonsterNotificationTest, NotifyOnUpdate) { std::vector<CanonicalCookie> cookies; std::vector<bool> removes; - scoped_ptr<CookieStore::CookieChangedSubscription> sub( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( test_url_, "abc", base::Bind(&RecordCookieChanges, &cookies, &removes))); @@ -3168,11 +3419,11 @@ TEST_F(CookieMonsterNotificationTest, NotifyOnUpdate) { TEST_F(CookieMonsterNotificationTest, MultipleNotifies) { std::vector<CanonicalCookie> cookies0; std::vector<CanonicalCookie> cookies1; - scoped_ptr<CookieStore::CookieChangedSubscription> sub0( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub0( monster()->AddCallbackForCookie( test_url_, "abc", base::Bind(&RecordCookieChanges, &cookies0, nullptr))); - scoped_ptr<CookieStore::CookieChangedSubscription> sub1( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub1( monster()->AddCallbackForCookie( test_url_, "def", base::Bind(&RecordCookieChanges, &cookies1, nullptr))); @@ -3189,11 +3440,11 @@ TEST_F(CookieMonsterNotificationTest, MultipleNotifies) { TEST_F(CookieMonsterNotificationTest, MultipleSameNotifies) { std::vector<CanonicalCookie> cookies0; std::vector<CanonicalCookie> cookies1; - scoped_ptr<CookieStore::CookieChangedSubscription> sub0( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub0( monster()->AddCallbackForCookie( test_url_, "abc", base::Bind(&RecordCookieChanges, &cookies0, nullptr))); - scoped_ptr<CookieStore::CookieChangedSubscription> sub1( + std::unique_ptr<CookieStore::CookieChangedSubscription> sub1( monster()->AddCallbackForCookie( test_url_, "abc", base::Bind(&RecordCookieChanges, &cookies1, nullptr))); diff --git a/chromium/net/cookies/cookie_store.cc b/chromium/net/cookies/cookie_store.cc index f1dff9ada43..cb9acc8b41d 100644 --- a/chromium/net/cookies/cookie_store.cc +++ b/chromium/net/cookies/cookie_store.cc @@ -4,6 +4,8 @@ #include "net/cookies/cookie_store.h" +#include "base/bind.h" +#include "base/callback.h" #include "net/cookies/cookie_options.h" namespace net { diff --git a/chromium/net/cookies/cookie_store.h b/chromium/net/cookies/cookie_store.h index f6426c5d695..aaf1b743e46 100644 --- a/chromium/net/cookies/cookie_store.h +++ b/chromium/net/cookies/cookie_store.h @@ -7,12 +7,12 @@ #ifndef NET_COOKIES_COOKIE_STORE_H_ #define NET_COOKIES_COOKIE_STORE_H_ +#include <memory> #include <string> #include <vector> -#include "base/callback.h" +#include "base/callback_forward.h" #include "base/callback_list.h" -#include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "net/base/net_export.h" #include "net/cookies/canonical_cookie.h" @@ -43,6 +43,7 @@ class NET_EXPORT CookieStore { typedef base::CallbackList<void(const CanonicalCookie& cookie, bool removed)> CookieChangedCallbackList; typedef CookieChangedCallbackList::Subscription CookieChangedSubscription; + typedef base::Callback<bool(const CanonicalCookie& cookie)> CookiePredicate; virtual ~CookieStore(); @@ -150,21 +151,21 @@ class NET_EXPORT CookieStore { // Deletes all of the cookies that have a creation_date greater than or equal // to |delete_begin| and less than |delete_end| - // Returns the number of cookies that have been deleted. + // Calls |callback| with the number of cookies deleted. virtual void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin, const base::Time& delete_end, const DeleteCallback& callback) = 0; - // Deletes all of the cookies that match the host of the given URL - // regardless of path and that have a creation_date greater than or - // equal to |delete_begin| and less then |delete_end|. This includes - // all http_only and secure cookies, but does not include any domain - // cookies that may apply to this host. - // Returns the number of cookies deleted. - virtual void DeleteAllCreatedBetweenForHostAsync( - const base::Time delete_begin, - const base::Time delete_end, - const GURL& url, + // Deletes all of the cookies that match the given predicate and that have a + // creation_date greater than or equal to |delete_begin| and less then + // |delete_end|. This includes all http_only and secure cookies. Avoid + // deleting cookies that could leave websites with a partial set of visible + // cookies. + // Calls |callback| with the number of cookies deleted. + virtual void DeleteAllCreatedBetweenWithPredicateAsync( + const base::Time& delete_begin, + const base::Time& delete_end, + const CookiePredicate& predicate, const DeleteCallback& callback) = 0; virtual void DeleteSessionCookiesAsync(const DeleteCallback&) = 0; @@ -197,7 +198,7 @@ class NET_EXPORT CookieStore { // (url, name) pair are removed. If this method ever needs to support an // unbounded amount of such pairs, this contract needs to change and // implementors need to be improved to not behave this way. - virtual scoped_ptr<CookieChangedSubscription> AddCallbackForCookie( + virtual std::unique_ptr<CookieChangedSubscription> AddCallbackForCookie( const GURL& url, const std::string& name, const CookieChangedCallback& callback) = 0; diff --git a/chromium/net/cookies/cookie_store_test_helpers.cc b/chromium/net/cookies/cookie_store_test_helpers.cc index d2dc2106192..5ae3629ae19 100644 --- a/chromium/net/cookies/cookie_store_test_helpers.cc +++ b/chromium/net/cookies/cookie_store_test_helpers.cc @@ -8,7 +8,7 @@ #include "base/location.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_util.h" -#include "base/thread_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" using net::registry_controlled_domains::GetDomainAndRegistry; @@ -189,10 +189,10 @@ void DelayedCookieMonster::DeleteAllCreatedBetweenAsync( ADD_FAILURE(); } -void DelayedCookieMonster::DeleteAllCreatedBetweenForHostAsync( - const base::Time delete_begin, - const base::Time delete_end, - const GURL& url, +void DelayedCookieMonster::DeleteAllCreatedBetweenWithPredicateAsync( + const base::Time& delete_begin, + const base::Time& delete_end, + const base::Callback<bool(const CanonicalCookie&)>& predicate, const DeleteCallback& callback) { ADD_FAILURE(); } @@ -205,13 +205,13 @@ void DelayedCookieMonster::FlushStore(const base::Closure& callback) { ADD_FAILURE(); } -scoped_ptr<CookieStore::CookieChangedSubscription> +std::unique_ptr<CookieStore::CookieChangedSubscription> DelayedCookieMonster::AddCallbackForCookie( const GURL& url, const std::string& name, const CookieChangedCallback& callback) { ADD_FAILURE(); - return scoped_ptr<CookieStore::CookieChangedSubscription>(); + return std::unique_ptr<CookieStore::CookieChangedSubscription>(); } bool DelayedCookieMonster::IsEphemeral() { diff --git a/chromium/net/cookies/cookie_store_test_helpers.h b/chromium/net/cookies/cookie_store_test_helpers.h index 0ebae5bb9e2..687261ec7bc 100644 --- a/chromium/net/cookies/cookie_store_test_helpers.h +++ b/chromium/net/cookies/cookie_store_test_helpers.h @@ -79,19 +79,20 @@ class DelayedCookieMonster : public CookieStore { const base::Time& delete_end, const DeleteCallback& callback) override; - void DeleteAllCreatedBetweenForHostAsync( - const base::Time delete_begin, - const base::Time delete_end, - const GURL& url, + void DeleteAllCreatedBetweenWithPredicateAsync( + const base::Time& delete_begin, + const base::Time& delete_end, + const base::Callback<bool(const CanonicalCookie&)>& predicate, const DeleteCallback& callback) override; void DeleteSessionCookiesAsync(const DeleteCallback&) override; void FlushStore(const base::Closure& callback) override; - scoped_ptr<CookieStore::CookieChangedSubscription> - AddCallbackForCookie(const GURL& url, const std::string& name, - const CookieChangedCallback& callback) override; + std::unique_ptr<CookieStore::CookieChangedSubscription> AddCallbackForCookie( + const GURL& url, + const std::string& name, + const CookieChangedCallback& callback) override; bool IsEphemeral() override; @@ -116,7 +117,7 @@ class DelayedCookieMonster : public CookieStore { friend class base::RefCountedThreadSafe<DelayedCookieMonster>; - scoped_ptr<CookieMonster> cookie_monster_; + std::unique_ptr<CookieMonster> cookie_monster_; bool did_run_; bool result_; diff --git a/chromium/net/cookies/cookie_store_unittest.cc b/chromium/net/cookies/cookie_store_unittest.cc index 739336594a7..a0c77f403af 100644 --- a/chromium/net/cookies/cookie_store_unittest.cc +++ b/chromium/net/cookies/cookie_store_unittest.cc @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "net/cookies/cookie_store.h" + +#include <memory> #include <vector> #include "base/time/time.h" -#include "net/cookies/cookie_store.h" -#include "base/memory/scoped_ptr.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_options.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,7 +20,7 @@ namespace { // Helper for testing BuildCookieLine void MatchCookieLineToVector( const std::string& line, - const std::vector<scoped_ptr<CanonicalCookie>>& cookies) { + const std::vector<std::unique_ptr<CanonicalCookie>>& cookies) { // Test the std::vector<CanonicalCookie> variant // ('CookieMonster::CookieList'): std::vector<CanonicalCookie> list; @@ -38,7 +39,7 @@ void MatchCookieLineToVector( } // namespace TEST(CookieStoreBaseTest, BuildCookieLine) { - std::vector<scoped_ptr<CanonicalCookie>> cookies; + std::vector<std::unique_ptr<CanonicalCookie>> cookies; GURL url("https://example.com/"); CookieOptions options; base::Time now = base::Time::Now(); diff --git a/chromium/net/cookies/cookie_store_unittest.h b/chromium/net/cookies/cookie_store_unittest.h index 2b42c897896..3f8b037cef8 100644 --- a/chromium/net/cookies/cookie_store_unittest.h +++ b/chromium/net/cookies/cookie_store_unittest.h @@ -14,8 +14,8 @@ #include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/string_tokenizer.h" -#include "base/thread_task_runner_handle.h" #include "base/threading/thread.h" +#include "base/threading/thread_task_runner_handle.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_store_test_callbacks.h" @@ -42,7 +42,7 @@ const char kValidCookieLine[] = "A=B; path=/"; // The CookieStoreTestTraits must have the following members: // struct CookieStoreTestTraits { // // Factory function. Will be called at most once per test. -// static scoped_ptr<CookieStore> Create(); +// static std::unique_ptr<CookieStore> Create(); // // // The cookie store supports cookies with the exclude_httponly() option. // static const bool supports_http_only; @@ -242,17 +242,17 @@ class CookieStoreTest : public testing::Test { return callback.result(); } - int DeleteAllCreatedBetweenForHost(CookieStore* cs, - const base::Time delete_begin, - const base::Time delete_end, - const GURL& url) { + int DeleteAllCreatedBetweenWithPredicate( + CookieStore* cs, + const base::Time delete_begin, + const base::Time delete_end, + const CookieStore::CookiePredicate& predicate) { DCHECK(cs); ResultSavingCookieCallback<int> callback; - cs->DeleteAllCreatedBetweenForHostAsync( - delete_begin, delete_end, url, - base::Bind( - &ResultSavingCookieCallback<int>::Run, - base::Unretained(&callback))); + cs->DeleteAllCreatedBetweenWithPredicateAsync( + delete_begin, delete_end, predicate, + base::Bind(&ResultSavingCookieCallback<int>::Run, + base::Unretained(&callback))); callback.WaitUntilDone(); return callback.result(); } @@ -319,8 +319,8 @@ class CookieStoreTest : public testing::Test { const CookieURLHelper http_foo_com_; const CookieURLHelper http_bar_com_; - scoped_ptr<base::WeakPtrFactory<base::MessageLoop> > weak_factory_; - scoped_ptr<base::MessageLoop> message_loop_; + std::unique_ptr<base::WeakPtrFactory<base::MessageLoop>> weak_factory_; + std::unique_ptr<base::MessageLoop> message_loop_; private: // Returns a set of strings of type "name=value". Fails in case of duplicate. @@ -332,7 +332,7 @@ class CookieStoreTest : public testing::Test { return tokens; } - scoped_ptr<CookieStore> cookie_store_; + std::unique_ptr<CookieStore> cookie_store_; }; TYPED_TEST_CASE_P(CookieStoreTest); @@ -1044,23 +1044,53 @@ TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) { this->GetCookies(cs, this->http_www_google_.url())); } -TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetweenForHost) { +namespace { +static bool CookieHasValue(const std::string& value, + const CanonicalCookie& cookie) { + return cookie.Value() == value; +} +} + +TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetweenWithPredicate) { CookieStore* cs = this->GetCookieStore(); - GURL url_not_google("http://www.notgoogle.com"); base::Time now = base::Time::Now(); + base::Time last_month = base::Time::Now() - base::TimeDelta::FromDays(30); + base::Time last_minute = base::Time::Now() - base::TimeDelta::FromMinutes(1); + std::string desired_value("B"); // These 3 cookies match the time range and host. EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B")); EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "C=D")); EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "Y=Z")); - - // This cookie does not match host. - EXPECT_TRUE(this->SetCookie(cs, url_not_google, "E=F")); + EXPECT_TRUE(this->SetCookie(cs, this->https_www_google_.url(), "E=B")); // Delete cookies. - EXPECT_EQ(3, // Deletes A=B, C=D, Y=Z - this->DeleteAllCreatedBetweenForHost(cs, now, base::Time::Max(), - this->http_www_google_.url())); + EXPECT_EQ(2, // Deletes A=B, E=B + this->DeleteAllCreatedBetweenWithPredicate( + cs, now, base::Time::Max(), + base::Bind(&CookieHasValue, desired_value))); + + // Check that we deleted the right ones. + this->MatchCookieLines("C=D;Y=Z", + this->GetCookies(cs, this->https_www_google_.url())); + + // Now check that using a null predicate will do nothing. + EXPECT_EQ(0, this->DeleteAllCreatedBetweenWithPredicate( + cs, now, base::Time::Max(), CookieStore::CookiePredicate())); + + // Finally, check that we don't delete cookies when our time range is off. + desired_value = "D"; + EXPECT_EQ(0, this->DeleteAllCreatedBetweenWithPredicate( + cs, last_month, last_minute, + base::Bind(&CookieHasValue, desired_value))); + this->MatchCookieLines("C=D;Y=Z", + this->GetCookies(cs, this->https_www_google_.url())); + // Same thing, but with a good time range. + EXPECT_EQ(1, this->DeleteAllCreatedBetweenWithPredicate( + cs, now, base::Time::Max(), + base::Bind(&CookieHasValue, desired_value))); + this->MatchCookieLines("Y=Z", + this->GetCookies(cs, this->https_www_google_.url())); } TYPED_TEST_P(CookieStoreTest, TestSecure) { @@ -1370,7 +1400,7 @@ REGISTER_TYPED_TEST_CASE_P(CookieStoreTest, TestCookieDeletion, TestDeleteAll, TestDeleteAllCreatedBetween, - TestDeleteAllCreatedBetweenForHost, + TestDeleteAllCreatedBetweenWithPredicate, TestSecure, NetUtilCookieTest, OverwritePersistentCookie, |