summaryrefslogtreecommitdiff
path: root/chromium/net/cookies
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-09 14:22:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-05-09 15:11:45 +0000
commit2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch)
treee75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/net/cookies
parenta4f3d46271c57e8155ba912df46a05559d14726e (diff)
downloadqtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion. Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/net/cookies')
-rw-r--r--chromium/net/cookies/canonical_cookie.cc139
-rw-r--r--chromium/net/cookies/canonical_cookie.h44
-rw-r--r--chromium/net/cookies/canonical_cookie_unittest.cc388
-rw-r--r--chromium/net/cookies/cookie_constants.cc17
-rw-r--r--chromium/net/cookies/cookie_constants.h16
-rw-r--r--chromium/net/cookies/cookie_monster.cc1181
-rw-r--r--chromium/net/cookies/cookie_monster.h288
-rw-r--r--chromium/net/cookies/cookie_monster_perftest.cc21
-rw-r--r--chromium/net/cookies/cookie_monster_store_test.cc68
-rw-r--r--chromium/net/cookies/cookie_monster_store_test.h62
-rw-r--r--chromium/net/cookies/cookie_monster_unittest.cc1586
-rw-r--r--chromium/net/cookies/cookie_options.cc3
-rw-r--r--chromium/net/cookies/cookie_options.h30
-rw-r--r--chromium/net/cookies/cookie_store.cc64
-rw-r--r--chromium/net/cookies/cookie_store.h119
-rw-r--r--chromium/net/cookies/cookie_store_test_callbacks.cc33
-rw-r--r--chromium/net/cookies/cookie_store_test_callbacks.h30
-rw-r--r--chromium/net/cookies/cookie_store_test_helpers.cc71
-rw-r--r--chromium/net/cookies/cookie_store_test_helpers.h40
-rw-r--r--chromium/net/cookies/cookie_store_unittest.cc65
-rw-r--r--chromium/net/cookies/cookie_store_unittest.h1445
-rw-r--r--chromium/net/cookies/cookie_util.cc2
-rw-r--r--chromium/net/cookies/parse_cookie_line_fuzzer.cc15
-rw-r--r--chromium/net/cookies/parsed_cookie.cc39
-rw-r--r--chromium/net/cookies/parsed_cookie.h10
-rw-r--r--chromium/net/cookies/parsed_cookie_unittest.cc74
26 files changed, 2907 insertions, 2943 deletions
diff --git a/chromium/net/cookies/canonical_cookie.cc b/chromium/net/cookies/canonical_cookie.cc
index 15287e0b8b5..bce2b5477fa 100644
--- a/chromium/net/cookies/canonical_cookie.cc
+++ b/chromium/net/cookies/canonical_cookie.cc
@@ -47,6 +47,7 @@
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/parsed_cookie.h"
@@ -133,7 +134,7 @@ CanonicalCookie::CanonicalCookie(const GURL& url,
const base::Time& last_access,
bool secure,
bool httponly,
- bool firstpartyonly,
+ CookieSameSite same_site,
CookiePriority priority)
: source_(url.SchemeIsFile() ? url : url.GetOrigin()),
name_(name),
@@ -145,36 +146,10 @@ CanonicalCookie::CanonicalCookie(const GURL& url,
last_access_date_(last_access),
secure_(secure),
httponly_(httponly),
- first_party_only_(firstpartyonly),
+ same_site_(same_site),
priority_(priority) {}
-CanonicalCookie::CanonicalCookie(const GURL& url, const ParsedCookie& pc)
- : source_(url.SchemeIsFile() ? url : url.GetOrigin()),
- name_(pc.Name()),
- value_(pc.Value()),
- path_(CanonPath(url, pc)),
- creation_date_(Time::Now()),
- last_access_date_(Time()),
- secure_(pc.IsSecure()),
- httponly_(pc.IsHttpOnly()),
- first_party_only_(pc.IsFirstPartyOnly()),
- priority_(pc.Priority()) {
- if (pc.HasExpires())
- expiry_date_ = CanonExpiration(pc, creation_date_, creation_date_);
-
- // Do the best we can with the domain.
- std::string cookie_domain;
- std::string domain_string;
- if (pc.HasDomain()) {
- domain_string = pc.Domain();
- }
- bool result
- = cookie_util::GetCookieDomainWithString(url, domain_string,
- &cookie_domain);
- // Caller is responsible for passing in good arguments.
- DCHECK(result);
- domain_ = cookie_domain;
-}
+CanonicalCookie::CanonicalCookie(const CanonicalCookie& other) = default;
CanonicalCookie::~CanonicalCookie() {
}
@@ -217,26 +192,27 @@ Time CanonicalCookie::CanonExpiration(const ParsedCookie& pc,
}
// static
-CanonicalCookie* CanonicalCookie::Create(const GURL& url,
- const std::string& cookie_line,
- const base::Time& creation_time,
- const CookieOptions& options) {
+scoped_ptr<CanonicalCookie> CanonicalCookie::Create(
+ const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time,
+ const CookieOptions& options) {
ParsedCookie parsed_cookie(cookie_line);
if (!parsed_cookie.IsValid()) {
VLOG(kVlogSetCookies) << "WARNING: Couldn't parse cookie";
- return NULL;
+ return nullptr;
}
if (options.exclude_httponly() && parsed_cookie.IsHttpOnly()) {
VLOG(kVlogSetCookies) << "Create() is not creating a httponly cookie";
- return NULL;
+ return nullptr;
}
std::string cookie_domain;
if (!GetCookieDomain(url, parsed_cookie, &cookie_domain)) {
VLOG(kVlogSetCookies) << "Create() failed to get a cookie domain";
- return NULL;
+ return nullptr;
}
// Per 3.2.1 of "Deprecate modification of 'secure' cookies from non-secure
@@ -247,7 +223,7 @@ CanonicalCookie* CanonicalCookie::Create(const GURL& url,
!url.SchemeIsCryptographic()) {
VLOG(kVlogSetCookies)
<< "Create() is trying to create a secure cookie from an insecure URL";
- return NULL;
+ return nullptr;
}
std::string cookie_path = CanonicalCookie::CanonPath(url, parsed_cookie);
@@ -269,54 +245,56 @@ CanonicalCookie* CanonicalCookie::Create(const GURL& url,
return nullptr;
}
- return new CanonicalCookie(
+ return make_scoped_ptr(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(),
- parsed_cookie.IsFirstPartyOnly(), parsed_cookie.Priority());
+ parsed_cookie.SameSite(), parsed_cookie.Priority()));
}
-CanonicalCookie* 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,
- bool first_party_only,
- bool enforce_strict_secure,
- CookiePriority priority) {
+// static
+scoped_ptr<CanonicalCookie> 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) {
// Expect valid attribute tokens and values, as defined by the ParsedCookie
// logic, otherwise don't create the cookie.
std::string parsed_name = ParsedCookie::ParseTokenString(name);
if (parsed_name != name)
- return NULL;
+ return nullptr;
std::string parsed_value = ParsedCookie::ParseValueString(value);
if (parsed_value != value)
- return NULL;
+ return nullptr;
std::string parsed_domain = ParsedCookie::ParseValueString(domain);
if (parsed_domain != domain)
- return NULL;
+ return nullptr;
std::string cookie_domain;
if (!cookie_util::GetCookieDomainWithString(url, parsed_domain,
&cookie_domain)) {
- return NULL;
+ return nullptr;
}
if (enforce_strict_secure && secure && !url.SchemeIsCryptographic())
- return NULL;
+ return nullptr;
std::string parsed_path = ParsedCookie::ParseValueString(path);
if (parsed_path != path)
- return NULL;
+ return nullptr;
std::string cookie_path = CanonPathWithString(url, parsed_path);
// Expect that the path was either not specified (empty), or is valid.
if (!parsed_path.empty() && cookie_path != parsed_path)
- return NULL;
+ return nullptr;
// Canonicalize path again to make sure it escapes characters as needed.
url::Component path_component(0, cookie_path.length());
url::RawCanonOutputT<char> canon_path;
@@ -326,9 +304,9 @@ CanonicalCookie* CanonicalCookie::Create(const GURL& url,
cookie_path = std::string(canon_path.data() + canon_path_component.begin,
canon_path_component.len);
- return new CanonicalCookie(url, parsed_name, parsed_value, cookie_domain,
- cookie_path, creation, expiration, creation,
- secure, http_only, first_party_only, priority);
+ return make_scoped_ptr(new CanonicalCookie(
+ url, parsed_name, parsed_value, cookie_domain, cookie_path, creation,
+ expiration, creation, secure, http_only, same_site, priority));
}
bool CanonicalCookie::IsOnPath(const std::string& url_path) const {
@@ -344,25 +322,24 @@ bool CanonicalCookie::IsOnPath(const std::string& url_path) const {
// was longer, the same length, or shorter than the length of the url path.
// I think the approach below is simpler.
- // Make sure the cookie path is a prefix of the url path. If the
- // url path is shorter than the cookie path, then the cookie path
- // can't be a prefix.
- if (url_path.find(path_) != 0)
+ // Make sure the cookie path is a prefix of the url path. If the url path is
+ // shorter than the cookie path, then the cookie path can't be a prefix.
+ if (!base::StartsWith(url_path, path_, base::CompareCase::SENSITIVE))
return false;
- // Now we know that url_path is >= cookie_path, and that cookie_path
- // is a prefix of url_path. If they are the are the same length then
- // they are identical, otherwise we need an additional check:
+ // |url_path| is >= |path_|, and |path_| is a prefix of |url_path|. If they
+ // are the are the same length then they are identical, otherwise need an
+ // additional check:
// In order to avoid in correctly matching a cookie path of /blah
// with a request path of '/blahblah/', we need to make sure that either
// the cookie path ends in a trailing '/', or that we prefix up to a '/'
// in the url path. Since we know that the url path length is greater
// than the cookie path length, it's safe to index one byte past.
- if (path_.length() != url_path.length() &&
- path_[path_.length() - 1] != '/' &&
- url_path[path_.length()] != '/')
+ if (path_.length() != url_path.length() && path_.back() != '/' &&
+ url_path[path_.length()] != '/') {
return false;
+ }
return true;
}
@@ -416,9 +393,23 @@ bool CanonicalCookie::IncludeForRequestURL(const GURL& url,
// match the cookie-path.
if (!IsOnPath(url.path()))
return false;
- // Don't include first-party-only cookies for non-first-party requests.
- if (IsFirstPartyOnly() && !options.include_first_party_only_cookies())
- return false;
+ // Don't include same-site cookies for cross-site requests.
+ switch (SameSite()) {
+ case CookieSameSite::STRICT_MODE:
+ if (options.same_site_cookie_mode() !=
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX) {
+ return false;
+ }
+ break;
+ case CookieSameSite::LAX_MODE:
+ if (options.same_site_cookie_mode() ==
+ CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE) {
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
return true;
}
diff --git a/chromium/net/cookies/canonical_cookie.h b/chromium/net/cookies/canonical_cookie.h
index 9c3a1c9c04b..f95501c7627 100644
--- a/chromium/net/cookies/canonical_cookie.h
+++ b/chromium/net/cookies/canonical_cookie.h
@@ -9,6 +9,7 @@
#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"
@@ -37,13 +38,10 @@ class NET_EXPORT CanonicalCookie {
const base::Time& last_access,
bool secure,
bool httponly,
- bool firstpartyonly,
+ CookieSameSite same_site,
CookiePriority priority);
- // This constructor does canonicalization but not validation.
- // The result of this constructor should not be relied on in contexts
- // in which pre-validation of the ParsedCookie has not been done.
- CanonicalCookie(const GURL& url, const ParsedCookie& pc);
+ CanonicalCookie(const CanonicalCookie& other);
~CanonicalCookie();
@@ -52,26 +50,26 @@ 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 CanonicalCookie* Create(const GURL& url,
- const std::string& cookie_line,
- const base::Time& creation_time,
- const CookieOptions& options);
+ static scoped_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 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,
- bool first_party_only,
- bool enforce_strict_secure,
- CookiePriority priority);
+ 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);
const GURL& Source() const { return source_; }
const std::string& Name() const { return name_; }
@@ -84,7 +82,7 @@ class NET_EXPORT CanonicalCookie {
const base::Time& ExpiryDate() const { return expiry_date_; }
bool IsSecure() const { return secure_; }
bool IsHttpOnly() const { return httponly_; }
- bool IsFirstPartyOnly() const { return first_party_only_; }
+ CookieSameSite SameSite() const { return same_site_; }
CookiePriority Priority() const { return priority_; }
bool IsDomainCookie() const {
return !domain_.empty() && domain_[0] == '.'; }
@@ -203,7 +201,7 @@ class NET_EXPORT CanonicalCookie {
base::Time last_access_date_;
bool secure_;
bool httponly_;
- bool first_party_only_;
+ CookieSameSite same_site_;
CookiePriority priority_;
};
diff --git a/chromium/net/cookies/canonical_cookie_unittest.cc b/chromium/net/cookies/canonical_cookie_unittest.cc
index 2a01d9742a2..80b772e9b2f 100644
--- a/chromium/net/cookies/canonical_cookie_unittest.cc
+++ b/chromium/net/cookies/canonical_cookie_unittest.cc
@@ -19,7 +19,7 @@ TEST(CanonicalCookieTest, Constructor) {
CanonicalCookie cookie(url, "A", "2", "www.example.com", "/test",
current_time, base::Time(), current_time, false, false,
- false, COOKIE_PRIORITY_DEFAULT);
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT);
EXPECT_EQ(url.GetOrigin(), cookie.Source());
EXPECT_EQ("A", cookie.Name());
EXPECT_EQ("2", cookie.Value());
@@ -27,11 +27,12 @@ TEST(CanonicalCookieTest, Constructor) {
EXPECT_EQ("/test", cookie.Path());
EXPECT_FALSE(cookie.IsSecure());
EXPECT_FALSE(cookie.IsHttpOnly());
- EXPECT_FALSE(cookie.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie.SameSite());
CanonicalCookie cookie2(url, "A", "2", std::string(), std::string(),
current_time, base::Time(), current_time, false,
- false, false, COOKIE_PRIORITY_DEFAULT);
+ false, CookieSameSite::DEFAULT_MODE,
+ COOKIE_PRIORITY_DEFAULT);
EXPECT_EQ(url.GetOrigin(), cookie.Source());
EXPECT_EQ("A", cookie2.Name());
EXPECT_EQ("2", cookie2.Value());
@@ -39,7 +40,7 @@ TEST(CanonicalCookieTest, Constructor) {
EXPECT_EQ("", cookie2.Path());
EXPECT_FALSE(cookie2.IsSecure());
EXPECT_FALSE(cookie2.IsHttpOnly());
- EXPECT_FALSE(cookie2.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2.SameSite());
}
TEST(CanonicalCookieTest, Create) {
@@ -58,7 +59,7 @@ TEST(CanonicalCookieTest, Create) {
EXPECT_FALSE(cookie->IsSecure());
GURL url2("http://www.foo.com");
- cookie.reset(CanonicalCookie::Create(url2, "B=1", creation_time, options));
+ cookie = CanonicalCookie::Create(url2, "B=1", creation_time, options);
EXPECT_EQ(url2.GetOrigin(), cookie->Source());
EXPECT_EQ("B", cookie->Name());
EXPECT_EQ("1", cookie->Value());
@@ -68,34 +69,37 @@ TEST(CanonicalCookieTest, Create) {
// Test creating secure cookies. RFC 6265 allows insecure urls to set secure
// cookies.
- cookie.reset(
- CanonicalCookie::Create(url, "A=2; Secure", creation_time, options));
+ cookie = CanonicalCookie::Create(url, "A=2; Secure", creation_time, options);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsSecure());
// Test creating http only cookies.
- cookie.reset(
- CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options));
+ cookie =
+ CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options);
EXPECT_FALSE(cookie.get());
CookieOptions httponly_options;
httponly_options.set_include_httponly();
- cookie.reset(CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time,
- httponly_options));
+ cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time,
+ httponly_options);
EXPECT_TRUE(cookie->IsHttpOnly());
- // Test creating http only cookies.
- CookieOptions first_party_options;
- first_party_options.set_include_first_party_only_cookies();
- cookie.reset(CanonicalCookie::Create(url, "A=2; First-Party-Only",
- creation_time, httponly_options));
+ // Test creating SameSite cookies.
+ CookieOptions same_site_options;
+ same_site_options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
+ same_site_options);
EXPECT_TRUE(cookie.get());
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time,
+ same_site_options);
// Test the creating cookies using specific parameter instead of a cookie
// string.
- cookie.reset(CanonicalCookie::Create(
- url, "A", "2", "www.example.com", "/test", creation_time, base::Time(),
- false, false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cookie = CanonicalCookie::Create(url, "A", "2", "www.example.com", "/test",
+ creation_time, base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false,
+ COOKIE_PRIORITY_DEFAULT);
EXPECT_EQ(url.GetOrigin(), cookie->Source());
EXPECT_EQ("A", cookie->Name());
EXPECT_EQ("2", cookie->Value());
@@ -103,11 +107,12 @@ TEST(CanonicalCookieTest, Create) {
EXPECT_EQ("/test", cookie->Path());
EXPECT_FALSE(cookie->IsSecure());
EXPECT_FALSE(cookie->IsHttpOnly());
- EXPECT_FALSE(cookie->IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
- cookie.reset(CanonicalCookie::Create(
- url, "A", "2", ".www.example.com", "/test", creation_time, base::Time(),
- false, false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cookie = CanonicalCookie::Create(url, "A", "2", ".www.example.com", "/test",
+ creation_time, base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false,
+ COOKIE_PRIORITY_DEFAULT);
EXPECT_EQ(url.GetOrigin(), cookie->Source());
EXPECT_EQ("A", cookie->Name());
EXPECT_EQ("2", cookie->Value());
@@ -115,7 +120,24 @@ TEST(CanonicalCookieTest, Create) {
EXPECT_EQ("/test", cookie->Path());
EXPECT_FALSE(cookie->IsSecure());
EXPECT_FALSE(cookie->IsHttpOnly());
- EXPECT_FALSE(cookie->IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
+}
+
+TEST(CanonicalCookieTest, CreateInvalidSameSite) {
+ GURL url("http://www.example.com/test/foo.html");
+ base::Time now = base::Time::Now();
+ scoped_ptr<CanonicalCookie> cookie;
+ CookieOptions options;
+
+ // Invalid 'SameSite' attribute values.
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Invalid", now, options);
+ EXPECT_EQ(nullptr, cookie.get());
+
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite", now, options);
+ EXPECT_EQ(nullptr, cookie.get());
}
TEST(CanonicalCookieTest, EmptyExpiry) {
@@ -134,8 +156,7 @@ TEST(CanonicalCookieTest, EmptyExpiry) {
// With a stale server time
options.set_server_time(creation_time - base::TimeDelta::FromHours(1));
- cookie.reset(
- CanonicalCookie::Create(url, cookie_line, creation_time, options));
+ cookie = CanonicalCookie::Create(url, cookie_line, creation_time, options);
EXPECT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -143,8 +164,7 @@ TEST(CanonicalCookieTest, EmptyExpiry) {
// With a future server time
options.set_server_time(creation_time + base::TimeDelta::FromHours(1));
- cookie.reset(
- CanonicalCookie::Create(url, cookie_line, creation_time, options));
+ cookie = CanonicalCookie::Create(url, cookie_line, creation_time, options);
EXPECT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -162,19 +182,19 @@ TEST(CanonicalCookieTest, IsEquivalent) {
base::Time expiration_time = creation_time + base::TimeDelta::FromDays(2);
bool secure(false);
bool httponly(false);
- bool firstparty(false);
+ CookieSameSite same_site(CookieSameSite::NO_RESTRICTION);
// Test that a cookie is equivalent to itself.
scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ 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(
url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
@@ -183,47 +203,47 @@ TEST(CanonicalCookieTest, IsEquivalent) {
other_cookie.reset(
new CanonicalCookie(url, cookie_name, "2", cookie_domain, cookie_path,
creation_time, expiration_time, last_access_time,
- secure, httponly, firstparty, COOKIE_PRIORITY_HIGH));
+ secure, httponly, same_site, COOKIE_PRIORITY_HIGH));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
base::Time other_creation_time =
creation_time + base::TimeDelta::FromMinutes(2);
other_cookie.reset(new CanonicalCookie(
url, cookie_name, "2", cookie_domain, cookie_path, other_creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, true, httponly, firstparty,
+ expiration_time, last_access_time, true, httponly, same_site,
COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, true, firstparty,
+ expiration_time, last_access_time, secure, true, same_site,
COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, true,
- COOKIE_PRIORITY_LOW));
+ expiration_time, last_access_time, secure, httponly,
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalent(*other_cookie));
// Tests that use different variations of attribute values that
// DO affect cookie equivalence.
- other_cookie.reset(new CanonicalCookie(
- url, "B", cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
- COOKIE_PRIORITY_MEDIUM));
+ other_cookie.reset(
+ new CanonicalCookie(url, "B", cookie_value, cookie_domain, cookie_path,
+ creation_time, expiration_time, last_access_time,
+ secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, "www.example.com", cookie_path,
creation_time, expiration_time, last_access_time, secure, httponly,
- firstparty, COOKIE_PRIORITY_MEDIUM));
+ same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsDomainCookie());
EXPECT_FALSE(other_cookie->IsDomainCookie());
EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
@@ -231,12 +251,12 @@ TEST(CanonicalCookieTest, IsEquivalent) {
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, ".example.com", cookie_path,
creation_time, expiration_time, last_access_time, secure, httponly,
- firstparty, COOKIE_PRIORITY_MEDIUM));
+ same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, "/test/0", creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_FALSE(cookie->IsEquivalent(*other_cookie));
}
@@ -252,19 +272,19 @@ TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) {
base::Time expiration_time = creation_time + base::TimeDelta::FromDays(2);
bool secure(false);
bool httponly(false);
- bool firstparty(false);
+ CookieSameSite same_site(CookieSameSite::NO_RESTRICTION);
// Test that a cookie is equivalent to itself.
scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ 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(
url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
@@ -277,47 +297,47 @@ TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) {
other_cookie.reset(
new CanonicalCookie(url, cookie_name, "2", cookie_domain, cookie_path,
creation_time, expiration_time, last_access_time,
- secure, httponly, firstparty, COOKIE_PRIORITY_HIGH));
+ secure, httponly, same_site, COOKIE_PRIORITY_HIGH));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
base::Time other_creation_time =
creation_time + base::TimeDelta::FromMinutes(2);
other_cookie.reset(new CanonicalCookie(
url, cookie_name, "2", cookie_domain, cookie_path, other_creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, true, httponly, firstparty,
+ expiration_time, last_access_time, true, httponly, same_site,
COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, true, firstparty,
+ expiration_time, last_access_time, secure, true, same_site,
COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, true,
- COOKIE_PRIORITY_LOW));
+ expiration_time, last_access_time, secure, httponly,
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_LOW));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
// The following 3 tests' expected results differ from their IsEquivalent
// counterparts above.
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, cookie_domain, "/test/0", creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
+ expiration_time, last_access_time, secure, httponly, same_site,
COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, "www.example.com", cookie_path,
creation_time, expiration_time, last_access_time, secure, httponly,
- firstparty, COOKIE_PRIORITY_MEDIUM));
+ same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsDomainCookie());
EXPECT_FALSE(other_cookie->IsDomainCookie());
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
@@ -325,17 +345,17 @@ TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) {
other_cookie.reset(new CanonicalCookie(
url, cookie_name, cookie_value, ".example.com", cookie_path,
creation_time, expiration_time, last_access_time, secure, httponly,
- firstparty, COOKIE_PRIORITY_MEDIUM));
+ same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
// Tests that use different variations of attribute values that
// DO affect cookie equivalence. Note that unlike the IsEquivalent tests
// above, this does *not* include tests for differing paths or domains that
// "domain-match".
- other_cookie.reset(new CanonicalCookie(
- url, "B", cookie_value, cookie_domain, cookie_path, creation_time,
- expiration_time, last_access_time, secure, httponly, firstparty,
- COOKIE_PRIORITY_MEDIUM));
+ other_cookie.reset(
+ new CanonicalCookie(url, "B", cookie_value, cookie_domain, cookie_path,
+ creation_time, expiration_time, last_access_time,
+ secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM));
EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie));
}
@@ -353,8 +373,8 @@ TEST(CanonicalCookieTest, IsDomainMatch) {
EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com"));
EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
- cookie.reset(CanonicalCookie::Create(url, "A=2; Domain=www.example.com",
- creation_time, options));
+ cookie = CanonicalCookie::Create(url, "A=2; Domain=www.example.com",
+ creation_time, options);
EXPECT_TRUE(cookie->IsDomainCookie());
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
@@ -362,8 +382,8 @@ TEST(CanonicalCookieTest, IsDomainMatch) {
EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com"));
EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
- cookie.reset(CanonicalCookie::Create(url, "A=2; Domain=.www.example.com",
- creation_time, options));
+ cookie = CanonicalCookie::Create(url, "A=2; Domain=.www.example.com",
+ creation_time, options);
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("foo.www.example.com"));
@@ -384,9 +404,8 @@ TEST(CanonicalCookieTest, IsOnPath) {
// Test the empty string edge case.
EXPECT_FALSE(cookie->IsOnPath(std::string()));
- cookie.reset(
- CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
- "A=2", creation_time, options));
+ cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
+ "A=2", creation_time, options);
EXPECT_FALSE(cookie->IsOnPath("/"));
EXPECT_TRUE(cookie->IsOnPath("/test"));
EXPECT_TRUE(cookie->IsOnPath("/test/bar.html"));
@@ -412,16 +431,16 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// Test that cookie with a cookie path that does not match the url path are
// not included.
- cookie.reset(CanonicalCookie::Create(url, "A=2; Path=/foo/bar", creation_time,
- options));
+ cookie = CanonicalCookie::Create(url, "A=2; Path=/foo/bar", creation_time,
+ options);
EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
EXPECT_TRUE(cookie->IncludeForRequestURL(
GURL("http://www.example.com/foo/bar/index.html"), options));
// Test that a secure cookie is not included for a non secure URL.
GURL secure_url("https://www.example.com");
- cookie.reset(CanonicalCookie::Create(secure_url, "A=2; Secure", creation_time,
- options));
+ cookie = CanonicalCookie::Create(secure_url, "A=2; Secure", creation_time,
+ options);
EXPECT_TRUE(cookie->IsSecure());
EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url, options));
EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
@@ -429,54 +448,49 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// Test that http only cookies are only included if the include httponly flag
// is set on the cookie options.
options.set_include_httponly();
- cookie.reset(
- CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options));
+ cookie =
+ CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options);
EXPECT_TRUE(cookie->IsHttpOnly());
EXPECT_TRUE(cookie->IncludeForRequestURL(url, options));
options.set_exclude_httponly();
EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
}
-TEST(CanonicalCookieTest, IncludeFirstPartyForFirstPartyURL) {
- GURL insecure_url("http://example.test");
- GURL secure_url("https://example.test");
- GURL secure_url_with_path("https://example.test/foo/bar/index.html");
- GURL third_party_url("https://not-example.test");
+TEST(CanonicalCookieTest, IncludeSameSiteForSameSiteURL) {
+ GURL url("https://example.test");
base::Time creation_time = base::Time::Now();
CookieOptions options;
scoped_ptr<CanonicalCookie> cookie;
- // First-party-only cookies are not included for non-first-party requests,
- // even if other properties match:
- cookie.reset(CanonicalCookie::Create(secure_url, "A=2; First-Party-Only",
- creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_FALSE(cookie->IncludeForRequestURL(secure_url, options));
- cookie.reset(CanonicalCookie::Create(
- secure_url, "A=2; Secure; First-Party-Only", creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_FALSE(cookie->IncludeForRequestURL(secure_url, options));
- cookie.reset(CanonicalCookie::Create(secure_url_with_path,
- "A=2; First-Party-Only; path=/foo/bar",
- creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_FALSE(cookie->IncludeForRequestURL(secure_url, options));
+ // `SameSite=Strict` cookies are included for a URL only if the options'
+ // SameSiteCookieMode is INCLUDE_STRICT_AND_LAX.
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
+ options);
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE);
+ EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_LAX);
+ EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ EXPECT_TRUE(cookie->IncludeForRequestURL(url, options));
- // First-party-only cookies are included for first-party requests:
- options.set_include_first_party_only_cookies();
- cookie.reset(CanonicalCookie::Create(secure_url, "A=2; First-Party-Only",
- creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url, options));
- cookie.reset(CanonicalCookie::Create(
- secure_url, "A=2; Secure; First-Party-Only", creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url, options));
- cookie.reset(CanonicalCookie::Create(secure_url_with_path,
- "A=2; First-Party-Only; path=/foo/bar",
- creation_time, options));
- EXPECT_TRUE(cookie->IsFirstPartyOnly());
- EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url_with_path, options));
+ // `SameSite=Lax` cookies are included for a URL only if the options'
+ // SameSiteCookieMode is INCLUDE_STRICT_AND_LAX.
+ cookie =
+ CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time, options);
+ EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE);
+ EXPECT_FALSE(cookie->IncludeForRequestURL(url, options));
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_LAX);
+ EXPECT_TRUE(cookie->IncludeForRequestURL(url, options));
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ EXPECT_TRUE(cookie->IncludeForRequestURL(url, options));
}
TEST(CanonicalCookieTest, PartialCompare) {
@@ -549,28 +563,24 @@ TEST(CanonicalCookieTest, SecureCookiePrefix) {
CookieOptions options;
// A __Secure- cookie must be Secure.
- EXPECT_EQ(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Secure-A=B", creation_time, options)));
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Secure-A=B; httponly", creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B", creation_time,
+ options));
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B; httponly",
+ creation_time, options));
// A typoed prefix does not have to be Secure.
- EXPECT_NE(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__secure-A=B; Secure", creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__secure-A=C;", creation_time, options)));
- EXPECT_NE(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__SecureA=B; Secure", creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__SecureA=C;", creation_time, options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=B; Secure",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=C;", creation_time,
+ options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Secure",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=C;", creation_time,
+ options));
// A __Secure- cookie can't be set on a non-secure origin.
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- http_url, "__Secure-A=B; Secure", creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(http_url, "__Secure-A=B; Secure",
+ creation_time, options));
}
TEST(CanonicalCookieTest, HostCookiePrefix) {
@@ -581,54 +591,44 @@ TEST(CanonicalCookieTest, HostCookiePrefix) {
std::string domain = https_url.host();
// A __Host- cookie must be Secure.
- EXPECT_EQ(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B;", creation_time, options)));
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Domain=" + domain + "; Path=/;",
- creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Path=/; Secure;",
- creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
+ options));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Domain=" + domain + "; Path=/;", creation_time,
+ options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
+ creation_time, options));
// A __Host- cookie must be set from a secure scheme.
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
- creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Path=/; Secure;",
- creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
+ creation_time, options));
// A __Host- cookie can't have a Domain.
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
- creation_time, options)));
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Domain=" + domain + "; Secure;",
- creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
+ creation_time, options));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Domain=" + domain + "; Secure;", creation_time,
+ options));
// A __Host- cookie must have a Path of "/".
- EXPECT_EQ(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Path=/foo; Secure;",
- creation_time, options)));
- EXPECT_EQ(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Secure;", creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Secure; Path=/;",
- creation_time, options)));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Path=/foo; Secure;", creation_time, options));
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure;",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure; Path=/;",
+ creation_time, options));
// Rules don't apply for a typoed prefix.
- EXPECT_NE(nullptr,
- make_scoped_ptr(CanonicalCookie::Create(
- http_url, "__host-A=B; Domain=" + domain + "; Path=/; Secure;",
- creation_time, options)));
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__HostA=B; Domain=" + domain + "; Secure;",
- creation_time, options)));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ http_url, "__host-A=B; Domain=" + domain + "; Path=/; Secure;",
+ creation_time, options));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__HostA=B; Domain=" + domain + "; Secure;", creation_time,
+ options));
}
TEST(CanonicalCookieTest, EnforceSecureCookiesRequireSecureScheme) {
@@ -653,21 +653,21 @@ TEST(CanonicalCookieTest, EnforceSecureCookiesRequireSecureScheme) {
EXPECT_TRUE(https_cookie_secure.get());
scoped_ptr<CanonicalCookie> http_cookie_no_secure_extended(
- CanonicalCookie::Create(http_url, "a", "b", "", "", creation_time,
- creation_time, false, false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ 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(
- CanonicalCookie::Create(http_url, "a", "b", "", "", creation_time,
- creation_time, true, false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ 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(
- CanonicalCookie::Create(https_url, "a", "b", "", "", creation_time,
- creation_time, false, false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ 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(
- CanonicalCookie::Create(https_url, "a", "b", "", "", creation_time,
- creation_time, true, false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ CanonicalCookie::Create(
+ https_url, "a", "b", "", "", creation_time, creation_time, true,
+ false, CookieSameSite::STRICT_MODE, true, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(http_cookie_no_secure_extended.get());
EXPECT_FALSE(http_cookie_secure_extended.get());
@@ -683,48 +683,42 @@ TEST(CanonicalCookieTest, TestPrefixHistograms) {
base::Time creation_time = base::Time::Now();
CookieOptions options;
- scoped_ptr<CanonicalCookie> cookie1 = make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B;", creation_time, options));
- EXPECT_EQ(nullptr, cookie1);
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
+ options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Host-A=B; Path=/; Secure", creation_time,
- options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__HostA=B; Path=/; Secure", creation_time,
- options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__HostA=B; Path=/; Secure",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- scoped_ptr<CanonicalCookie> cookie2 = make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Secure-A=B;", creation_time, options));
- EXPECT_EQ(nullptr, cookie2);
+ EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B;",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__Secure-A=B; Path=/; Secure",
- creation_time, options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Secure-A=B; Path=/; Secure",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
- EXPECT_NE(nullptr, make_scoped_ptr(CanonicalCookie::Create(
- https_url, "__SecureA=B; Path=/; Secure",
- creation_time, options)));
+ EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Path=/; Secure",
+ creation_time, options));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
diff --git a/chromium/net/cookies/cookie_constants.cc b/chromium/net/cookies/cookie_constants.cc
index 05fe22ea437..b618261f8b2 100644
--- a/chromium/net/cookies/cookie_constants.cc
+++ b/chromium/net/cookies/cookie_constants.cc
@@ -10,12 +10,17 @@
namespace net {
namespace {
+
const char kPriorityLow[] = "low";
const char kPriorityMedium[] = "medium";
const char kPriorityHigh[] = "high";
+
+const char kSameSiteLax[] = "lax";
+const char kSameSiteStrict[] = "strict";
+
} // namespace
-NET_EXPORT const std::string CookiePriorityToString(CookiePriority priority) {
+std::string CookiePriorityToString(CookiePriority priority) {
switch(priority) {
case COOKIE_PRIORITY_HIGH:
return kPriorityHigh;
@@ -29,7 +34,7 @@ NET_EXPORT const std::string CookiePriorityToString(CookiePriority priority) {
return std::string();
}
-NET_EXPORT CookiePriority StringToCookiePriority(const std::string& priority) {
+CookiePriority StringToCookiePriority(const std::string& priority) {
std::string priority_comp = base::ToLowerASCII(priority);
if (priority_comp == kPriorityHigh)
@@ -42,4 +47,12 @@ NET_EXPORT CookiePriority StringToCookiePriority(const std::string& priority) {
return COOKIE_PRIORITY_DEFAULT;
}
+CookieSameSite StringToCookieSameSite(const std::string& same_site) {
+ if (base::EqualsCaseInsensitiveASCII(same_site, kSameSiteLax))
+ return CookieSameSite::LAX_MODE;
+ if (base::EqualsCaseInsensitiveASCII(same_site, kSameSiteStrict))
+ return CookieSameSite::STRICT_MODE;
+ return CookieSameSite::DEFAULT_MODE;
+}
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_constants.h b/chromium/net/cookies/cookie_constants.h
index 7e27e14657d..49dafbdb3a1 100644
--- a/chromium/net/cookies/cookie_constants.h
+++ b/chromium/net/cookies/cookie_constants.h
@@ -18,13 +18,27 @@ enum CookiePriority {
COOKIE_PRIORITY_DEFAULT = COOKIE_PRIORITY_MEDIUM
};
+enum class CookieSameSite {
+ NO_RESTRICTION = 0,
+ LAX_MODE = 1,
+ STRICT_MODE = 2,
+ DEFAULT_MODE = NO_RESTRICTION
+};
+
// Returns the Set-Cookie header priority token corresponding to |priority|.
-NET_EXPORT const std::string CookiePriorityToString(CookiePriority priority);
+//
+// TODO(mkwst): Remove this once its callsites are refactored.
+NET_EXPORT std::string CookiePriorityToString(CookiePriority priority);
// Converts the Set-Cookie header priority token |priority| to a CookiePriority.
// Defaults to COOKIE_PRIORITY_DEFAULT for empty or unrecognized strings.
NET_EXPORT CookiePriority StringToCookiePriority(const std::string& priority);
+// Converst the Set-Cookie header SameSite token |same_site| to a
+// CookieSameSite. Defaults to CookieSameSite::DEFAULT_MODE for empty or
+// unrecognized strings.
+NET_EXPORT CookieSameSite StringToCookieSameSite(const std::string& same_site);
+
} // namespace net
#endif // NET_COOKIES_COOKIE_CONSTANTS_H_
diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc
index 15e4f7ee8e1..aaecaf9a265 100644
--- a/chromium/net/cookies/cookie_monster.cc
+++ b/chromium/net/cookies/cookie_monster.cc
@@ -162,13 +162,10 @@ bool CookieSorter(CanonicalCookie* cc1, CanonicalCookie* cc2) {
bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1,
const CookieMonster::CookieMap::iterator& it2) {
- // Cookies accessed less recently should be deleted first.
if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
return it1->second->LastAccessDate() < it2->second->LastAccessDate();
- // In rare cases we might have two cookies with identical last access times.
- // To preserve the stability of the sort, in these cases prefer to delete
- // older cookies over newer ones. CreationDate() is guaranteed to be unique.
+ // Ensure stability for == last access times by falling back to creation.
return it1->second->CreationDate() < it2->second->CreationDate();
}
@@ -250,30 +247,6 @@ void SplitCookieVectorIntoSecureAndNonSecure(
}
}
-// Predicate to support PartitionCookieByPriority().
-struct CookiePriorityEqualsTo
- : std::unary_function<const CookieMonster::CookieMap::iterator, bool> {
- explicit CookiePriorityEqualsTo(CookiePriority priority)
- : priority_(priority) {}
-
- bool operator()(const CookieMonster::CookieMap::iterator it) const {
- return it->second->Priority() == priority_;
- }
-
- const CookiePriority priority_;
-};
-
-// For a CookieItVector iterator range [|it_begin|, |it_end|),
-// moves all cookies with a given |priority| to the beginning of the list.
-// Returns: An iterator in [it_begin, it_end) to the first element with
-// priority != |priority|, or |it_end| if all have priority == |priority|.
-CookieMonster::CookieItVector::iterator PartitionCookieByPriority(
- CookieMonster::CookieItVector::iterator it_begin,
- CookieMonster::CookieItVector::iterator it_end,
- CookiePriority priority) {
- return std::partition(it_begin, it_end, CookiePriorityEqualsTo(priority));
-}
-
bool LowerBoundAccessDateComparator(const CookieMonster::CookieMap::iterator it,
const Time& access_date) {
return it->second->LastAccessDate() < access_date;
@@ -328,22 +301,6 @@ ChangeCausePair ChangeCauseMapping[] = {
// DELETE_COOKIE_LAST_ENTRY
{CookieMonsterDelegate::CHANGE_COOKIE_EXPLICIT, false}};
-std::string BuildCookieLine(const CanonicalCookieVector& cookies) {
- std::string cookie_line;
- for (CanonicalCookieVector::const_iterator it = cookies.begin();
- it != cookies.end(); ++it) {
- if (it != cookies.begin())
- cookie_line += "; ";
- // In Mozilla if you set a cookie like AAAA, it will have an empty token
- // and a value of AAAA. When it sends the cookie back, it will send AAAA,
- // so we need to avoid sending =AAAA for a blank token value.
- if (!(*it)->Name().empty())
- cookie_line += (*it)->Name() + "=";
- cookie_line += (*it)->Value();
- }
- return cookie_line;
-}
-
void RunAsync(scoped_refptr<base::TaskRunner> proxy,
const CookieStore::CookieChangedCallback& callback,
const CanonicalCookie& cookie,
@@ -355,19 +312,7 @@ void RunAsync(scoped_refptr<base::TaskRunner> proxy,
CookieMonster::CookieMonster(PersistentCookieStore* store,
CookieMonsterDelegate* delegate)
- : initialized_(false),
- started_fetching_all_cookies_(false),
- finished_fetching_all_cookies_(false),
- fetch_strategy_(kUnknownFetch),
- store_(store),
- last_access_threshold_(
- TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)),
- delegate_(delegate),
- last_statistic_record_time_(Time::Now()),
- keep_expired_cookies_(false),
- persist_session_cookies_(false) {
- InitializeHistograms();
- SetDefaultCookieableSchemes();
+ : CookieMonster(store, delegate, kDefaultAccessUpdateThresholdSeconds) {
}
CookieMonster::CookieMonster(PersistentCookieStore* store,
@@ -377,15 +322,18 @@ CookieMonster::CookieMonster(PersistentCookieStore* store,
started_fetching_all_cookies_(false),
finished_fetching_all_cookies_(false),
fetch_strategy_(kUnknownFetch),
+ seen_global_task_(false),
store_(store),
last_access_threshold_(base::TimeDelta::FromMilliseconds(
last_access_threshold_milliseconds)),
delegate_(delegate),
last_statistic_record_time_(base::Time::Now()),
- keep_expired_cookies_(false),
- persist_session_cookies_(false) {
+ persist_session_cookies_(false),
+ weak_ptr_factory_(this) {
InitializeHistograms();
- SetDefaultCookieableSchemes();
+ cookieable_schemes_.insert(
+ cookieable_schemes_.begin(), kDefaultCookieableSchemes,
+ kDefaultCookieableSchemes + kDefaultCookieableSchemesCount);
}
// Task classes for queueing the coming request.
@@ -401,51 +349,23 @@ class CookieMonster::CookieMonsterTask
explicit CookieMonsterTask(CookieMonster* cookie_monster);
virtual ~CookieMonsterTask();
- // Invokes the callback immediately, if the current thread is the one
- // that originated the task, or queues the callback for execution on the
- // appropriate thread. Maintains a reference to this CookieMonsterTask
- // instance until the callback completes.
- void InvokeCallback(base::Closure callback);
-
CookieMonster* cookie_monster() { return cookie_monster_; }
private:
friend class base::RefCountedThreadSafe<CookieMonsterTask>;
CookieMonster* cookie_monster_;
- scoped_refptr<base::SingleThreadTaskRunner> thread_;
DISALLOW_COPY_AND_ASSIGN(CookieMonsterTask);
};
CookieMonster::CookieMonsterTask::CookieMonsterTask(
CookieMonster* cookie_monster)
- : cookie_monster_(cookie_monster),
- thread_(base::ThreadTaskRunnerHandle::Get()) {
-}
+ : cookie_monster_(cookie_monster) {}
CookieMonster::CookieMonsterTask::~CookieMonsterTask() {
}
-// Unfortunately, one cannot re-bind a Callback with parameters into a closure.
-// Therefore, the closure passed to InvokeCallback is a clumsy binding of
-// Callback::Run on a wrapped Callback instance. Since Callback is not
-// reference counted, we bind to an instance that is a member of the
-// CookieMonsterTask subclass. Then, we cannot simply post the callback to a
-// message loop because the underlying instance may be destroyed (along with the
-// CookieMonsterTask instance) in the interim. Therefore, we post a callback
-// bound to the CookieMonsterTask, which *is* reference counted (thus preventing
-// destruction of the original callback), and which invokes the closure (which
-// invokes the original callback with the returned data).
-void CookieMonster::CookieMonsterTask::InvokeCallback(base::Closure callback) {
- if (thread_->BelongsToCurrentThread()) {
- callback.Run();
- } else {
- thread_->PostTask(FROM_HERE, base::Bind(&CookieMonsterTask::InvokeCallback,
- this, callback));
- }
-}
-
// Task class for SetCookieWithDetails call.
class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
public:
@@ -455,11 +375,12 @@ class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
const std::string& value,
const std::string& domain,
const std::string& path,
- const base::Time& expiration_time,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
bool secure,
bool http_only,
- bool first_party_only,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority,
const SetCookiesCallback& callback)
@@ -469,11 +390,12 @@ class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
value_(value),
domain_(domain),
path_(path),
+ creation_time_(creation_time),
expiration_time_(expiration_time),
+ last_access_time_(last_access_time),
secure_(secure),
http_only_(http_only),
- first_party_only_(first_party_only),
- enforce_prefixes_(enforce_prefixes),
+ same_site_(same_site),
enforce_strict_secure_(enforce_strict_secure),
priority_(priority),
callback_(callback) {}
@@ -490,11 +412,12 @@ class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
std::string value_;
std::string domain_;
std::string path_;
+ base::Time creation_time_;
base::Time expiration_time_;
+ base::Time last_access_time_;
bool secure_;
bool http_only_;
- bool first_party_only_;
- bool enforce_prefixes_;
+ CookieSameSite same_site_;
bool enforce_strict_secure_;
CookiePriority priority_;
SetCookiesCallback callback_;
@@ -504,13 +427,11 @@ class CookieMonster::SetCookieWithDetailsTask : public CookieMonsterTask {
void CookieMonster::SetCookieWithDetailsTask::Run() {
bool success = this->cookie_monster()->SetCookieWithDetails(
- url_, name_, value_, domain_, path_, expiration_time_, secure_,
- http_only_, first_party_only_, enforce_prefixes_, enforce_strict_secure_,
- priority_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
- base::Unretained(&callback_), success));
- }
+ url_, name_, value_, domain_, path_, creation_time_, expiration_time_,
+ last_access_time_, secure_, http_only_, same_site_,
+ enforce_strict_secure_, priority_);
+ if (!callback_.is_null())
+ callback_.Run(success);
}
// Task class for GetAllCookies call.
@@ -535,19 +456,17 @@ class CookieMonster::GetAllCookiesTask : public CookieMonsterTask {
void CookieMonster::GetAllCookiesTask::Run() {
if (!callback_.is_null()) {
CookieList cookies = this->cookie_monster()->GetAllCookies();
- this->InvokeCallback(base::Bind(&GetCookieListCallback::Run,
- base::Unretained(&callback_), cookies));
+ callback_.Run(cookies);
}
}
-// Task class for GetAllCookiesForURLWithOptions call.
-class CookieMonster::GetAllCookiesForURLWithOptionsTask
- : public CookieMonsterTask {
+// Task class for GetCookieListWithOptionsAsync call.
+class CookieMonster::GetCookieListWithOptionsTask : public CookieMonsterTask {
public:
- GetAllCookiesForURLWithOptionsTask(CookieMonster* cookie_monster,
- const GURL& url,
- const CookieOptions& options,
- const GetCookieListCallback& callback)
+ GetCookieListWithOptionsTask(CookieMonster* cookie_monster,
+ const GURL& url,
+ const CookieOptions& options,
+ const GetCookieListCallback& callback)
: CookieMonsterTask(cookie_monster),
url_(url),
options_(options),
@@ -557,22 +476,21 @@ class CookieMonster::GetAllCookiesForURLWithOptionsTask
void Run() override;
protected:
- ~GetAllCookiesForURLWithOptionsTask() override {}
+ ~GetCookieListWithOptionsTask() override {}
private:
GURL url_;
CookieOptions options_;
GetCookieListCallback callback_;
- DISALLOW_COPY_AND_ASSIGN(GetAllCookiesForURLWithOptionsTask);
+ DISALLOW_COPY_AND_ASSIGN(GetCookieListWithOptionsTask);
};
-void CookieMonster::GetAllCookiesForURLWithOptionsTask::Run() {
+void CookieMonster::GetCookieListWithOptionsTask::Run() {
if (!callback_.is_null()) {
CookieList cookies =
- this->cookie_monster()->GetAllCookiesForURLWithOptions(url_, options_);
- this->InvokeCallback(base::Bind(&GetCookieListCallback::Run,
- base::Unretained(&callback_), cookies));
+ this->cookie_monster()->GetCookieListWithOptions(url_, options_);
+ callback_.Run(cookies);
}
}
@@ -603,8 +521,11 @@ class CookieMonster::DeleteTask : public CookieMonsterTask {
private:
// Runs the delete task and returns a result.
virtual Result RunDeleteTask() = 0;
+ // Runs the delete task and then returns a callback to be called after
+ // flushing the persistent store.
+ // TODO(mmenke): This seems like a pretty ugly and needlessly confusing API.
+ // Simplify it?
base::Closure RunDeleteTaskAndBindCallback();
- void FlushDone(const base::Closure& callback);
typename CallbackType<Result>::Type callback_;
@@ -632,36 +553,13 @@ base::Closure CookieMonster::DeleteTask<void>::RunDeleteTaskAndBindCallback() {
template <typename Result>
void CookieMonster::DeleteTask<Result>::Run() {
- this->cookie_monster()->FlushStore(base::Bind(
- &DeleteTask<Result>::FlushDone, this, RunDeleteTaskAndBindCallback()));
-}
-
-template <typename Result>
-void CookieMonster::DeleteTask<Result>::FlushDone(
- const base::Closure& callback) {
+ base::Closure callback = RunDeleteTaskAndBindCallback();
if (!callback.is_null()) {
- this->InvokeCallback(callback);
+ callback = base::Bind(
+ &CookieMonster::RunCallback,
+ this->cookie_monster()->weak_ptr_factory_.GetWeakPtr(), callback);
}
-}
-
-// Task class for DeleteAll call.
-class CookieMonster::DeleteAllTask : public DeleteTask<int> {
- public:
- DeleteAllTask(CookieMonster* cookie_monster, const DeleteCallback& callback)
- : DeleteTask<int>(cookie_monster, callback) {}
-
- // DeleteTask:
- int RunDeleteTask() override;
-
- protected:
- ~DeleteAllTask() override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DeleteAllTask);
-};
-
-int CookieMonster::DeleteAllTask::RunDeleteTask() {
- return this->cookie_monster()->DeleteAll(true);
+ this->cookie_monster()->FlushStore(callback);
}
// Task class for DeleteAllCreatedBetween call.
@@ -693,30 +591,6 @@ int CookieMonster::DeleteAllCreatedBetweenTask::RunDeleteTask() {
delete_end_);
}
-// Task class for DeleteAllForHost call.
-class CookieMonster::DeleteAllForHostTask : public DeleteTask<int> {
- public:
- DeleteAllForHostTask(CookieMonster* cookie_monster,
- const GURL& url,
- const DeleteCallback& callback)
- : DeleteTask<int>(cookie_monster, callback), url_(url) {}
-
- // DeleteTask:
- int RunDeleteTask() override;
-
- protected:
- ~DeleteAllForHostTask() override {}
-
- private:
- GURL url_;
-
- DISALLOW_COPY_AND_ASSIGN(DeleteAllForHostTask);
-};
-
-int CookieMonster::DeleteAllForHostTask::RunDeleteTask() {
- return this->cookie_monster()->DeleteAllForHost(url_);
-}
-
// Task class for DeleteAllCreatedBetweenForHost call.
class CookieMonster::DeleteAllCreatedBetweenForHostTask
: public DeleteTask<int> {
@@ -751,15 +625,15 @@ int CookieMonster::DeleteAllCreatedBetweenForHostTask::RunDeleteTask() {
}
// Task class for DeleteCanonicalCookie call.
-class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<bool> {
+class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<int> {
public:
DeleteCanonicalCookieTask(CookieMonster* cookie_monster,
const CanonicalCookie& cookie,
- const DeleteCookieCallback& callback)
- : DeleteTask<bool>(cookie_monster, callback), cookie_(cookie) {}
+ const DeleteCallback& callback)
+ : DeleteTask<int>(cookie_monster, callback), cookie_(cookie) {}
// DeleteTask:
- bool RunDeleteTask() override;
+ int RunDeleteTask() override;
protected:
~DeleteCanonicalCookieTask() override {}
@@ -770,7 +644,7 @@ class CookieMonster::DeleteCanonicalCookieTask : public DeleteTask<bool> {
DISALLOW_COPY_AND_ASSIGN(DeleteCanonicalCookieTask);
};
-bool CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() {
+int CookieMonster::DeleteCanonicalCookieTask::RunDeleteTask() {
return this->cookie_monster()->DeleteCanonicalCookie(cookie_);
}
@@ -806,10 +680,8 @@ class CookieMonster::SetCookieWithOptionsTask : public CookieMonsterTask {
void CookieMonster::SetCookieWithOptionsTask::Run() {
bool result = this->cookie_monster()->SetCookieWithOptions(url_, cookie_line_,
options_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
- base::Unretained(&callback_), result));
- }
+ if (!callback_.is_null())
+ callback_.Run(result);
}
// Task class for SetAllCookies call.
@@ -849,10 +721,8 @@ void CookieMonster::SetAllCookiesTask::Run() {
if (positive_diff.size() > 0)
result = this->cookie_monster()->SetCanonicalCookies(list_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&SetCookiesCallback::Run,
- base::Unretained(&callback_), result));
- }
+ if (!callback_.is_null())
+ callback_.Run(result);
}
// Task class for GetCookiesWithOptions call.
@@ -888,10 +758,8 @@ void CookieMonster::GetCookiesWithOptionsTask::Run() {
"456373 CookieMonster::GetCookiesWithOptionsTask::Run"));
std::string cookie =
this->cookie_monster()->GetCookiesWithOptions(url_, options_);
- if (!callback_.is_null()) {
- this->InvokeCallback(base::Bind(&GetCookiesCallback::Run,
- base::Unretained(&callback_), cookie));
- }
+ if (!callback_.is_null())
+ callback_.Run(cookie);
}
// Task class for DeleteCookie call.
@@ -951,51 +819,95 @@ void CookieMonster::SetCookieWithDetailsAsync(
const std::string& value,
const std::string& domain,
const std::string& path,
- const Time& expiration_time,
+ Time creation_time,
+ Time expiration_time,
+ Time last_access_time,
bool secure,
bool http_only,
- bool first_party_only,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority,
const SetCookiesCallback& callback) {
scoped_refptr<SetCookieWithDetailsTask> task = new SetCookieWithDetailsTask(
- this, url, name, value, domain, path, expiration_time, secure, http_only,
- first_party_only, enforce_prefixes, enforce_strict_secure, priority,
- callback);
+ this, url, name, value, domain, path, creation_time, expiration_time,
+ last_access_time, secure, http_only, same_site, enforce_strict_secure,
+ priority, callback);
DoCookieTaskForURL(task, url);
}
-void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) {
- scoped_refptr<GetAllCookiesTask> task = new GetAllCookiesTask(this, callback);
+void CookieMonster::FlushStore(const base::Closure& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (initialized_ && store_.get())
+ store_->Flush(callback);
+ else if (!callback.is_null())
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+}
+
+void CookieMonster::SetForceKeepSessionState() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (store_)
+ store_->SetForceKeepSessionState();
+}
+void CookieMonster::SetAllCookiesAsync(const CookieList& list,
+ const SetCookiesCallback& callback) {
+ scoped_refptr<SetAllCookiesTask> task =
+ new SetAllCookiesTask(this, list, callback);
DoCookieTask(task);
}
-void CookieMonster::GetAllCookiesForURLWithOptionsAsync(
+void CookieMonster::SetCookieWithOptionsAsync(
const GURL& url,
+ const std::string& cookie_line,
const CookieOptions& options,
- const GetCookieListCallback& callback) {
- scoped_refptr<GetAllCookiesForURLWithOptionsTask> task =
- new GetAllCookiesForURLWithOptionsTask(this, url, options, callback);
+ const SetCookiesCallback& callback) {
+ scoped_refptr<SetCookieWithOptionsTask> task =
+ new SetCookieWithOptionsTask(this, url, cookie_line, options, callback);
DoCookieTaskForURL(task, url);
}
-void CookieMonster::GetAllCookiesForURLAsync(
+void CookieMonster::GetCookiesWithOptionsAsync(
const GURL& url,
+ const CookieOptions& options,
+ const GetCookiesCallback& callback) {
+ scoped_refptr<GetCookiesWithOptionsTask> task =
+ new GetCookiesWithOptionsTask(this, url, options, callback);
+
+ DoCookieTaskForURL(task, url);
+}
+
+void CookieMonster::GetCookieListWithOptionsAsync(
+ const GURL& url,
+ const CookieOptions& options,
const GetCookieListCallback& callback) {
- CookieOptions options;
- options.set_include_httponly();
- options.set_include_first_party_only_cookies();
- scoped_refptr<GetAllCookiesForURLWithOptionsTask> task =
- new GetAllCookiesForURLWithOptionsTask(this, url, options, callback);
+ scoped_refptr<GetCookieListWithOptionsTask> task =
+ new GetCookieListWithOptionsTask(this, url, options, callback);
DoCookieTaskForURL(task, url);
}
-void CookieMonster::DeleteAllAsync(const DeleteCallback& callback) {
- scoped_refptr<DeleteAllTask> task = new DeleteAllTask(this, callback);
+void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) {
+ scoped_refptr<GetAllCookiesTask> task = new GetAllCookiesTask(this, callback);
+
+ DoCookieTask(task);
+}
+
+void CookieMonster::DeleteCookieAsync(const GURL& url,
+ const std::string& cookie_name,
+ const base::Closure& callback) {
+ scoped_refptr<DeleteCookieTask> task =
+ new DeleteCookieTask(this, url, cookie_name, callback);
+
+ DoCookieTaskForURL(task, url);
+}
+
+void CookieMonster::DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+ const DeleteCallback& callback) {
+ scoped_refptr<DeleteCanonicalCookieTask> task =
+ new DeleteCanonicalCookieTask(this, cookie, callback);
DoCookieTask(task);
}
@@ -1022,115 +934,74 @@ void CookieMonster::DeleteAllCreatedBetweenForHostAsync(
DoCookieTaskForURL(task, url);
}
-void CookieMonster::DeleteAllForHostAsync(const GURL& url,
- const DeleteCallback& callback) {
- scoped_refptr<DeleteAllForHostTask> task =
- new DeleteAllForHostTask(this, url, callback);
-
- DoCookieTaskForURL(task, url);
-}
-
-void CookieMonster::DeleteCanonicalCookieAsync(
- const CanonicalCookie& cookie,
- const DeleteCookieCallback& callback) {
- scoped_refptr<DeleteCanonicalCookieTask> task =
- new DeleteCanonicalCookieTask(this, cookie, callback);
+void CookieMonster::DeleteSessionCookiesAsync(
+ const CookieStore::DeleteCallback& callback) {
+ scoped_refptr<DeleteSessionCookiesTask> task =
+ new DeleteSessionCookiesTask(this, callback);
DoCookieTask(task);
}
-void CookieMonster::SetAllCookiesAsync(const CookieList& list,
- const SetCookiesCallback& callback) {
- scoped_refptr<SetAllCookiesTask> task =
- new SetAllCookiesTask(this, list, callback);
- DoCookieTask(task);
-}
+void CookieMonster::SetCookieableSchemes(
+ const std::vector<std::string>& schemes) {
+ DCHECK(thread_checker_.CalledOnValidThread());
-void CookieMonster::SetCookieWithOptionsAsync(
- const GURL& url,
- const std::string& cookie_line,
- const CookieOptions& options,
- const SetCookiesCallback& callback) {
- scoped_refptr<SetCookieWithOptionsTask> task =
- new SetCookieWithOptionsTask(this, url, cookie_line, options, callback);
+ // Calls to this method will have no effect if made after a WebView or
+ // CookieManager instance has been created.
+ if (initialized_)
+ return;
- DoCookieTaskForURL(task, url);
+ cookieable_schemes_ = schemes;
}
-void CookieMonster::GetCookiesWithOptionsAsync(
- const GURL& url,
- const CookieOptions& options,
- const GetCookiesCallback& callback) {
- scoped_refptr<GetCookiesWithOptionsTask> task =
- new GetCookiesWithOptionsTask(this, url, options, callback);
-
- DoCookieTaskForURL(task, url);
+// This function must be called before the CookieMonster is used.
+void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!initialized_);
+ persist_session_cookies_ = persist_session_cookies;
}
-void CookieMonster::DeleteCookieAsync(const GURL& url,
- const std::string& cookie_name,
- const base::Closure& callback) {
- scoped_refptr<DeleteCookieTask> task =
- new DeleteCookieTask(this, url, cookie_name, callback);
+bool CookieMonster::IsCookieableScheme(const std::string& scheme) {
+ DCHECK(thread_checker_.CalledOnValidThread());
- DoCookieTaskForURL(task, url);
+ return std::find(cookieable_schemes_.begin(), cookieable_schemes_.end(),
+ scheme) != cookieable_schemes_.end();
}
-void CookieMonster::DeleteSessionCookiesAsync(
- const CookieStore::DeleteCallback& callback) {
- scoped_refptr<DeleteSessionCookiesTask> task =
- new DeleteSessionCookiesTask(this, callback);
+const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http", "https",
+ "ws", "wss"};
+const int CookieMonster::kDefaultCookieableSchemesCount =
+ arraysize(kDefaultCookieableSchemes);
- DoCookieTask(task);
-}
+scoped_ptr<CookieStore::CookieChangedSubscription>
+CookieMonster::AddCallbackForCookie(const GURL& gurl,
+ const std::string& name,
+ const CookieChangedCallback& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
-void CookieMonster::DoCookieTask(
- const scoped_refptr<CookieMonsterTask>& task_item) {
- {
- base::AutoLock autolock(lock_);
- MarkCookieStoreAsInitialized();
- FetchAllCookiesIfNecessary();
- if (!finished_fetching_all_cookies_ && store_.get()) {
- tasks_pending_.push(task_item);
- return;
- }
- }
+ std::pair<GURL, std::string> key(gurl, name);
+ if (hook_map_.count(key) == 0)
+ hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList());
+ return hook_map_[key]->Add(
+ base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
+}
- task_item->Run();
+bool CookieMonster::IsEphemeral() {
+ return store_.get() == nullptr;
}
-void CookieMonster::DoCookieTaskForURL(
- const scoped_refptr<CookieMonsterTask>& task_item,
- const GURL& url) {
- {
- base::AutoLock autolock(lock_);
- MarkCookieStoreAsInitialized();
- if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
- FetchAllCookiesIfNecessary();
- // If cookies for the requested domain key (eTLD+1) have been loaded from DB
- // then run the task, otherwise load from DB.
- if (!finished_fetching_all_cookies_ && store_.get()) {
- // Checks if the domain key has been loaded.
- std::string key(
- cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
- if (keys_loaded_.find(key) == keys_loaded_.end()) {
- std::map<std::string,
- std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
- tasks_pending_for_key_.find(key);
- if (it == tasks_pending_for_key_.end()) {
- store_->LoadCookiesForKey(
- key, base::Bind(&CookieMonster::OnKeyLoaded, this, key));
- it = tasks_pending_for_key_
- .insert(std::make_pair(
- key, std::deque<scoped_refptr<CookieMonsterTask>>()))
- .first;
- }
- it->second.push_back(task_item);
- return;
- }
- }
+CookieMonster::~CookieMonster() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // TODO(mmenke): Does it really make sense to run |delegate_| and
+ // CookieChanged callbacks when the CookieStore is destroyed?
+ for (CookieMap::iterator cookie_it = cookies_.begin();
+ cookie_it != cookies_.end();) {
+ CookieMap::iterator current_cookie_it = cookie_it;
+ ++cookie_it;
+ InternalDeleteCookie(current_cookie_it, false /* sync_to_store */,
+ DELETE_COOKIE_DONT_RECORD);
}
- task_item->Run();
}
bool CookieMonster::SetCookieWithDetails(const GURL& url,
@@ -1138,56 +1009,50 @@ bool CookieMonster::SetCookieWithDetails(const GURL& url,
const std::string& value,
const std::string& domain,
const std::string& path,
- const base::Time& expiration_time,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
bool secure,
bool http_only,
- bool first_party_only,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url))
return false;
- Time creation_time = CurrentTime();
- last_time_seen_ = creation_time;
+ // TODO(mmenke): This class assumes each cookie to have a unique creation
+ // time. Allowing the caller to set the creation time violates that
+ // assumption. Worth fixing? Worth noting that time changes between browser
+ // restarts can cause the same issue.
+ base::Time actual_creation_time = creation_time;
+ if (creation_time.is_null()) {
+ actual_creation_time = CurrentTime();
+ last_time_seen_ = actual_creation_time;
+ }
- scoped_ptr<CanonicalCookie> cc;
- cc.reset(CanonicalCookie::Create(
- url, name, value, domain, path, creation_time, expiration_time, secure,
- http_only, first_party_only, enforce_strict_secure, priority));
+ scoped_ptr<CanonicalCookie> cc(CanonicalCookie::Create(
+ url, name, value, domain, path, actual_creation_time, expiration_time,
+ secure, http_only, same_site, enforce_strict_secure, priority));
if (!cc.get())
return false;
+ if (!last_access_time.is_null())
+ cc->SetLastAccessDate(last_access_time);
+
CookieOptions options;
options.set_include_httponly();
- options.set_include_first_party_only_cookies();
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
if (enforce_strict_secure)
options.set_enforce_strict_secure();
- return SetCanonicalCookie(&cc, creation_time, options);
-}
-
-bool CookieMonster::ImportCookies(const CookieList& list) {
- base::AutoLock autolock(lock_);
- MarkCookieStoreAsInitialized();
- if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
- FetchAllCookiesIfNecessary();
- for (CookieList::const_iterator iter = list.begin(); iter != list.end();
- ++iter) {
- scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(*iter));
- CookieOptions options;
- options.set_include_httponly();
- options.set_include_first_party_only_cookies();
- if (!SetCanonicalCookie(&cookie, cookie->CreationDate(), options))
- return false;
- }
- return true;
+ return SetCanonicalCookie(std::move(cc), options);
}
CookieList CookieMonster::GetAllCookies() {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
// This function is being called to scrape the cookie list for management UI
// or similar. We shouldn't show expired cookies in this list since it will
@@ -1217,16 +1082,19 @@ CookieList CookieMonster::GetAllCookies() {
return cookie_list;
}
-CookieList CookieMonster::GetAllCookiesForURLWithOptions(
+CookieList CookieMonster::GetCookieListWithOptions(
const GURL& url,
const CookieOptions& options) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ CookieList cookies;
+ if (!HasCookieableScheme(url))
+ return cookies;
std::vector<CanonicalCookie*> cookie_ptrs;
- FindCookiesForHostAndDomain(url, options, false, &cookie_ptrs);
+ FindCookiesForHostAndDomain(url, options, &cookie_ptrs);
std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
- CookieList cookies;
cookies.reserve(cookie_ptrs.size());
for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin();
it != cookie_ptrs.end(); it++)
@@ -1235,26 +1103,9 @@ CookieList CookieMonster::GetAllCookiesForURLWithOptions(
return cookies;
}
-int CookieMonster::DeleteAll(bool sync_to_store) {
- base::AutoLock autolock(lock_);
-
- int num_deleted = 0;
- for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
- CookieMap::iterator curit = it;
- ++it;
- InternalDeleteCookie(curit, sync_to_store,
- sync_to_store
- ? DELETE_COOKIE_EXPLICIT
- : DELETE_COOKIE_DONT_RECORD /* Destruction. */);
- ++num_deleted;
- }
-
- return num_deleted;
-}
-
int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
const Time& delete_end) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
int num_deleted = 0;
for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
@@ -1276,7 +1127,7 @@ int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin,
int CookieMonster::DeleteAllCreatedBetweenForHost(const Time delete_begin,
const Time delete_end,
const GURL& url) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url))
return 0;
@@ -1308,55 +1159,11 @@ int CookieMonster::DeleteAllCreatedBetweenForHost(const Time delete_begin,
return num_deleted;
}
-int CookieMonster::DeleteAllForHost(const GURL& url) {
- return DeleteAllCreatedBetweenForHost(Time(), Time::Max(), url);
-}
-
-bool CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
- base::AutoLock autolock(lock_);
-
- for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
- its.first != its.second; ++its.first) {
- // The creation date acts as our unique index...
- if (its.first->second->CreationDate() == cookie.CreationDate()) {
- InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
- return true;
- }
- }
- return false;
-}
-
-void CookieMonster::SetCookieableSchemes(const char* const schemes[],
- size_t num_schemes) {
- base::AutoLock autolock(lock_);
-
- // Calls to this method will have no effect if made after a WebView or
- // CookieManager instance has been created.
- if (initialized_) {
- return;
- }
-
- cookieable_schemes_.clear();
- cookieable_schemes_.insert(cookieable_schemes_.end(), schemes,
- schemes + num_schemes);
-}
-
-void CookieMonster::SetKeepExpiredCookies() {
- keep_expired_cookies_ = true;
-}
-
-void CookieMonster::FlushStore(const base::Closure& callback) {
- base::AutoLock autolock(lock_);
- if (initialized_ && store_.get())
- store_->Flush(callback);
- else if (!callback.is_null())
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
-}
bool CookieMonster::SetCookieWithOptions(const GURL& url,
const std::string& cookie_line,
const CookieOptions& options) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url)) {
return false;
@@ -1367,13 +1174,13 @@ bool CookieMonster::SetCookieWithOptions(const GURL& url,
std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
const CookieOptions& options) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url))
return std::string();
std::vector<CanonicalCookie*> cookies;
- FindCookiesForHostAndDomain(url, options, true, &cookies);
+ FindCookiesForHostAndDomain(url, options, &cookies);
std::sort(cookies.begin(), cookies.end(), CookieSorter);
std::string cookie_line = BuildCookieLine(cookies);
@@ -1385,26 +1192,26 @@ std::string CookieMonster::GetCookiesWithOptions(const GURL& url,
void CookieMonster::DeleteCookie(const GURL& url,
const std::string& cookie_name) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
if (!HasCookieableScheme(url))
return;
CookieOptions options;
options.set_include_httponly();
- options.set_include_first_party_only_cookies();
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
// Get the cookies for this host and its domain(s).
std::vector<CanonicalCookie*> cookies;
- FindCookiesForHostAndDomain(url, options, true, &cookies);
+ FindCookiesForHostAndDomain(url, options, &cookies);
std::set<CanonicalCookie*> matching_cookies;
- for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
- it != cookies.end(); ++it) {
- if ((*it)->Name() != cookie_name)
+ for (const auto& cookie : cookies) {
+ if (cookie->Name() != cookie_name)
continue;
- if (url.path().find((*it)->Path()))
+ if (!cookie->IsOnPath(url.path()))
continue;
- matching_cookies.insert(*it);
+ matching_cookies.insert(cookie);
}
for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
@@ -1416,50 +1223,25 @@ void CookieMonster::DeleteCookie(const GURL& url,
}
}
-int CookieMonster::DeleteSessionCookies() {
- base::AutoLock autolock(lock_);
+int CookieMonster::DeleteCanonicalCookie(const CanonicalCookie& cookie) {
+ DCHECK(thread_checker_.CalledOnValidThread());
- int num_deleted = 0;
- for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
- CookieMap::iterator curit = it;
- CanonicalCookie* cc = curit->second;
- ++it;
-
- if (!cc->IsPersistent()) {
- InternalDeleteCookie(curit, true, /*sync_to_store*/
- DELETE_COOKIE_EXPIRED);
- ++num_deleted;
+ for (CookieMapItPair its = cookies_.equal_range(GetKey(cookie.Domain()));
+ its.first != its.second; ++its.first) {
+ // The creation date acts as the unique index...
+ if (its.first->second->CreationDate() == cookie.CreationDate()) {
+ InternalDeleteCookie(its.first, true, DELETE_COOKIE_EXPLICIT);
+ return 1;
}
}
-
- return num_deleted;
-}
-
-CookieMonster* CookieMonster::GetCookieMonster() {
- return this;
-}
-
-// This function must be called before the CookieMonster is used.
-void CookieMonster::SetPersistSessionCookies(bool persist_session_cookies) {
- DCHECK(!initialized_);
- persist_session_cookies_ = persist_session_cookies;
-}
-
-void CookieMonster::SetForceKeepSessionState() {
- if (store_.get()) {
- store_->SetForceKeepSessionState();
- }
-}
-
-CookieMonster::~CookieMonster() {
- DeleteAll(false);
+ return 0;
}
bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!store_.get()) << "This method is only to be used by unit-tests.";
- base::AutoLock autolock(lock_);
if (!HasCookieableScheme(url)) {
return false;
@@ -1473,18 +1255,53 @@ bool CookieMonster::SetCookieWithCreationTime(const GURL& url,
CookieOptions());
}
+int CookieMonster::DeleteSessionCookies() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ int num_deleted = 0;
+ for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) {
+ CookieMap::iterator curit = it;
+ CanonicalCookie* cc = curit->second;
+ ++it;
+
+ if (!cc->IsPersistent()) {
+ InternalDeleteCookie(curit, true, /*sync_to_store*/
+ DELETE_COOKIE_EXPIRED);
+ ++num_deleted;
+ }
+ }
+
+ return num_deleted;
+}
+
void CookieMonster::MarkCookieStoreAsInitialized() {
+ DCHECK(thread_checker_.CalledOnValidThread());
initialized_ = true;
}
void CookieMonster::FetchAllCookiesIfNecessary() {
+ DCHECK(thread_checker_.CalledOnValidThread());
if (store_.get() && !started_fetching_all_cookies_) {
started_fetching_all_cookies_ = true;
FetchAllCookies();
}
}
+void CookieMonster::FetchAllCookies() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(store_.get()) << "Store must exist to initialize";
+ DCHECK(!finished_fetching_all_cookies_)
+ << "All cookies have already been fetched.";
+
+ // We bind in the current time so that we can report the wall-clock time for
+ // loading cookies.
+ store_->Load(base::Bind(&CookieMonster::OnLoaded,
+ weak_ptr_factory_.GetWeakPtr(), TimeTicks::Now()));
+}
+
bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
if (fetch_strategy_ == kUnknownFetch) {
const std::string group_name =
base::FieldTrialList::FindFullName(kCookieMonsterFetchStrategyName);
@@ -1502,18 +1319,9 @@ bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() {
return fetch_strategy_ == kAlwaysFetch;
}
-void CookieMonster::FetchAllCookies() {
- DCHECK(store_.get()) << "Store must exist to initialize";
- DCHECK(!finished_fetching_all_cookies_)
- << "All cookies have already been fetched.";
-
- // We bind in the current time so that we can report the wall-clock time for
- // loading cookies.
- store_->Load(base::Bind(&CookieMonster::OnLoaded, this, TimeTicks::Now()));
-}
-
void CookieMonster::OnLoaded(TimeTicks beginning_time,
const std::vector<CanonicalCookie*>& cookies) {
+ DCHECK(thread_checker_.CalledOnValidThread());
StoreLoadedCookies(cookies);
histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time);
@@ -1523,52 +1331,45 @@ void CookieMonster::OnLoaded(TimeTicks beginning_time,
void CookieMonster::OnKeyLoaded(const std::string& key,
const std::vector<CanonicalCookie*>& cookies) {
- // This function does its own separate locking.
+ DCHECK(thread_checker_.CalledOnValidThread());
+
StoreLoadedCookies(cookies);
- std::deque<scoped_refptr<CookieMonsterTask>> tasks_pending_for_key;
+ auto tasks_pending_for_key = tasks_pending_for_key_.find(key);
- // We need to do this repeatedly until no more tasks were added to the queue
- // during the period where we release the lock.
- while (true) {
- {
- base::AutoLock autolock(lock_);
- std::map<std::string,
- std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
- tasks_pending_for_key_.find(key);
- if (it == tasks_pending_for_key_.end()) {
- keys_loaded_.insert(key);
- return;
- }
- if (it->second.empty()) {
- keys_loaded_.insert(key);
- tasks_pending_for_key_.erase(it);
- return;
- }
- it->second.swap(tasks_pending_for_key);
- }
+ // TODO(mmenke): Can this be turned into a DCHECK?
+ if (tasks_pending_for_key == tasks_pending_for_key_.end())
+ return;
- while (!tasks_pending_for_key.empty()) {
- scoped_refptr<CookieMonsterTask> task = tasks_pending_for_key.front();
- task->Run();
- tasks_pending_for_key.pop_front();
- }
+ // Run all tasks for the key. Note that running a task can result in multiple
+ // tasks being added to the back of the deque.
+ while (!tasks_pending_for_key->second.empty()) {
+ scoped_refptr<CookieMonsterTask> task =
+ tasks_pending_for_key->second.front();
+ tasks_pending_for_key->second.pop_front();
+
+ task->Run();
}
+
+ tasks_pending_for_key_.erase(tasks_pending_for_key);
+
+ // This has to be done last, in case running a task queues a new task for the
+ // key, to ensure tasks are run in the correct order.
+ keys_loaded_.insert(key);
}
void CookieMonster::StoreLoadedCookies(
const std::vector<CanonicalCookie*>& cookies) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// TODO(erikwright): Remove ScopedTracker below once crbug.com/457528 is
// fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"457528 CookieMonster::StoreLoadedCookies"));
- // Initialize the store and sync in any saved persistent cookies. We don't
- // care if it's expired, insert it so it can be garbage collected, removed,
- // and sync'd.
- base::AutoLock autolock(lock_);
-
+ // Even if a key is expired, insert it so it can be garbage collected,
+ // removed, and sync'd.
CookieItVector cookies_with_control_chars;
for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin();
@@ -1621,25 +1422,36 @@ void CookieMonster::StoreLoadedCookies(
}
void CookieMonster::InvokeQueue() {
- while (true) {
- scoped_refptr<CookieMonsterTask> request_task;
- {
- base::AutoLock autolock(lock_);
- if (tasks_pending_.empty()) {
- finished_fetching_all_cookies_ = true;
- creation_times_.clear();
- keys_loaded_.clear();
- break;
- }
- request_task = tasks_pending_.front();
- tasks_pending_.pop();
- }
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Move all per-key tasks into the global queue, if there are any. This is
+ // protection about a race where the store learns about all cookies loading
+ // before it learned about the cookies for a key loading.
+
+ // Needed to prevent any recursively queued tasks from going back into the
+ // per-key queues.
+ seen_global_task_ = true;
+ for (const auto& tasks_for_key : tasks_pending_for_key_) {
+ tasks_pending_.insert(tasks_pending_.begin(), tasks_for_key.second.begin(),
+ tasks_for_key.second.end());
+ }
+ tasks_pending_for_key_.clear();
+
+ while (!tasks_pending_.empty()) {
+ scoped_refptr<CookieMonsterTask> request_task = tasks_pending_.front();
+ tasks_pending_.pop_front();
request_task->Run();
}
+
+ DCHECK(tasks_pending_for_key_.empty());
+
+ finished_fetching_all_cookies_ = true;
+ creation_times_.clear();
+ keys_loaded_.clear();
}
void CookieMonster::EnsureCookiesMapIsValid() {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Iterate through all the of the cookies, grouped by host.
CookieMap::iterator prev_range_end = cookies_.begin();
@@ -1657,7 +1469,7 @@ void CookieMonster::EnsureCookiesMapIsValid() {
void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key,
CookieMap::iterator begin,
CookieMap::iterator end) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Set of cookies ordered by creation time.
typedef std::set<CookieMap::iterator, OrderByCreationTimeDesc> CookieSet;
@@ -1729,27 +1541,11 @@ void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key,
DCHECK_EQ(num_duplicates, num_duplicates_found);
}
-// Note: file must be the last scheme.
-const char* const CookieMonster::kDefaultCookieableSchemes[] = {"http",
- "https",
- "ws",
- "wss",
- "file"};
-const int CookieMonster::kDefaultCookieableSchemesCount =
- arraysize(kDefaultCookieableSchemes);
-
-void CookieMonster::SetDefaultCookieableSchemes() {
- // Always disable file scheme unless SetEnableFileScheme(true) is called.
- SetCookieableSchemes(kDefaultCookieableSchemes,
- kDefaultCookieableSchemesCount - 1);
-}
-
void CookieMonster::FindCookiesForHostAndDomain(
const GURL& url,
const CookieOptions& options,
- bool update_access_time,
std::vector<CanonicalCookie*>* cookies) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
const Time current_time(CurrentTime());
@@ -1760,17 +1556,15 @@ void CookieMonster::FindCookiesForHostAndDomain(
// Can just dispatch to FindCookiesForKey
const std::string key(GetKey(url.host()));
- FindCookiesForKey(key, url, options, current_time, update_access_time,
- cookies);
+ FindCookiesForKey(key, url, options, current_time, cookies);
}
void CookieMonster::FindCookiesForKey(const std::string& key,
const GURL& url,
const CookieOptions& options,
const Time& current,
- bool update_access_time,
std::vector<CanonicalCookie*>* cookies) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
for (CookieMapItPair its = cookies_.equal_range(key);
its.first != its.second;) {
@@ -1779,7 +1573,7 @@ void CookieMonster::FindCookiesForKey(const std::string& key,
++its.first;
// If the cookie is expired, delete it.
- if (cc->IsExpired(current) && !keep_expired_cookies_) {
+ if (cc->IsExpired(current)) {
InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED);
continue;
}
@@ -1792,7 +1586,7 @@ void CookieMonster::FindCookiesForKey(const std::string& key,
// Add this cookie to the set of matching cookies. Update the access
// time if we've been requested to do so.
- if (update_access_time) {
+ if (options.update_access_time()) {
InternalUpdateCookieAccessTime(cc, current);
}
cookies->push_back(cc);
@@ -1804,7 +1598,7 @@ bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key,
bool skip_httponly,
bool already_expired,
bool enforce_strict_secure) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
bool found_equivalent_cookie = false;
bool skipped_httponly = false;
@@ -1867,11 +1661,12 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
const std::string& key,
CanonicalCookie* cc,
bool sync_to_store) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// TODO(mkwst): Remove ScopedTracker below once crbug.com/456373 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"456373 CookieMonster::InternalInsertCookie"));
- lock_.AssertAcquired();
if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() &&
sync_to_store)
@@ -1884,11 +1679,12 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
}
// See InitializeHistograms() for details.
- int32_t cookie_type_sample =
- cc->IsFirstPartyOnly() ? 1 << COOKIE_TYPE_FIRSTPARTYONLY : 0;
- cookie_type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
- cookie_type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
- histogram_cookie_type_->Add(cookie_type_sample);
+ int32_t type_sample = cc->SameSite() != CookieSameSite::NO_RESTRICTION
+ ? 1 << COOKIE_TYPE_SAME_SITE
+ : 0;
+ type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
+ type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
+ histogram_cookie_type_->Add(type_sample);
// Histogram the type of scheme used on URLs that set cookies. This
// intentionally includes cookies that are set or overwritten by
@@ -1910,7 +1706,7 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
histogram_cookie_source_scheme_->Add(cookie_source_sample);
}
- RunCallbacks(*cc, false);
+ RunCookieChangedCallbacks(*cc, false);
return inserted;
}
@@ -1920,7 +1716,7 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions(
const std::string& cookie_line,
const Time& creation_time_or_null,
const CookieOptions& options) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
VLOG(kVlogSetCookies) << "SetCookie() line: " << cookie_line;
@@ -1937,16 +1733,18 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions(
VLOG(kVlogSetCookies) << "WARNING: Failed to allocate CanonicalCookie";
return false;
}
- return SetCanonicalCookie(&cc, creation_time, options);
+ return SetCanonicalCookie(std::move(cc), options);
}
-bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
- const Time& creation_time,
+bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie> cc,
const CookieOptions& options) {
- const std::string key(GetKey((*cc)->Domain()));
- bool already_expired = (*cc)->IsExpired(creation_time);
+ DCHECK(thread_checker_.CalledOnValidThread());
- if (DeleteAnyEquivalentCookie(key, **cc, options.exclude_httponly(),
+ Time creation_time = cc->CreationDate();
+ const std::string key(GetKey(cc->Domain()));
+ bool already_expired = cc->IsExpired(creation_time);
+
+ if (DeleteAnyEquivalentCookie(key, *cc, options.exclude_httponly(),
already_expired,
options.enforce_strict_secure())) {
std::string error;
@@ -1963,21 +1761,18 @@ bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
}
VLOG(kVlogSetCookies) << "SetCookie() key: " << key
- << " cc: " << (*cc)->DebugString();
+ << " cc: " << cc->DebugString();
// Realize that we might be setting an expired cookie, and the only point
// was to delete the cookie which we've already done.
- if (!already_expired || keep_expired_cookies_) {
+ if (!already_expired) {
// See InitializeHistograms() for details.
- if ((*cc)->IsPersistent()) {
+ if (cc->IsPersistent()) {
histogram_expiration_duration_minutes_->Add(
- ((*cc)->ExpiryDate() - creation_time).InMinutes());
+ (cc->ExpiryDate() - creation_time).InMinutes());
}
- {
- CanonicalCookie cookie = *(cc->get());
- InternalInsertCookie(key, cc->release(), true);
- }
+ InternalInsertCookie(key, cc.release(), true);
} else {
VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie.";
}
@@ -1993,15 +1788,16 @@ bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc,
}
bool CookieMonster::SetCanonicalCookies(const CookieList& list) {
- base::AutoLock autolock(lock_);
+ DCHECK(thread_checker_.CalledOnValidThread());
CookieOptions options;
options.set_include_httponly();
- for (CookieList::const_iterator it = list.begin(); it != list.end(); ++it) {
- scoped_ptr<CanonicalCookie> canonical_cookie(new CanonicalCookie(*it));
- if (!SetCanonicalCookie(&canonical_cookie, it->CreationDate(), options))
+ for (const auto& cookie : list) {
+ if (!SetCanonicalCookie(make_scoped_ptr(new CanonicalCookie(cookie)),
+ options)) {
return false;
+ }
}
return true;
@@ -2009,7 +1805,7 @@ bool CookieMonster::SetCanonicalCookies(const CookieList& list) {
void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
const Time& current) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Based off the Mozilla code. When a cookie has been accessed recently,
// don't bother updating its access time again. This reduces the number of
@@ -2028,7 +1824,7 @@ void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc,
void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
bool sync_to_store,
DeletionCause deletion_cause) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Ideally, this would be asserted up where we define ChangeCauseMapping,
// but DeletionCause's visibility (or lack thereof) forces us to make
@@ -2054,39 +1850,17 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
if (mapping.notify)
delegate_->OnCookieChanged(*cc, true, mapping.cause);
}
- RunCallbacks(*cc, true);
+ RunCookieChangedCallbacks(*cc, true);
cookies_.erase(it);
delete cc;
}
-size_t CookieMonster::GarbageCollectLeastRecentlyAccessed(
- const base::Time& current,
- const base::Time& safe_date,
- size_t purge_goal,
- CookieItVector cookie_its) {
- // Sorts up to *and including* |cookie_its[purge_goal]|, so
- // |earliest_access_time| will be properly assigned even if
- // |global_purge_it| == |cookie_its.begin() + purge_goal|.
- SortLeastRecentlyAccessed(cookie_its.begin(), cookie_its.end(), purge_goal);
- // Find boundary to cookies older than safe_date.
- CookieItVector::iterator global_purge_it = LowerBoundAccessDate(
- cookie_its.begin(), cookie_its.begin() + purge_goal, safe_date);
- // Only delete the old cookies, and if strict secure is enabled, delete
- // non-secure ones first.
- size_t num_deleted =
- GarbageCollectDeleteRange(current, DELETE_COOKIE_EVICTED_GLOBAL,
- cookie_its.begin(), global_purge_it);
- // Set access day to the oldest cookie that wasn't deleted.
- earliest_access_time_ = (*global_purge_it)->second->LastAccessDate();
- return num_deleted;
-}
-
// Domain expiry behavior is unchanged by key/expiry scheme (the
// meaning of the key is different, but that's not visible to this routine).
size_t CookieMonster::GarbageCollect(const Time& current,
const std::string& key,
bool enforce_strict_secure) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
size_t num_deleted = 0;
Time safe_date(Time::Now() - TimeDelta::FromDays(kSafeFromGlobalPurgeDays));
@@ -2102,6 +1876,7 @@ size_t CookieMonster::GarbageCollect(const Time& current,
num_deleted +=
GarbageCollectExpired(current, cookies_.equal_range(key), cookie_its);
+ // TODO(mkwst): Soften this.
CookieItVector secure_cookie_its;
if (enforce_strict_secure && cookie_its->size() > kDomainMaxCookies) {
VLOG(kVlogGarbageCollection) << "Garbage collecting non-Secure cookies.";
@@ -2116,56 +1891,27 @@ size_t CookieMonster::GarbageCollect(const Time& current,
cookie_its->size() - (kDomainMaxCookies - kDomainPurgeCookies);
DCHECK(purge_goal > kDomainPurgeCookies);
- // Boundary iterators into |cookie_its| for different priorities.
- CookieItVector::iterator it_bdd[4];
- // Intialize |it_bdd| while sorting |cookie_its| by priorities.
- // Schematic: [MLLHMHHLMM] => [LLL|MMMM|HHH], with 4 boundaries.
- it_bdd[0] = cookie_its->begin();
- it_bdd[3] = cookie_its->end();
- it_bdd[1] =
- PartitionCookieByPriority(it_bdd[0], it_bdd[3], COOKIE_PRIORITY_LOW);
- it_bdd[2] = PartitionCookieByPriority(it_bdd[1], it_bdd[3],
- COOKIE_PRIORITY_MEDIUM);
- size_t quota[3] = {kDomainCookiesQuotaLow,
- kDomainCookiesQuotaMedium,
- kDomainCookiesQuotaHigh};
-
- // Purge domain cookies in 3 rounds.
- // Round 1: consider low-priority cookies only: evict least-recently
- // accessed, while protecting quota[0] of these from deletion.
- // Round 2: consider {low, medium}-priority cookies, evict least-recently
- // accessed, while protecting quota[0] + quota[1].
- // Round 3: consider all cookies, evict least-recently accessed.
- size_t accumulated_quota = 0;
- CookieItVector::iterator it_purge_begin = it_bdd[0];
- for (int i = 0; i < 3 && purge_goal > 0; ++i) {
- accumulated_quota += quota[i];
-
- size_t num_considered = it_bdd[i + 1] - it_purge_begin;
- if (num_considered <= accumulated_quota)
- continue;
-
- // Number of cookies that will be purged in this round.
- size_t round_goal =
- std::min(purge_goal, num_considered - accumulated_quota);
- purge_goal -= round_goal;
-
- SortLeastRecentlyAccessed(it_purge_begin, it_bdd[i + 1], round_goal);
- // Cookies accessed on or after |safe_date| would have been safe from
- // global purge, and we want to keep track of this.
- CookieItVector::iterator it_purge_end = it_purge_begin + round_goal;
- CookieItVector::iterator it_purge_middle =
- LowerBoundAccessDate(it_purge_begin, it_purge_end, safe_date);
- // Delete cookies accessed before |safe_date|.
- num_deleted += GarbageCollectDeleteRange(
- current, DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE, it_purge_begin,
- it_purge_middle);
- // Delete cookies accessed on or after |safe_date|.
- num_deleted += GarbageCollectDeleteRange(
- current, DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE, it_purge_middle,
- it_purge_end);
- it_purge_begin = it_purge_end;
+ // Sort the cookies by access date, from least-recent to most-recent.
+ std::sort(cookie_its->begin(), cookie_its->end(), LRACookieSorter);
+
+ // Remove all but the kDomainCookiesQuotaLow most-recently accessed
+ // cookies with low-priority. Then, if cookies still need to be removed,
+ // bump the quota and remove low- and medium-priority. Then, if cookies
+ // _still_ need to be removed, bump the quota and remove cookies with
+ // any priority.
+ const size_t kQuotas[3] = {kDomainCookiesQuotaLow,
+ kDomainCookiesQuotaMedium,
+ kDomainCookiesQuotaHigh};
+ size_t quota = 0;
+ for (size_t i = 0; i < arraysize(kQuotas) && purge_goal > 0; i++) {
+ quota += kQuotas[i];
+ size_t just_deleted = PurgeLeastRecentMatches(
+ cookie_its, static_cast<CookiePriority>(i), quota, purge_goal);
+ DCHECK_LE(just_deleted, purge_goal);
+ purge_goal -= just_deleted;
+ num_deleted += just_deleted;
}
+
DCHECK_EQ(0U, purge_goal);
}
}
@@ -2213,13 +1959,49 @@ size_t CookieMonster::GarbageCollect(const Time& current,
return num_deleted;
}
+size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
+ CookiePriority priority,
+ size_t to_protect,
+ size_t purge_goal) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Find the first protected cookie by walking down from the end of the list
+ // cookie list (most-recently accessed) until |to_protect| cookies that match
+ // |priority| are found.
+ size_t protection_boundary = cookies->size();
+ while (to_protect > 0 && protection_boundary > 0) {
+ protection_boundary--;
+ if (cookies->at(protection_boundary)->second->Priority() <= priority)
+ to_protect--;
+ }
+
+ // Now, walk up from the beginning of the list (least-recently accessed) until
+ // |purge_goal| cookies are removed, or the iterator hits
+ // |protection_boundary|.
+ size_t removed = 0;
+ size_t current = 0;
+ while (removed < purge_goal && current < protection_boundary) {
+ if (cookies->at(current)->second->Priority() <= priority) {
+ InternalDeleteCookie(cookies->at(current), true,
+ DELETE_COOKIE_EVICTED_DOMAIN);
+ cookies->erase(cookies->begin() + current);
+ removed++;
+
+ // The call to 'erase' above shifts the contents of the vector, but
+ // doesn't shift |protection_boundary|. Decrement that here to ensure that
+ // the correct set of cookies is protected.
+ protection_boundary--;
+ } else {
+ current++;
+ }
+ }
+ return removed;
+}
+
size_t CookieMonster::GarbageCollectExpired(const Time& current,
const CookieMapItPair& itpair,
CookieItVector* cookie_its) {
- if (keep_expired_cookies_)
- return 0;
-
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
int num_deleted = 0;
for (CookieMap::iterator it = itpair.first, end = itpair.second; it != end;) {
@@ -2240,7 +2022,7 @@ size_t CookieMonster::GarbageCollectExpired(const Time& current,
size_t CookieMonster::GarbageCollectNonSecure(
const CookieItVector& valid_cookies,
CookieItVector* cookie_its) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
size_t num_deleted = 0;
for (const auto& curr_cookie_it : valid_cookies) {
@@ -2260,6 +2042,8 @@ size_t CookieMonster::GarbageCollectDeleteRange(
DeletionCause cause,
CookieItVector::iterator it_begin,
CookieItVector::iterator it_end) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
for (CookieItVector::iterator it = it_begin; it != it_end; it++) {
histogram_evicted_last_access_minutes_->Add(
(current - (*it)->second->LastAccessDate()).InMinutes());
@@ -2268,6 +2052,30 @@ size_t CookieMonster::GarbageCollectDeleteRange(
return it_end - it_begin;
}
+size_t CookieMonster::GarbageCollectLeastRecentlyAccessed(
+ const base::Time& current,
+ const base::Time& safe_date,
+ size_t purge_goal,
+ CookieItVector cookie_its) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Sorts up to *and including* |cookie_its[purge_goal]|, so
+ // |earliest_access_time| will be properly assigned even if
+ // |global_purge_it| == |cookie_its.begin() + purge_goal|.
+ SortLeastRecentlyAccessed(cookie_its.begin(), cookie_its.end(), purge_goal);
+ // Find boundary to cookies older than safe_date.
+ CookieItVector::iterator global_purge_it = LowerBoundAccessDate(
+ cookie_its.begin(), cookie_its.begin() + purge_goal, safe_date);
+ // Only delete the old cookies, and if strict secure is enabled, delete
+ // non-secure ones first.
+ size_t num_deleted =
+ GarbageCollectDeleteRange(current, DELETE_COOKIE_EVICTED_GLOBAL,
+ cookie_its.begin(), global_purge_it);
+ // Set access day to the oldest cookie that wasn't deleted.
+ earliest_access_time_ = (*global_purge_it)->second->LastAccessDate();
+ return num_deleted;
+}
+
// A wrapper around registry_controlled_domains::GetDomainAndRegistry
// to make clear we're creating a key for our local map. Here and
// in FindCookiesForHostAndDomain() are the only two places where
@@ -2292,6 +2100,8 @@ size_t CookieMonster::GarbageCollectDeleteRange(
// be worth it, but is still too much trouble to solve what is currently a
// non-problem).
std::string CookieMonster::GetKey(const std::string& domain) const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
std::string effective_domain(
registry_controlled_domains::GetDomainAndRegistry(
domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
@@ -2303,15 +2113,8 @@ std::string CookieMonster::GetKey(const std::string& domain) const {
return effective_domain;
}
-bool CookieMonster::IsCookieableScheme(const std::string& scheme) {
- base::AutoLock autolock(lock_);
-
- return std::find(cookieable_schemes_.begin(), cookieable_schemes_.end(),
- scheme) != cookieable_schemes_.end();
-}
-
bool CookieMonster::HasCookieableScheme(const GURL& url) {
- lock_.AssertAcquired();
+ DCHECK(thread_checker_.CalledOnValidThread());
// Make sure the request is on a cookie-able url scheme.
for (size_t i = 0; i < cookieable_schemes_.size(); ++i) {
@@ -2337,6 +2140,8 @@ bool CookieMonster::HasCookieableScheme(const GURL& url) {
// in the constructor so that we won't take statistics right after
// startup, to avoid bias from browsers that are started but not used.
void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
const base::TimeDelta kRecordStatisticsIntervalTime(
base::TimeDelta::FromSeconds(kRecordStatisticsIntervalSeconds));
@@ -2377,6 +2182,8 @@ void CookieMonster::RecordPeriodicStats(const base::Time& current_time) {
// methods where needed. The specific histogram macro calls on which the
// initialization is based are included in comments below.
void CookieMonster::InitializeHistograms() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
// From UMA_HISTOGRAM_CUSTOM_COUNTS
histogram_expiration_duration_minutes_ = base::Histogram::FactoryGet(
"Cookie.ExpirationDurationMinutes", 1, kMinutesInTenYears, 50,
@@ -2418,10 +2225,70 @@ Time CookieMonster::CurrentTime() {
last_time_seen_.ToInternalValue() + 1));
}
+void CookieMonster::DoCookieTask(
+ const scoped_refptr<CookieMonsterTask>& task_item) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ MarkCookieStoreAsInitialized();
+ FetchAllCookiesIfNecessary();
+ seen_global_task_ = true;
+
+ if (!finished_fetching_all_cookies_ && store_.get()) {
+ tasks_pending_.push_back(task_item);
+ return;
+ }
+
+ task_item->Run();
+}
+
+void CookieMonster::DoCookieTaskForURL(
+ const scoped_refptr<CookieMonsterTask>& task_item,
+ const GURL& url) {
+ MarkCookieStoreAsInitialized();
+ if (ShouldFetchAllCookiesWhenFetchingAnyCookie())
+ FetchAllCookiesIfNecessary();
+
+ // If cookies for the requested domain key (eTLD+1) have been loaded from DB
+ // then run the task, otherwise load from DB.
+ if (!finished_fetching_all_cookies_ && store_.get()) {
+ // If a global task has been previously seen, queue the task as a global
+ // task. Note that the CookieMonster may be in the middle of executing
+ // the global queue, |tasks_pending_| may be empty, which is why another
+ // bool is needed.
+ if (seen_global_task_) {
+ tasks_pending_.push_back(task_item);
+ return;
+ }
+
+ // Checks if the domain key has been loaded.
+ std::string key(cookie_util::GetEffectiveDomain(url.scheme(), url.host()));
+ if (keys_loaded_.find(key) == keys_loaded_.end()) {
+ std::map<std::string,
+ std::deque<scoped_refptr<CookieMonsterTask>>>::iterator it =
+ tasks_pending_for_key_.find(key);
+ if (it == tasks_pending_for_key_.end()) {
+ store_->LoadCookiesForKey(
+ key, base::Bind(&CookieMonster::OnKeyLoaded,
+ weak_ptr_factory_.GetWeakPtr(), key));
+ it = tasks_pending_for_key_
+ .insert(std::make_pair(
+ key, std::deque<scoped_refptr<CookieMonsterTask>>()))
+ .first;
+ }
+ it->second.push_back(task_item);
+ return;
+ }
+ }
+
+ task_item->Run();
+}
+
void CookieMonster::ComputeCookieDiff(CookieList* old_cookies,
CookieList* new_cookies,
CookieList* cookies_to_add,
CookieList* cookies_to_delete) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
DCHECK(old_cookies);
DCHECK(new_cookies);
DCHECK(cookies_to_add);
@@ -2451,45 +2318,23 @@ void CookieMonster::ComputeCookieDiff(CookieList* old_cookies,
FullDiffCookieSorter);
}
-scoped_ptr<CookieStore::CookieChangedSubscription>
-CookieMonster::AddCallbackForCookie(const GURL& gurl,
- const std::string& name,
- const CookieChangedCallback& callback) {
- base::AutoLock autolock(lock_);
- std::pair<GURL, std::string> key(gurl, name);
- if (hook_map_.count(key) == 0)
- hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList());
- return hook_map_[key]->Add(
- base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback));
+void CookieMonster::RunCallback(const base::Closure& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ callback.Run();
}
-#if defined(OS_ANDROID)
-void CookieMonster::SetEnableFileScheme(bool accept) {
- // This assumes "file" is always at the end of the array. See the comment
- // above kDefaultCookieableSchemes.
- //
- // TODO(mkwst): We're keeping this method around to support the
- // 'CookieManager::setAcceptFileSchemeCookies' method on Android's WebView;
- // if/when we can deprecate and remove that method, we can remove this one
- // as well. Until then, we'll just ensure that the method has no effect on
- // non-android systems.
- int num_schemes = accept ? kDefaultCookieableSchemesCount
- : kDefaultCookieableSchemesCount - 1;
-
- SetCookieableSchemes(kDefaultCookieableSchemes, num_schemes);
-}
-#endif
+void CookieMonster::RunCookieChangedCallbacks(const CanonicalCookie& cookie,
+ bool removed) {
+ DCHECK(thread_checker_.CalledOnValidThread());
-void CookieMonster::RunCallbacks(const CanonicalCookie& cookie, bool removed) {
- lock_.AssertAcquired();
CookieOptions opts;
opts.set_include_httponly();
- opts.set_include_first_party_only_cookies();
- // Note that the callbacks in hook_map_ are wrapped with MakeAsync(), so they
+ opts.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ // Note that the callbacks in hook_map_ are wrapped with RunAsync(), so they
// are guaranteed to not take long - they just post a RunAsync task back to
- // the appropriate thread's message loop and return. It is important that this
- // method not run user-supplied callbacks directly, since the CookieMonster
- // lock is held and it is easy to accidentally introduce deadlocks.
+ // the appropriate thread's message loop and return.
+ // TODO(mmenke): Consider running these synchronously?
for (CookieChangedHookMap::iterator it = hook_map_.begin();
it != hook_map_.end(); ++it) {
std::pair<GURL, std::string> key = it->first;
diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h
index 94c3813b4a2..12e04942c8c 100644
--- a/chromium/net/cookies/cookie_monster.h
+++ b/chromium/net/cookies/cookie_monster.h
@@ -24,7 +24,8 @@
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/cookies/canonical_cookie.h"
@@ -48,13 +49,8 @@ class ParsedCookie;
// optional permanent storage that implements the PersistentCookieStore
// interface.
//
-// This class IS thread-safe. Normally, it is only used on the I/O thread, but
-// is also accessed directly through Automation for UI testing.
-//
-// All cookie tasks are handled asynchronously. Tasks may be deferred if
-// all affected cookies are not yet loaded from the backing store. Otherwise,
-// the callback may be invoked immediately (prior to return of the asynchronous
-// function).
+// Tasks may be deferred if all affected cookies are not yet loaded from the
+// backing store. Otherwise, callbacks may be invoked immediately.
//
// A cookie task is either pending loading of the entire cookie store, or
// loading of cookies for a specfic domain key(eTLD+1). In the former case, the
@@ -63,8 +59,6 @@ class ParsedCookie;
// task will be queued in tasks_pending_for_key_ while PermanentCookieStore
// loads cookies for the specified domain key(eTLD+1) on DB thread.
//
-// Callbacks are guaranteed to be invoked on the calling thread.
-//
// TODO(deanm) Implement CookieMonster, the cookie database.
// - Verify that our domain enforcement and non-dotted handling is correct
class NET_EXPORT CookieMonster : public CookieStore {
@@ -148,148 +142,66 @@ class NET_EXPORT CookieMonster : public CookieStore {
CookieMonsterDelegate* delegate,
int last_access_threshold_milliseconds);
- // Helper function that adds all cookies from |list| into this instance,
- // overwriting any equivalent cookies.
- bool ImportCookies(const CookieList& list);
+ ~CookieMonster() override;
- typedef base::Callback<void(const CookieList& cookies)> GetCookieListCallback;
- typedef base::Callback<void(bool success)> DeleteCookieCallback;
+ // Replaces all the cookies by |list|. This method does not flush the backend.
+ void SetAllCookiesAsync(const CookieList& list,
+ const SetCookiesCallback& callback);
- // Sets a cookie given explicit user-provided cookie attributes. The cookie
- // name, value, domain, etc. are each provided as separate strings. This
- // function expects each attribute to be well-formed. It will check for
- // disallowed characters (e.g. the ';' character is disallowed within the
- // cookie value attribute) and will return false without setting the cookie
- // if such characters are found.
+ // CookieStore implementation.
+ void SetCookieWithOptionsAsync(const GURL& url,
+ const std::string& cookie_line,
+ const CookieOptions& options,
+ const SetCookiesCallback& callback) override;
void SetCookieWithDetailsAsync(const GURL& url,
const std::string& name,
const std::string& value,
const std::string& domain,
const std::string& path,
- const base::Time& expiration_time,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
bool secure,
bool http_only,
- bool first_party,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority,
- const SetCookiesCallback& callback);
-
- // Returns all the cookies, for use in management UI, etc. This does not mark
- // the cookies as having been accessed.
- // The returned cookies are ordered by longest path, then by earliest
- // creation date.
- void GetAllCookiesAsync(const GetCookieListCallback& callback);
-
- // Returns all the cookies, for use in management UI, etc. Filters results
- // using given url scheme, host / domain and path and options. This does not
- // mark the cookies as having been accessed.
- // The returned cookies are ordered by longest path, then earliest
- // creation date.
- void GetAllCookiesForURLWithOptionsAsync(
- const GURL& url,
- const CookieOptions& options,
- const GetCookieListCallback& callback);
-
- // Deletes all of the cookies.
- void DeleteAllAsync(const DeleteCallback& callback);
-
- // Deletes all cookies that match the host of the given URL
- // regardless of path. 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.
- void DeleteAllForHostAsync(const GURL& url, const DeleteCallback& callback);
-
- // Deletes one specific cookie.
- void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
- const DeleteCookieCallback& callback);
-
- // Resets the list of cookieable schemes to the supplied schemes. Does
- // nothing if called after first use of the instance (i.e. after the
- // instance initialization process).
- void SetCookieableSchemes(const char* const schemes[], size_t num_schemes);
-
- // Instructs the cookie monster to not delete expired cookies. This is used
- // in cases where the cookie monster is used as a data structure to keep
- // arbitrary cookies.
- void SetKeepExpiredCookies();
-
- // Protects session cookies from deletion on shutdown.
- void SetForceKeepSessionState();
-
- // Flush the backing store (if any) to disk and post the given callback when
- // done.
- // WARNING: THE CALLBACK WILL RUN ON A RANDOM THREAD. IT MUST BE THREAD SAFE.
- // It may be posted to the current thread, or it may run on the thread that
- // actually does the flushing. Your Task should generally post a notification
- // to the thread you actually want to be notified on.
- void FlushStore(const base::Closure& callback);
-
- // Replaces all the cookies by |list|. This method does not flush the backend.
- void SetAllCookiesAsync(const CookieList& list,
- const SetCookiesCallback& callback);
-
- // CookieStore implementation.
-
- // Sets the cookies specified by |cookie_list| returned from |url|
- // with options |options| in effect.
- void SetCookieWithOptionsAsync(const GURL& url,
- const std::string& cookie_line,
- const CookieOptions& options,
const SetCookiesCallback& callback) override;
-
- // Gets all cookies that apply to |url| given |options|.
- // The returned cookies are ordered by longest path, then earliest
- // creation date.
void GetCookiesWithOptionsAsync(const GURL& url,
const CookieOptions& options,
const GetCookiesCallback& callback) override;
-
- // Invokes GetAllCookiesForURLWithOptions with options set to include HTTP
- // only cookies.
- void GetAllCookiesForURLAsync(const GURL& url,
- const GetCookieListCallback& callback) override;
-
- // Deletes all cookies with that might apply to |url| that has |cookie_name|.
+ void GetCookieListWithOptionsAsync(
+ const GURL& url,
+ const CookieOptions& options,
+ const GetCookieListCallback& callback) override;
+ void GetAllCookiesAsync(const GetCookieListCallback& callback) override;
void DeleteCookieAsync(const GURL& url,
const std::string& cookie_name,
const base::Closure& callback) override;
-
- // 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.
+ void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+ const DeleteCallback& callback) override;
void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin,
const base::Time& delete_end,
const DeleteCallback& callback) override;
-
- // 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.
void DeleteAllCreatedBetweenForHostAsync(
const base::Time delete_begin,
const base::Time delete_end,
const GURL& url,
const DeleteCallback& callback) override;
-
void DeleteSessionCookiesAsync(const DeleteCallback&) override;
+ void FlushStore(const base::Closure& callback) override;
+ void SetForceKeepSessionState() override;
- CookieMonster* GetCookieMonster() override;
+ // Resets the list of cookieable schemes to the supplied schemes. Does
+ // nothing if called after first use of the instance (i.e. after the
+ // instance initialization process).
+ void SetCookieableSchemes(const std::vector<std::string>& schemes);
// Enables writing session cookies into the cookie database. If this this
// method is called, it must be called before first use of the instance
// (i.e. as part of the instance initialization process).
void SetPersistSessionCookies(bool persist_session_cookies);
- // Debugging method to perform various validation checks on the map.
- // Currently just checking that there are no null CanonicalCookie pointers
- // in the map.
- // Argument |arg| is to allow retaining of arbitrary data if the CHECKs
- // in the function trip. TODO(rdsmith):Remove hack.
- void ValidateMap(int arg);
-
// Determines if the scheme of the URL is a scheme that cookies will be
// stored for.
bool IsCookieableScheme(const std::string& scheme);
@@ -303,21 +215,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
const std::string& name,
const CookieChangedCallback& callback) override;
-#if defined(OS_ANDROID)
- // Resets the list of cookieable schemes to kDefaultCookieableSchemes with or
- // without 'file' being included.
- //
- // There are some unknowns about how to correctly handle file:// cookies,
- // and our implementation for this is not robust enough (Bug 1157243).
- // This allows you to enable support, and is exposed as a public WebView
- // API ('CookieManager::setAcceptFileSchemeCookies').
- //
- // TODO(mkwst): This method will be removed once we can deprecate and remove
- // the Android WebView 'CookieManager::setAcceptFileSchemeCookies' method.
- // Until then, this method only has effect on Android, and must not be used
- // outside a WebView context.
- void SetEnableFileScheme(bool accept);
-#endif
+ bool IsEphemeral() override;
private:
// For queueing the cookie monster calls.
@@ -326,13 +224,12 @@ class NET_EXPORT CookieMonster : public CookieStore {
class DeleteTask;
class DeleteAllCreatedBetweenTask;
class DeleteAllCreatedBetweenForHostTask;
- class DeleteAllForHostTask;
- class DeleteAllTask;
class DeleteCookieTask;
class DeleteCanonicalCookieTask;
- class GetAllCookiesForURLWithOptionsTask;
+ class GetCookieListForURLWithOptionsTask;
class GetAllCookiesTask;
class GetCookiesWithOptionsTask;
+ class GetCookieListWithOptionsTask;
class SetAllCookiesTask;
class SetCookieWithDetailsTask;
class SetCookieWithOptionsTask;
@@ -342,9 +239,6 @@ class NET_EXPORT CookieMonster : public CookieStore {
// For SetCookieWithCreationTime.
FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest,
TestCookieDeleteAllCreatedBetweenTimestamps);
- // For SetCookieWithCreationTime.
- FRIEND_TEST_ALL_PREFIXES(MultiThreadedCookieMonsterTest,
- ThreadCheckDeleteAllCreatedBetweenForHost);
// For gargage collection constants.
FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestHostGarbageCollection);
@@ -386,37 +280,37 @@ class NET_EXPORT CookieMonster : public CookieStore {
// at the end of the list, just before DELETE_COOKIE_LAST_ENTRY.
enum DeletionCause {
DELETE_COOKIE_EXPLICIT = 0,
- DELETE_COOKIE_OVERWRITE,
- DELETE_COOKIE_EXPIRED,
- DELETE_COOKIE_EVICTED,
- DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE,
- DELETE_COOKIE_DONT_RECORD, // e.g. For final cleanup after flush to store.
- DELETE_COOKIE_EVICTED_DOMAIN,
- DELETE_COOKIE_EVICTED_GLOBAL,
-
- // Cookies evicted during domain level garbage collection that
- // were accessed longer ago than kSafeFromGlobalPurgeDays
- DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE,
-
- // Cookies evicted during domain level garbage collection that
- // were accessed more recently than kSafeFromGlobalPurgeDays
- // (and thus would have been preserved by global garbage collection).
- DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE,
+ DELETE_COOKIE_OVERWRITE = 1,
+ DELETE_COOKIE_EXPIRED = 2,
+ DELETE_COOKIE_EVICTED = 3,
+ DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE = 4,
+ DELETE_COOKIE_DONT_RECORD = 5, // For final cleanup after flush to store.
+
+ // Cookies evicted during domain-level garbage collection.
+ DELETE_COOKIE_EVICTED_DOMAIN = 6,
+
+ // Cookies evicted during global garbage collection (which takes place after
+ // domain-level garbage collection fails to bring the cookie store under
+ // the overall quota.
+ DELETE_COOKIE_EVICTED_GLOBAL = 7,
+
+ // #8 was DELETE_COOKIE_EVICTED_DOMAIN_PRE_SAFE
+ // #9 was DELETE_COOKIE_EVICTED_DOMAIN_POST_SAFE
// A common idiom is to remove a cookie by overwriting it with an
// already-expired expiration date. This captures that case.
- DELETE_COOKIE_EXPIRED_OVERWRITE,
+ DELETE_COOKIE_EXPIRED_OVERWRITE = 10,
// Cookies are not allowed to contain control characters in the name or
// value. However, we used to allow them, so we are now evicting any such
// cookies as we load them. See http://crbug.com/238041.
- DELETE_COOKIE_CONTROL_CHAR,
+ DELETE_COOKIE_CONTROL_CHAR = 11,
// When strict secure cookies is enabled, non-secure cookies are evicted
// right after expired cookies.
- DELETE_COOKIE_NON_SECURE,
+ DELETE_COOKIE_NON_SECURE = 12,
- DELETE_COOKIE_LAST_ENTRY
+ DELETE_COOKIE_LAST_ENTRY = 13
};
// This enum is used to generate a histogramed bitmask measureing the types
@@ -424,7 +318,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
// New items MUST be added at the end of the list, just before
// COOKIE_TYPE_LAST_ENTRY;
enum CookieType {
- COOKIE_TYPE_FIRSTPARTYONLY = 0,
+ COOKIE_TYPE_SAME_SITE = 0,
COOKIE_TYPE_HTTPONLY,
COOKIE_TYPE_SECURE,
COOKIE_TYPE_LAST_ENTRY
@@ -487,8 +381,6 @@ class NET_EXPORT CookieMonster : public CookieStore {
// Record statistics every kRecordStatisticsIntervalSeconds of uptime.
static const int kRecordStatisticsIntervalSeconds = 10 * 60;
- ~CookieMonster() override;
-
// The following are synchronous calls to which the asynchronous methods
// delegate either immediately (if the store is loaded) or through a deferred
// task (if the store is not yet loaded).
@@ -497,31 +389,27 @@ class NET_EXPORT CookieMonster : public CookieStore {
const std::string& value,
const std::string& domain,
const std::string& path,
- const base::Time& expiration_time,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
bool secure,
bool http_only,
- bool first_party,
- bool enforce_prefixes,
+ CookieSameSite same_site,
bool enforce_strict_secure,
CookiePriority priority);
CookieList GetAllCookies();
- CookieList GetAllCookiesForURLWithOptions(const GURL& url,
- const CookieOptions& options);
-
- int DeleteAll(bool sync_to_store);
+ CookieList GetCookieListWithOptions(const GURL& url,
+ const CookieOptions& options);
int DeleteAllCreatedBetween(const base::Time& delete_begin,
const base::Time& delete_end);
- int DeleteAllForHost(const GURL& url);
int DeleteAllCreatedBetweenForHost(const base::Time delete_begin,
const base::Time delete_end,
const GURL& url);
- bool DeleteCanonicalCookie(const CanonicalCookie& cookie);
-
bool SetCookieWithOptions(const GURL& url,
const std::string& cookie_line,
const CookieOptions& options);
@@ -531,6 +419,8 @@ class NET_EXPORT CookieMonster : public CookieStore {
void DeleteCookie(const GURL& url, const std::string& cookie_name);
+ int DeleteCanonicalCookie(const CanonicalCookie& cookie);
+
bool SetCookieWithCreationTime(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time);
@@ -543,11 +433,9 @@ class NET_EXPORT CookieMonster : public CookieStore {
// Fetches all cookies if the backing store exists and they're not already
// being fetched.
- // Note: this method should always be called with lock_ held.
void FetchAllCookiesIfNecessary();
// Fetches all cookies from the backing store.
- // Note: this method should always be called with lock_ held.
void FetchAllCookies();
// Whether all cookies should be fetched as soon as any is requested.
@@ -588,14 +476,12 @@ class NET_EXPORT CookieMonster : public CookieStore {
void FindCookiesForHostAndDomain(const GURL& url,
const CookieOptions& options,
- bool update_access_time,
std::vector<CanonicalCookie*>* cookies);
void FindCookiesForKey(const std::string& key,
const GURL& url,
const CookieOptions& options,
const base::Time& current,
- bool update_access_time,
std::vector<CanonicalCookie*>* cookies);
// Delete any cookies that are equivalent to |ecc| (same path, domain, etc).
@@ -628,8 +514,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,
- const base::Time& creation_time,
+ bool SetCanonicalCookie(scoped_ptr<CanonicalCookie> cc,
const CookieOptions& options);
// Helper function calling SetCanonicalCookie() for all cookies in |list|.
@@ -656,6 +541,18 @@ class NET_EXPORT CookieMonster : public CookieStore {
const std::string& key,
bool enforce_strict_secure);
+ // 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.
+ //
+ // |cookies| must be sorted from least-recent to most-recent.
+ //
+ // Returns the number of cookies deleted.
+ size_t PurgeLeastRecentMatches(CookieItVector* cookies,
+ CookiePriority priority,
+ size_t to_protect,
+ size_t purge_goal);
+
// Helper for GarbageCollect(); can be called directly as well. Deletes all
// expired cookies in |itpair|. If |cookie_its| is non-NULL, all the
// non-expired cookies from |itpair| are appended to |cookie_its|.
@@ -727,9 +624,13 @@ class NET_EXPORT CookieMonster : public CookieStore {
CookieList* cookies_to_add,
CookieList* cookies_to_delete);
+ // Runs the given callback. Used to avoid running callbacks after the store
+ // has been destroyed.
+ void RunCallback(const base::Closure& callback);
+
// Run all cookie changed callbacks that are monitoring |cookie|.
// |removed| is true if the cookie was deleted.
- void RunCallbacks(const CanonicalCookie& cookie, bool removed);
+ void RunCookieChangedCallbacks(const CanonicalCookie& cookie, bool removed);
// Histogram variables; see CookieMonster::InitializeHistograms() in
// cookie_monster.cc for details.
@@ -765,7 +666,14 @@ class NET_EXPORT CookieMonster : public CookieStore {
// Queues tasks that are blocked until all cookies are loaded from the backend
// store.
- std::queue<scoped_refptr<CookieMonsterTask>> tasks_pending_;
+ std::deque<scoped_refptr<CookieMonsterTask>> tasks_pending_;
+
+ // Once a global cookie task has been seen, all per-key tasks must be put in
+ // |tasks_pending_| instead of |tasks_pending_for_key_| to ensure a reasonable
+ // view of the cookie store. This more to ensure fancy cookie export/import
+ // code has a consistent view of the CookieStore, rather than out of concern
+ // for typical use.
+ bool seen_global_task_;
scoped_refptr<PersistentCookieStore> store_;
@@ -796,23 +704,18 @@ class NET_EXPORT CookieMonster : public CookieStore {
scoped_refptr<CookieMonsterDelegate> delegate_;
- // Lock for thread-safety
- base::Lock lock_;
-
base::Time last_statistic_record_time_;
- bool keep_expired_cookies_;
bool persist_session_cookies_;
- // Static setting for whether or not file scheme cookies are allows when
- // a new CookieMonster is created, or the accepted schemes on a CookieMonster
- // instance are reset back to defaults.
- static bool default_enable_file_scheme_;
-
typedef std::map<std::pair<GURL, std::string>,
linked_ptr<CookieChangedCallbackList>> CookieChangedHookMap;
CookieChangedHookMap hook_map_;
+ base::ThreadChecker thread_checker_;
+
+ base::WeakPtrFactory<CookieMonster> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(CookieMonster);
};
@@ -869,6 +772,8 @@ class NET_EXPORT CookieMonster::PersistentCookieStore
// Initializes the store and retrieves the existing cookies. This will be
// called only once at startup. The callback will return all the cookies
// that are not yet returned to CookieMonster by previous priority loads.
+ //
+ // |loaded_callback| may not be NULL.
virtual void Load(const LoadedCallback& loaded_callback) = 0;
// Does a priority load of all cookies for the domain key (eTLD+1). The
@@ -876,6 +781,8 @@ class NET_EXPORT CookieMonster::PersistentCookieStore
// loads, which includes cookies for the requested domain key if they are not
// already returned, plus all cookies that are chain-loaded and not yet
// returned to CookieMonster.
+ //
+ // |loaded_callback| may not be NULL.
virtual void LoadCookiesForKey(const std::string& key,
const LoadedCallback& loaded_callback) = 0;
@@ -886,7 +793,8 @@ class NET_EXPORT CookieMonster::PersistentCookieStore
// Instructs the store to not discard session only cookies on shutdown.
virtual void SetForceKeepSessionState() = 0;
- // Flushes the store and posts |callback| when complete.
+ // Flushes the store and posts |callback| when complete. |callback| may be
+ // NULL.
virtual void Flush(const base::Closure& callback) = 0;
protected:
diff --git a/chromium/net/cookies/cookie_monster_perftest.cc b/chromium/net/cookies/cookie_monster_perftest.cc
index dd35638ead3..1dcb2769733 100644
--- a/chromium/net/cookies/cookie_monster_perftest.cc
+++ b/chromium/net/cookies/cookie_monster_perftest.cc
@@ -5,6 +5,8 @@
#include <algorithm>
#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"
@@ -119,7 +121,7 @@ TEST(ParsedCookieTest, TestParseBigCookies) {
}
TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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));
@@ -152,7 +154,7 @@ TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) {
}
TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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) {
@@ -185,7 +187,7 @@ TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) {
}
TEST_F(CookieMonsterTest, TestDomainTree) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
GetCookiesCallback getCookiesCallback;
SetCookieCallback setCookieCallback;
const char domain_cookie_format_tree[] = "a=b; domain=%s";
@@ -238,7 +240,7 @@ TEST_F(CookieMonsterTest, TestDomainTree) {
}
TEST_F(CookieMonsterTest, TestDomainLine) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
SetCookieCallback setCookieCallback;
GetCookiesCallback getCookiesCallback;
std::vector<std::string> domain_list;
@@ -287,8 +289,7 @@ TEST_F(CookieMonsterTest, TestImport) {
int64_t time_tick(base::Time::Now().ToInternalValue());
for (int domain_num = 0; domain_num < 300; domain_num++) {
- std::string domain_name(base::StringPrintf(".Domain_%d.com", domain_num));
- std::string gurl("www" + domain_name);
+ GURL gurl(base::StringPrintf("http://www.Domain_%d.com", domain_num));
for (int cookie_num = 0; cookie_num < 50; cookie_num++) {
std::string cookie_line(
base::StringPrintf("Cookie_%d=1; Path=/", cookie_num));
@@ -300,7 +301,7 @@ TEST_F(CookieMonsterTest, TestImport) {
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
// Import will happen on first access.
GURL gurl("www.google.com");
@@ -314,7 +315,7 @@ TEST_F(CookieMonsterTest, TestImport) {
}
TEST_F(CookieMonsterTest, TestGetKey) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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");
@@ -370,9 +371,9 @@ TEST_F(CookieMonsterTest, TestGCTimes) {
};
for (int ci = 0; ci < static_cast<int>(arraysize(test_cases)); ++ci) {
const TestCase& test_case(test_cases[ci]);
- scoped_refptr<CookieMonster> cm(CreateMonsterFromStoreForGC(
+ scoped_ptr<CookieMonster> cm = CreateMonsterFromStoreForGC(
test_case.num_cookies, test_case.num_old_cookies, 0, 0,
- CookieMonster::kSafeFromGlobalPurgeDays * 2));
+ CookieMonster::kSafeFromGlobalPurgeDays * 2);
GURL gurl("http://google.com");
std::string cookie_line("z=3");
diff --git a/chromium/net/cookies/cookie_monster_store_test.cc b/chromium/net/cookies/cookie_monster_store_test.cc
index 8c004ef6140..4573d4ad881 100644
--- a/chromium/net/cookies/cookie_monster_store_test.cc
+++ b/chromium/net/cookies/cookie_monster_store_test.cc
@@ -17,6 +17,7 @@
#include "url/gurl.h"
namespace net {
+
LoadedCallbackTask::LoadedCallbackTask(LoadedCallback loaded_callback,
std::vector<CanonicalCookie*> cookies)
: loaded_callback_(loaded_callback), cookies_(cookies) {
@@ -25,9 +26,22 @@ LoadedCallbackTask::LoadedCallbackTask(LoadedCallback loaded_callback,
LoadedCallbackTask::~LoadedCallbackTask() {
}
+CookieStoreCommand::CookieStoreCommand(
+ Type type,
+ const CookieMonster::PersistentCookieStore::LoadedCallback& loaded_callback,
+ const std::string& key)
+ : type(type), loaded_callback(loaded_callback), key(key) {}
+
+CookieStoreCommand::CookieStoreCommand(Type type, const CanonicalCookie& cookie)
+ : type(type), cookie(cookie) {}
+
+CookieStoreCommand::CookieStoreCommand(const CookieStoreCommand& other) =
+ default;
+
+CookieStoreCommand::~CookieStoreCommand() {}
+
MockPersistentCookieStore::MockPersistentCookieStore()
- : load_return_value_(true), loaded_(false) {
-}
+ : store_load_commands_(false), load_return_value_(true), loaded_(false) {}
void MockPersistentCookieStore::SetLoadExpectation(
bool return_value,
@@ -37,6 +51,11 @@ void MockPersistentCookieStore::SetLoadExpectation(
}
void MockPersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
+ if (store_load_commands_) {
+ commands_.push_back(
+ CookieStoreCommand(CookieStoreCommand::LOAD, loaded_callback, ""));
+ return;
+ }
std::vector<CanonicalCookie*> out_cookies;
if (load_return_value_) {
out_cookies = load_result_;
@@ -51,6 +70,11 @@ void MockPersistentCookieStore::Load(const LoadedCallback& loaded_callback) {
void MockPersistentCookieStore::LoadCookiesForKey(
const std::string& key,
const LoadedCallback& loaded_callback) {
+ if (store_load_commands_) {
+ commands_.push_back(CookieStoreCommand(
+ CookieStoreCommand::LOAD_COOKIES_FOR_KEY, loaded_callback, key));
+ return;
+ }
if (!loaded_) {
Load(loaded_callback);
} else {
@@ -68,8 +92,6 @@ void MockPersistentCookieStore::AddCookie(const CanonicalCookie& cookie) {
void MockPersistentCookieStore::UpdateCookieAccessTime(
const CanonicalCookie& cookie) {
- commands_.push_back(
- CookieStoreCommand(CookieStoreCommand::UPDATE_ACCESS_TIME, cookie));
}
void MockPersistentCookieStore::DeleteCookie(const CanonicalCookie& cookie) {
@@ -101,9 +123,10 @@ void MockCookieMonsterDelegate::OnCookieChanged(
MockCookieMonsterDelegate::~MockCookieMonsterDelegate() {
}
-CanonicalCookie BuildCanonicalCookie(const std::string& key,
- const std::string& cookie_line,
- const base::Time& creation_time) {
+scoped_ptr<CanonicalCookie> BuildCanonicalCookie(
+ const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time) {
// Parse the cookie line.
ParsedCookie pc(cookie_line);
EXPECT_TRUE(pc.IsValid());
@@ -118,18 +141,18 @@ CanonicalCookie BuildCanonicalCookie(const std::string& key,
: base::Time();
std::string cookie_path = pc.Path();
- return CanonicalCookie(GURL(), pc.Name(), pc.Value(), key, cookie_path,
- creation_time, cookie_expires, creation_time,
- pc.IsSecure(), pc.IsHttpOnly(), pc.IsFirstPartyOnly(),
- pc.Priority());
+ return CanonicalCookie::Create(url, pc.Name(), pc.Value(), url.host(),
+ cookie_path, creation_time, cookie_expires,
+ pc.IsSecure(), pc.IsHttpOnly(), pc.SameSite(),
+ false, pc.Priority());
}
-void AddCookieToList(const std::string& key,
+void AddCookieToList(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time,
std::vector<CanonicalCookie*>* out_list) {
- scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(
- BuildCanonicalCookie(key, cookie_line, creation_time)));
+ scoped_ptr<CanonicalCookie> cookie(
+ BuildCanonicalCookie(url, cookie_line, creation_time));
out_list->push_back(cookie.release());
}
@@ -196,11 +219,12 @@ void MockSimplePersistentCookieStore::Flush(const base::Closure& callback) {
void MockSimplePersistentCookieStore::SetForceKeepSessionState() {
}
-CookieMonster* CreateMonsterFromStoreForGC(int num_secure_cookies,
- int num_old_secure_cookies,
- int num_non_secure_cookies,
- int num_old_non_secure_cookies,
- int days_old) {
+scoped_ptr<CookieMonster> CreateMonsterFromStoreForGC(
+ int num_secure_cookies,
+ int num_old_secure_cookies,
+ int num_non_secure_cookies,
+ int num_old_non_secure_cookies,
+ int days_old) {
base::Time current(base::Time::Now());
base::Time past_creation(base::Time::Now() - base::TimeDelta::FromDays(1000));
scoped_refptr<MockSimplePersistentCookieStore> store(
@@ -229,12 +253,12 @@ CookieMonster* CreateMonsterFromStoreForGC(int num_secure_cookies,
CanonicalCookie cc(GURL(), "a", "1", base::StringPrintf("h%05d.izzle", i),
"/path", creation_time, expiration_time,
- last_access_time, secure, false, false,
- COOKIE_PRIORITY_DEFAULT);
+ last_access_time, secure, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT);
store->AddCookie(cc);
}
- return new CookieMonster(store.get(), NULL);
+ return make_scoped_ptr(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 686bb07afdb..aac83f82992 100644
--- a/chromium/net/cookies/cookie_monster_store_test.h
+++ b/chromium/net/cookies/cookie_monster_store_test.h
@@ -18,9 +18,12 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_monster.h"
+class GURL;
+
namespace base {
class Time;
}
@@ -50,18 +53,41 @@ class LoadedCallbackTask
DISALLOW_COPY_AND_ASSIGN(LoadedCallbackTask);
}; // Wrapper class LoadedCallbackTask
-// Describes a call to one of the 3 functions of PersistentCookieStore.
+// Describes a call to one of the 5 functions of PersistentCookieStore.
struct CookieStoreCommand {
enum Type {
+ LOAD,
+ LOAD_COOKIES_FOR_KEY,
+ // UPDATE_ACCESS_TIME is not included in this list, because get cookie
+ // commands may or may not end updating the access time, unless they have
+ // the option set not to do so.
ADD,
- UPDATE_ACCESS_TIME,
REMOVE,
};
- CookieStoreCommand(Type type, const CanonicalCookie& cookie)
- : type(type), cookie(cookie) {}
+ // Constructor for LOAD and LOAD_COOKIES_FOR_KEY calls. |key| should be empty
+ // for LOAD_COOKIES_FOR_KEY.
+ CookieStoreCommand(Type type,
+ const CookieMonster::PersistentCookieStore::LoadedCallback&
+ loaded_callback,
+ const std::string& key);
+
+ // Constructor for ADD, UPDATE_ACCESS_TIME, and REMOVE calls.
+ CookieStoreCommand(Type type, const CanonicalCookie& cookie);
+
+ CookieStoreCommand(const CookieStoreCommand& other);
+
+ ~CookieStoreCommand();
Type type;
+
+ // Only non-null for LOAD and LOAD_COOKIES_FOR_KEY.
+ CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback;
+
+ // Only non-empty for LOAD_COOKIES_FOR_KEY.
+ std::string key;
+
+ // Only non-null for ADD, UPDATE_ACCESS_TIME, and REMOVE.
CanonicalCookie cookie;
};
@@ -74,6 +100,12 @@ class MockPersistentCookieStore : public CookieMonster::PersistentCookieStore {
MockPersistentCookieStore();
+ // When set, Load() and LoadCookiesForKey() calls are store in the command
+ // list, rather than being automatically executed. Defaults to false.
+ void set_store_load_commands(bool store_load_commands) {
+ store_load_commands_ = store_load_commands;
+ }
+
void SetLoadExpectation(bool return_value,
const std::vector<CanonicalCookie*>& result);
@@ -100,6 +132,8 @@ class MockPersistentCookieStore : public CookieMonster::PersistentCookieStore {
private:
CommandList commands_;
+ bool store_load_commands_;
+
// Deferred result to use when Load() is called.
bool load_return_value_;
std::vector<CanonicalCookie*> load_result_;
@@ -134,12 +168,13 @@ class MockCookieMonsterDelegate : public CookieMonsterDelegate {
};
// Helper to build a single CanonicalCookie.
-CanonicalCookie BuildCanonicalCookie(const std::string& key,
- const std::string& cookie_line,
- const base::Time& creation_time);
+scoped_ptr<CanonicalCookie> BuildCanonicalCookie(
+ const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& creation_time);
// Helper to build a list of CanonicalCookie*s.
-void AddCookieToList(const std::string& key,
+void AddCookieToList(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time,
std::vector<CanonicalCookie*>* out_list);
@@ -188,11 +223,12 @@ 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.
-CookieMonster* CreateMonsterFromStoreForGC(int num_secure_cookies,
- int num_old_secure_cookies,
- int num_non_secure_cookies,
- int num_old_non_secure_cookies,
- int days_old);
+scoped_ptr<CookieMonster> CreateMonsterFromStoreForGC(
+ int num_secure_cookies,
+ int num_old_secure_cookies,
+ int num_non_secure_cookies,
+ int num_old_non_secure_cookies,
+ int days_old);
} // namespace net
diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc
index efeadd96d58..45c3063b70c 100644
--- a/chromium/net/cookies/cookie_monster_unittest.cc
+++ b/chromium/net/cookies/cookie_monster_unittest.cc
@@ -70,29 +70,11 @@ const char kTopLevelDomainPlus2Secure[] = "https://www.math.harvard.edu";
const char kTopLevelDomainPlus3[] = "http://www.bourbaki.math.harvard.edu";
const char kOtherDomain[] = "http://www.mit.edu";
-class GetCookieListCallback : public CookieCallback {
- public:
- GetCookieListCallback() {}
- explicit GetCookieListCallback(Thread* run_in_thread)
- : CookieCallback(run_in_thread) {}
-
- void Run(const CookieList& cookies) {
- cookies_ = cookies;
- CallbackEpilogue();
- }
-
- const CookieList& cookies() { return cookies_; }
-
- private:
- CookieList cookies_;
-};
-
struct CookieMonsterTestTraits {
- static scoped_refptr<CookieStore> Create() {
- return new CookieMonster(NULL, NULL);
+ static scoped_ptr<CookieStore> Create() {
+ return make_scoped_ptr(new CookieMonster(nullptr, nullptr));
}
- static const bool is_cookie_monster = true;
static const bool supports_http_only = true;
static const bool supports_non_dotted_domains = true;
static const bool preserves_trailing_dots = true;
@@ -103,11 +85,10 @@ struct CookieMonsterTestTraits {
};
struct CookieMonsterEnforcingStrictSecure {
- static scoped_refptr<CookieStore> Create() {
- return new CookieMonster(NULL, NULL);
+ static scoped_ptr<CookieStore> Create() {
+ return make_scoped_ptr(new CookieMonster(nullptr, nullptr));
}
- static const bool is_cookie_monster = true;
static const bool supports_http_only = true;
static const bool supports_non_dotted_domains = true;
static const bool preserves_trailing_dots = true;
@@ -121,10 +102,6 @@ INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster,
CookieStoreTest,
CookieMonsterTestTraits);
-INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster,
- MultiThreadedCookieStoreTest,
- CookieMonsterTestTraits);
-
INSTANTIATE_TYPED_TEST_CASE_P(CookieMonsterStrictSecure,
CookieStoreTest,
CookieMonsterEnforcingStrictSecure);
@@ -132,88 +109,31 @@ INSTANTIATE_TYPED_TEST_CASE_P(CookieMonsterStrictSecure,
template <typename T>
class CookieMonsterTestBase : public CookieStoreTest<T> {
public:
- using CookieStoreTest<T>::RunFor;
using CookieStoreTest<T>::SetCookie;
protected:
using CookieStoreTest<T>::http_www_google_;
using CookieStoreTest<T>::https_www_google_;
- CookieList GetAllCookies(CookieMonster* cm) {
- DCHECK(cm);
- GetCookieListCallback callback;
- cm->GetAllCookiesAsync(
- base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.cookies();
- }
-
- CookieList GetAllCookiesForURL(CookieMonster* cm, const GURL& url) {
- DCHECK(cm);
- GetCookieListCallback callback;
- cm->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.cookies();
- }
-
CookieList GetAllCookiesForURLWithOptions(CookieMonster* cm,
const GURL& url,
const CookieOptions& options) {
DCHECK(cm);
GetCookieListCallback callback;
- cm->GetAllCookiesForURLWithOptionsAsync(
+ cm->GetCookieListWithOptionsAsync(
url, options,
base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.cookies();
}
- bool SetCookieWithDetails(CookieMonster* cm,
- const GURL& url,
- const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- const base::Time& expiration_time,
- bool secure,
- bool http_only,
- bool first_party_only,
- CookiePriority priority) {
- DCHECK(cm);
- ResultSavingCookieCallback<bool> callback;
- cm->SetCookieWithDetailsAsync(
- url, name, value, domain, path, expiration_time, secure, http_only,
- first_party_only, false /* enforce prefixes */,
- false /* enforces strict secure cookies */, priority,
- base::Bind(&ResultSavingCookieCallback<bool>::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
- }
-
bool SetAllCookies(CookieMonster* cm, const CookieList& list) {
DCHECK(cm);
ResultSavingCookieCallback<bool> callback;
cm->SetAllCookiesAsync(list,
base::Bind(&ResultSavingCookieCallback<bool>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
- }
-
- int DeleteAll(CookieMonster* cm) {
- DCHECK(cm);
- ResultSavingCookieCallback<int> callback;
- cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
@@ -226,8 +146,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
delete_begin, delete_end,
base::Bind(&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
@@ -241,120 +160,102 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
delete_begin, delete_end, url,
base::Bind(&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
- }
-
- int DeleteAllForHost(CookieMonster* cm, const GURL& url) {
- DCHECK(cm);
- ResultSavingCookieCallback<int> callback;
- cm->DeleteAllForHostAsync(url,
- base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
- }
-
- bool DeleteCanonicalCookie(CookieMonster* cm, const CanonicalCookie& cookie) {
- DCHECK(cm);
- ResultSavingCookieCallback<bool> callback;
- cm->DeleteCanonicalCookieAsync(
- cookie, base::Bind(&ResultSavingCookieCallback<bool>::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
// Helper for DeleteAllForHost test; repopulates CM with same layout
// each time.
- void PopulateCmForDeleteAllForHost(scoped_refptr<CookieMonster> cm) {
+ void PopulateCmForDeleteAllForHost(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);
GURL url_top_level_domain_plus_3(kTopLevelDomainPlus3);
GURL url_other(kOtherDomain);
- DeleteAll(cm.get());
+ this->DeleteAll(cm);
// Static population for probe:
// * Three levels of domain cookie (.b.a, .c.b.a, .d.c.b.a)
// * Three levels of host cookie (w.b.a, w.c.b.a, w.d.c.b.a)
// * http_only cookie (w.c.b.a)
- // * first-party cookie (w.c.b.a)
+ // * same_site cookie (w.c.b.a)
// * Two secure cookies (.c.b.a, w.c.b.a)
// * Two domain path cookies (.c.b.a/dir1, .c.b.a/dir1/dir2)
// * Two host path cookies (w.c.b.a/dir1, w.c.b.a/dir1/dir2)
// Domain cookies
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_1, "dom_1", "X", ".harvard.edu",
- "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_1, "dom_1", "X", ".harvard.edu", "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "dom_2", "X",
- ".math.harvard.edu", "/", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "dom_2", "X", ".math.harvard.edu", "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_3, "dom_3", "X",
- ".bourbaki.math.harvard.edu", "/", base::Time(), false, false, false,
+ cm, url_top_level_domain_plus_3, "dom_3", "X",
+ ".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.get(), url_top_level_domain_plus_1, "host_1", "X", std::string(),
- "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_1, "host_1", "X", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "host_2", "X", std::string(),
- "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "host_2", "X", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_3, "host_3", "X", std::string(),
- "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_3, "host_3", "X", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// http_only cookie
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "httpo_check", "x",
- std::string(), "/", base::Time(), false, true, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "httpo_check", "x", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), false, true,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
- // first-party cookie
+ // same-site cookie
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "firstp_check", "x",
- std::string(), "/", base::Time(), false, false, true,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "firstp_check", "x", std::string(),
+ "/", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT));
// Secure cookies
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2_secure, "sec_dom", "X",
- ".math.harvard.edu", "/", base::Time(), true, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2_secure, "sec_dom", "X",
+ ".math.harvard.edu", "/", base::Time(), base::Time(), base::Time(),
+ true, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2_secure, "sec_host", "X",
- std::string(), "/", base::Time(), true, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2_secure, "sec_host", "X", std::string(),
+ "/", base::Time(), base::Time(), base::Time(), true, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Domain path cookies
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "dom_path_1", "X",
- ".math.harvard.edu", "/dir1", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "dom_path_1", "X", ".math.harvard.edu",
+ "/dir1", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "dom_path_2", "X",
- ".math.harvard.edu", "/dir1/dir2", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "dom_path_2", "X", ".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.get(), url_top_level_domain_plus_2, "host_path_1", "X",
- std::string(), "/dir1", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "host_path_1", "X", std::string(),
+ "/dir1", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(this->SetCookieWithDetails(
- cm.get(), url_top_level_domain_plus_2, "host_path_2", "X",
- std::string(), "/dir1/dir2", base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ cm, url_top_level_domain_plus_2, "host_path_2", "X", std::string(),
+ "/dir1/dir2", base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
- EXPECT_EQ(14U, this->GetAllCookies(cm.get()).size());
+ EXPECT_EQ(14U, this->GetAllCookies(cm).size());
}
Time GetFirstCookieAccessDate(CookieMonster* cm) {
@@ -383,7 +284,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_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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));
@@ -401,7 +302,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_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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(
@@ -461,7 +362,8 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
size_t expected_low_count,
size_t expected_medium_count,
size_t expected_high_count) {
- DeleteAll(cm);
+ 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.
@@ -472,7 +374,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
base::SPLIT_WANT_ALL)) {
DCHECK(!token.empty());
// Take last character as priority.
- CookiePriority priority = CharToPriority(token[token.length() - 1]);
+ CookiePriority priority = CharToPriority(token.back());
std::string priority_str = CookiePriorityToString(priority);
// The rest of the string (possibly empty) specifies repetition.
int rep = 1;
@@ -544,10 +446,10 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
size_t expected_secure_cookies,
size_t expected_non_secure_cookies,
const AltHosts* alt_host_entries) {
- scoped_refptr<CookieMonster> cm;
+ scoped_ptr<CookieMonster> cm;
if (alt_host_entries == nullptr) {
- cm = new CookieMonster(nullptr, nullptr);
+ cm.reset(new CookieMonster(nullptr, nullptr));
} else {
// When generating all of these cookies on alternate hosts, they need to
// be all older than the max "safe" date for GC, which is currently 30
@@ -595,7 +497,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
DCHECK_EQ(50U, CookieMonster::kDomainCookiesQuotaMedium);
DCHECK_EQ(70U, CookieMonster::kDomainCookiesQuotaHigh);
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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.
@@ -712,13 +614,6 @@ class MockDeleteCallback
MOCK_METHOD1(Invoke, void(int num_deleted));
};
-class MockDeleteCookieCallback
- : public MockCookieCallback<MockDeleteCookieCallback,
- CookieMonster::DeleteCookieCallback> {
- public:
- MOCK_METHOD1(Invoke, void(bool success));
-};
-
struct CookiesInputInfo {
const GURL url;
const std::string name;
@@ -728,13 +623,12 @@ struct CookiesInputInfo {
const base::Time expiration_time;
bool secure;
bool http_only;
- bool first_party_only;
+ CookieSameSite same_site;
CookiePriority priority;
};
-ACTION(QuitCurrentMessageLoop) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
+ACTION_P(QuitRunLoop, run_loop) {
+ run_loop->Quit();
}
// TODO(erikwright): When the synchronous helpers 'GetCookies' etc. are removed,
@@ -763,18 +657,24 @@ ACTION_P4(DeleteAllCreatedBetweenAction,
}
ACTION_P3(SetCookieWithDetailsAction, cookie_monster, cc, callback) {
cookie_monster->SetCookieWithDetailsAsync(
- cc.url, cc.name, cc.value, cc.domain, cc.path, cc.expiration_time,
- cc.secure, cc.http_only, cc.first_party_only,
- false /* enforce prefixes */, false /* enforces strict secure cookies */,
- cc.priority, callback->AsCallback());
+ cc.url, cc.name, cc.value, cc.domain, cc.path, base::Time(),
+ cc.expiration_time, base::Time(), cc.secure, cc.http_only, cc.same_site,
+ false /* enforces strict secure cookies */, cc.priority,
+ callback->AsCallback());
}
ACTION_P2(GetAllCookiesAction, cookie_monster, callback) {
cookie_monster->GetAllCookiesAsync(callback->AsCallback());
}
-ACTION_P3(DeleteAllForHostAction, cookie_monster, url, callback) {
- cookie_monster->DeleteAllForHostAsync(url, callback->AsCallback());
+ACTION_P5(DeleteAllCreatedBetweenForHostAction,
+ cookie_monster,
+ delete_begin,
+ delete_end,
+ url,
+ callback) {
+ cookie_monster->DeleteAllCreatedBetweenForHostAsync(
+ delete_begin, delete_end, url, callback->AsCallback());
}
ACTION_P3(DeleteCanonicalCookieAction, cookie_monster, cookie, callback) {
@@ -785,9 +685,9 @@ ACTION_P2(DeleteAllAction, cookie_monster, callback) {
cookie_monster->DeleteAllAsync(callback->AsCallback());
}
-ACTION_P3(GetAllCookiesForUrlWithOptionsAction, cookie_monster, url, callback) {
- cookie_monster->GetAllCookiesForURLWithOptionsAsync(url, CookieOptions(),
- callback->AsCallback());
+ACTION_P3(GetCookieListForUrlWithOptionsAction, cookie_monster, url, callback) {
+ cookie_monster->GetCookieListWithOptionsAsync(url, CookieOptions(),
+ callback->AsCallback());
}
ACTION_P3(GetAllCookiesForUrlAction, cookie_monster, url, callback) {
@@ -813,39 +713,36 @@ ACTION_P2(DeleteSessionCookiesAction, cookie_monster, callback) {
// 3. Invocations after the loading has completed complete immediately.
class DeferredCookieTaskTest : public CookieMonsterTest {
protected:
- DeferredCookieTaskTest() {
+ DeferredCookieTaskTest() : expect_load_called_(false) {
persistent_store_ = new NewMockPersistentCookieStore();
- cookie_monster_ = new CookieMonster(persistent_store_.get(), NULL);
+ cookie_monster_.reset(new CookieMonster(persistent_store_.get(), nullptr));
}
// Defines a cookie to be returned from PersistentCookieStore::Load
- void DeclareLoadedCookie(const std::string& key,
+ void DeclareLoadedCookie(const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time) {
- AddCookieToList(key, cookie_line, creation_time, &loaded_cookies_);
+ AddCookieToList(url, cookie_line, creation_time, &loaded_cookies_);
}
// Runs the message loop, waiting until PersistentCookieStore::Load is called.
- // Call CompleteLoadingAndWait to cause the load to complete.
+ // Call CompleteLoading to cause the load to complete.
void WaitForLoadCall() {
- RunFor(kTimeout);
+ load_run_loop_.Run();
// Verify that PeristentStore::Load was called.
testing::Mock::VerifyAndClear(persistent_store_.get());
}
// Invokes the PersistentCookieStore::LoadCookiesForKey completion callbacks
- // and PersistentCookieStore::Load completion callback and waits
- // until the message loop is quit.
- void CompleteLoadingAndWait() {
+ // and PersistentCookieStore::Load completion callback.
+ void CompleteLoading() {
while (!loaded_for_key_callbacks_.empty()) {
loaded_for_key_callbacks_.front().Run(loaded_cookies_);
loaded_cookies_.clear();
loaded_for_key_callbacks_.pop();
}
-
loaded_callback_.Run(loaded_cookies_);
- RunFor(kTimeout);
}
// Performs the provided action, expecting it to cause a call to
@@ -861,30 +758,26 @@ class DeferredCookieTaskTest : public CookieMonsterTest {
testing::Action<void(void)> action) {
EXPECT_CALL(*this, Begin()).WillOnce(action);
ExpectLoadCall();
- ExpectLoadForKeyCall(key, false);
+ ExpectLoadForKeyCall(key);
Begin();
}
// Declares an expectation that PersistentCookieStore::Load will be called,
- // saving the provided callback and sending a quit to the message loop.
+ // saving the provided callback and sending a quit to |load_run_loop_|.
void ExpectLoadCall() {
+ // Make sure the |load_run_loop_| is not reused.
+ CHECK(!expect_load_called_);
+ expect_load_called_ = true;
EXPECT_CALL(*persistent_store_.get(), Load(testing::_))
.WillOnce(testing::DoAll(testing::SaveArg<0>(&loaded_callback_),
- QuitCurrentMessageLoop()));
+ QuitRunLoop(&load_run_loop_)));
}
// Declares an expectation that PersistentCookieStore::LoadCookiesForKey
- // will be called, saving the provided callback and sending a quit to the
- // message loop.
- void ExpectLoadForKeyCall(const std::string& key, bool quit_queue) {
- if (quit_queue)
- EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
- .WillOnce(
- testing::DoAll(PushCallbackAction(&loaded_for_key_callbacks_),
- QuitCurrentMessageLoop()));
- else
- EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
- .WillOnce(PushCallbackAction(&loaded_for_key_callbacks_));
+ // will be called, saving the provided callback.
+ void ExpectLoadForKeyCall(const std::string& key) {
+ EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
+ .WillOnce(PushCallbackAction(&loaded_for_key_callbacks_));
}
// Invokes the initial action.
@@ -906,15 +799,18 @@ class DeferredCookieTaskTest : public CookieMonsterTest {
// PersistentCookieStore::LoadCookiesForKey
std::queue<CookieMonster::PersistentCookieStore::LoadedCallback>
loaded_for_key_callbacks_;
-
+ // base::RunLoop used to wait for PersistentCookieStore::Load to be called.
+ base::RunLoop load_run_loop_;
+ // Indicates whether ExpectLoadCall() has been called.
+ bool expect_load_called_;
// Stores the CookieMonster under test.
- scoped_refptr<CookieMonster> cookie_monster_;
+ scoped_ptr<CookieMonster> cookie_monster_;
// Stores the mock PersistentCookieStore.
scoped_refptr<NewMockPersistentCookieStore> persistent_store_;
};
TEST_F(DeferredCookieTaskTest, DeferredGetCookies) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
@@ -930,10 +826,11 @@ TEST_F(DeferredCookieTaskTest, DeferredGetCookies) {
EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
.WillOnce(GetCookiesAction(&cookie_monster(), http_www_google_.url(),
&get_cookies_callback));
- EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(get_cookies_callback, Invoke("X=1")).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
@@ -949,23 +846,24 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
EXPECT_CALL(set_cookies_callback, Invoke(true))
.WillOnce(SetCookieAction(&cookie_monster(), http_www_google_.url(),
"X=Y", &set_cookies_callback));
- EXPECT_CALL(set_cookies_callback, Invoke(true))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) {
MockSetCookiesCallback set_cookies_callback;
CookieList list;
- list.push_back(CanonicalCookie(http_www_google_.url(), "A", "B",
- http_www_google_.domain(), "/",
- base::Time::Now(), base::Time(), base::Time(),
- false, true, false, COOKIE_PRIORITY_DEFAULT));
- list.push_back(CanonicalCookie(http_www_google_.url(), "C", "D",
- http_www_google_.domain(), "/",
- base::Time::Now(), base::Time(), base::Time(),
- false, true, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "A", "B", http_www_google_.domain(), "/",
+ base::Time::Now(), base::Time(), false, true,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "C", "D", http_www_google_.domain(), "/",
+ base::Time::Now(), base::Time(), false, true,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
BeginWith(
SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
@@ -975,10 +873,11 @@ TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) {
EXPECT_CALL(set_cookies_callback, Invoke(true))
.WillOnce(
SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
- EXPECT_CALL(set_cookies_callback, Invoke(true))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteCookie) {
@@ -994,10 +893,11 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteCookie) {
EXPECT_CALL(delete_cookie_callback, Invoke())
.WillOnce(DeleteCookieAction(&cookie_monster(), http_www_google_.url(),
"X", &delete_cookie_callback));
- EXPECT_CALL(delete_cookie_callback, Invoke())
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(delete_cookie_callback, Invoke()).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
@@ -1011,7 +911,7 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
base::Time(),
false,
false,
- false,
+ CookieSameSite::DEFAULT_MODE,
COOKIE_PRIORITY_DEFAULT};
BeginWithForDomainKey(
http_www_google_.domain(),
@@ -1028,19 +928,20 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
base::Time(),
false,
false,
- false,
+ CookieSameSite::DEFAULT_MODE,
COOKIE_PRIORITY_DEFAULT};
EXPECT_CALL(set_cookies_callback, Invoke(true))
.WillOnce(SetCookieWithDetailsAction(&cookie_monster(), cookie_info_exp,
&set_cookies_callback));
- EXPECT_CALL(set_cookies_callback, Invoke(true))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
@@ -1053,14 +954,16 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) {
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
.WillOnce(
GetAllCookiesAction(&cookie_monster(), &get_cookie_list_callback));
+ base::RunLoop loop;
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
@@ -1077,34 +980,38 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) {
.WillOnce(GetAllCookiesForUrlAction(&cookie_monster(),
http_www_google_.url(),
&get_cookie_list_callback));
+ base::RunLoop loop;
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
MockGetCookieListCallback get_cookie_list_callback;
BeginWithForDomainKey(http_www_google_.domain(),
- GetAllCookiesForUrlWithOptionsAction(
+ GetCookieListForUrlWithOptionsAction(
&cookie_monster(), http_www_google_.url(),
&get_cookie_list_callback));
WaitForLoadCall();
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
- .WillOnce(GetAllCookiesForUrlWithOptionsAction(
+ .WillOnce(GetCookieListForUrlWithOptionsAction(
&cookie_monster(), http_www_google_.url(),
&get_cookie_list_callback));
+ base::RunLoop loop;
EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) {
@@ -1116,10 +1023,12 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) {
EXPECT_CALL(delete_callback, Invoke(false))
.WillOnce(DeleteAllAction(&cookie_monster(), &delete_callback));
- EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
- CompleteLoadingAndWait();
+ base::RunLoop loop;
+ EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
+
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedBetweenCookies) {
@@ -1134,50 +1043,54 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedBetweenCookies) {
.WillOnce(DeleteAllCreatedBetweenAction(&cookie_monster(), base::Time(),
base::Time::Now(),
&delete_callback));
- EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
-TEST_F(DeferredCookieTaskTest, DeferredDeleteAllForHostCookies) {
+TEST_F(DeferredCookieTaskTest, DeferredDeleteAllForHostCreatedBetweenCookies) {
MockDeleteCallback delete_callback;
- BeginWithForDomainKey(
- http_www_google_.domain(),
- DeleteAllForHostAction(&cookie_monster(), http_www_google_.url(),
- &delete_callback));
+ BeginWithForDomainKey(http_www_google_.domain(),
+ DeleteAllCreatedBetweenForHostAction(
+ &cookie_monster(), base::Time(), base::Time::Now(),
+ http_www_google_.url(), &delete_callback));
WaitForLoadCall();
EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(DeleteAllForHostAction(
- &cookie_monster(), http_www_google_.url(), &delete_callback));
- EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(DeleteAllCreatedBetweenForHostAction(
+ &cookie_monster(), base::Time(), base::Time::Now(),
+ http_www_google_.url(), &delete_callback));
+ base::RunLoop loop;
+ EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) {
std::vector<CanonicalCookie*> cookies;
- CanonicalCookie cookie = BuildCanonicalCookie(
- http_www_google_.host(), "X=1; path=/", base::Time::Now());
+ scoped_ptr<CanonicalCookie> cookie = BuildCanonicalCookie(
+ http_www_google_.url(), "X=1; path=/", base::Time::Now());
- MockDeleteCookieCallback delete_cookie_callback;
+ MockDeleteCallback delete_cookie_callback;
- BeginWith(DeleteCanonicalCookieAction(&cookie_monster(), cookie,
+ BeginWith(DeleteCanonicalCookieAction(&cookie_monster(), *cookie,
&delete_cookie_callback));
WaitForLoadCall();
- EXPECT_CALL(delete_cookie_callback, Invoke(false))
- .WillOnce(DeleteCanonicalCookieAction(&cookie_monster(), cookie,
+ EXPECT_CALL(delete_cookie_callback, Invoke(0))
+ .WillOnce(DeleteCanonicalCookieAction(&cookie_monster(), *cookie,
&delete_cookie_callback));
- EXPECT_CALL(delete_cookie_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(delete_cookie_callback, Invoke(0)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) {
@@ -1190,17 +1103,18 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) {
EXPECT_CALL(delete_callback, Invoke(false))
.WillOnce(
DeleteSessionCookiesAction(&cookie_monster(), &delete_callback));
- EXPECT_CALL(delete_callback, Invoke(false))
- .WillOnce(QuitCurrentMessageLoop());
+ base::RunLoop loop;
+ EXPECT_CALL(delete_callback, Invoke(false)).WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
// Verify that a series of queued tasks are executed in order upon loading of
// the backing store and that new tasks received while the queued tasks are
// being dispatched go to the end of the queue.
TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
- DeclareLoadedCookie(http_www_google_.host(),
+ DeclareLoadedCookie(http_www_google_.url(),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3));
@@ -1215,7 +1129,7 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
SetCookieAction(&cookie_monster(), http_www_google_.url(), "A=B",
&set_cookies_callback)));
ExpectLoadCall();
- ExpectLoadForKeyCall(http_www_google_.domain(), false);
+ ExpectLoadForKeyCall(http_www_google_.domain());
Begin();
WaitForLoadCall();
@@ -1223,15 +1137,17 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
.WillOnce(GetCookiesAction(&cookie_monster(), http_www_google_.url(),
&get_cookies_callback_deferred));
EXPECT_CALL(set_cookies_callback, Invoke(true));
+ base::RunLoop loop;
EXPECT_CALL(get_cookies_callback_deferred, Invoke("A=B; X=1"))
- .WillOnce(QuitCurrentMessageLoop());
+ .WillOnce(QuitRunLoop(&loop));
- CompleteLoadingAndWait();
+ CompleteLoading();
+ loop.Run();
}
TEST_F(CookieMonsterTest, TestCookieDeleteAll) {
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
CookieOptions options;
options.set_include_httponly();
@@ -1264,7 +1180,7 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAll) {
}
TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
Time now = Time::Now();
// Nothing has been added so nothing should be deleted.
@@ -1306,8 +1222,8 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
static const int kAccessDelayMs = kLastAccessThresholdMilliseconds + 20;
TEST_F(CookieMonsterTest, TestLastAccess) {
- scoped_refptr<CookieMonster> cm(
- new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
+ scoped_ptr<CookieMonster> cm(
+ new CookieMonster(nullptr, nullptr, kLastAccessThresholdMilliseconds));
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
const Time last_access_date(GetFirstCookieAccessDate(cm.get()));
@@ -1315,12 +1231,33 @@ TEST_F(CookieMonsterTest, TestLastAccess) {
// Reading the cookie again immediately shouldn't update the access date,
// since we're inside the threshold.
EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_google_.url()));
- EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm.get()));
+ EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
- // Reading after a short wait should update the access date.
+ // Reading after a short wait will update the access date, if the cookie
+ // is requested with options that would update the access date. First, test
+ // that the flag's behavior is respected.
base::PlatformThread::Sleep(
base::TimeDelta::FromMilliseconds(kAccessDelayMs));
- EXPECT_EQ("A=B", GetCookies(cm.get(), http_www_google_.url()));
+ CookieOptions options;
+ options.set_do_not_update_access_time();
+ EXPECT_EQ("A=B",
+ GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
+ EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
+
+ // Getting all cookies for a URL doesn't update the accessed time either.
+ CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_google_.url());
+ CookieList::iterator it = cookies.begin();
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ(http_www_google_.host(), it->Domain());
+ EXPECT_EQ("A", it->Name());
+ EXPECT_EQ("B", it->Value());
+ EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
+ EXPECT_TRUE(++it == cookies.end());
+
+ // If the flag isn't set, the last accessed time should be updated.
+ options = CookieOptions();
+ EXPECT_EQ("A=B",
+ GetCookiesWithOptions(cm.get(), http_www_google_.url(), options));
EXPECT_FALSE(last_access_date == GetFirstCookieAccessDate(cm.get()));
}
@@ -1332,29 +1269,14 @@ TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollection) {
TestPriorityAwareGarbageCollectHelper();
}
-TEST_F(CookieMonsterTest, TestDeleteSingleCookie) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
-
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "C=D"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "E=F"));
- EXPECT_EQ("A=B; C=D; E=F", GetCookies(cm.get(), http_www_google_.url()));
-
- EXPECT_TRUE(
- FindAndDeleteCookie(cm.get(), http_www_google_.url().host(), "C"));
- EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), http_www_google_.url()));
-
- EXPECT_FALSE(FindAndDeleteCookie(cm.get(), "random.host", "E"));
- EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), http_www_google_.url()));
-}
-
TEST_F(CookieMonsterTest, SetCookieableSchemes) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- scoped_refptr<CookieMonster> cm_foo(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
+ scoped_ptr<CookieMonster> cm_foo(new CookieMonster(nullptr, nullptr));
// Only cm_foo should allow foo:// cookies.
- const char* const kSchemes[] = {"foo"};
- cm_foo->SetCookieableSchemes(kSchemes, 1);
+ std::vector<std::string> schemes;
+ schemes.push_back("foo");
+ cm_foo->SetCookieableSchemes(schemes);
GURL foo_url("foo://host/path");
GURL http_url("http://host/path");
@@ -1366,8 +1288,8 @@ TEST_F(CookieMonsterTest, SetCookieableSchemes) {
}
TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
- scoped_refptr<CookieMonster> cm(
- new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
+ scoped_ptr<CookieMonster> cm(
+ new CookieMonster(nullptr, nullptr, kLastAccessThresholdMilliseconds));
// Create an httponly cookie.
CookieOptions options;
@@ -1431,11 +1353,11 @@ TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
ASSERT_TRUE(++it == cookies.end());
// Reading after a short wait should not update the access date.
- EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm.get()));
+ EXPECT_EQ(last_access_date, GetFirstCookieAccessDate(cm.get()));
}
TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
CookieOptions options;
EXPECT_TRUE(SetCookieWithOptions(cm.get(), www_google_foo_.url(),
@@ -1473,7 +1395,7 @@ TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
}
TEST_F(CookieMonsterTest, CookieSorting) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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"));
@@ -1503,7 +1425,7 @@ TEST_F(CookieMonsterTest, CookieSorting) {
}
TEST_F(CookieMonsterTest, DeleteCookieByName) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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"));
@@ -1523,40 +1445,6 @@ TEST_F(CookieMonsterTest, DeleteCookieByName) {
}
}
-TEST_F(CookieMonsterTest, ImportCookiesFromCookieMonster) {
- scoped_refptr<CookieMonster> cm_1(new CookieMonster(NULL, NULL));
- CookieOptions options;
-
- EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), www_google_foo_.url(),
- "A1=B; path=/foo;", options));
- EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), www_google_bar_.url(),
- "A2=D; path=/bar;", options));
- EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), http_www_google_.url(), "A3=F;",
- options));
-
- CookieList cookies_1 = GetAllCookies(cm_1.get());
- scoped_refptr<CookieMonster> cm_2(new CookieMonster(NULL, NULL));
- ASSERT_TRUE(cm_2->ImportCookies(cookies_1));
- CookieList cookies_2 = GetAllCookies(cm_2.get());
-
- size_t expected_size = 3;
- EXPECT_EQ(expected_size, cookies_2.size());
-
- CookieList::iterator it = cookies_2.begin();
-
- ASSERT_TRUE(it != cookies_2.end());
- EXPECT_EQ("A1", it->Name());
- EXPECT_EQ("/foo", it->Path());
-
- ASSERT_TRUE(++it != cookies_2.end());
- EXPECT_EQ("A2", it->Name());
- EXPECT_EQ("/bar", it->Path());
-
- ASSERT_TRUE(++it != cookies_2.end());
- EXPECT_EQ("A3", it->Name());
- EXPECT_EQ("/", it->Path());
-}
-
// Tests importing from a persistent cookie store that contains duplicate
// equivalent cookies. This situation should be handled by removing the
// duplicate cookie (both from the in-memory cache, and from the backing store).
@@ -1576,20 +1464,20 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) {
// dates. We expect only the most recent one to be preserved following
// the import.
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(3), &initial_cookies);
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=2; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(1), &initial_cookies);
// ===> This one is the WINNER (biggest creation time). <====
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=3; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(4), &initial_cookies);
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=4; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now(), &initial_cookies);
@@ -1597,23 +1485,23 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) {
// dates. We expect only the most recent one to be preserved the import.
// ===> This one is the WINNER (biggest creation time). <====
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=a1; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(9), &initial_cookies);
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"X=a2; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(2), &initial_cookies);
// Insert 1 cookie with name "Y" on path "/".
- AddCookieToList("www.google.com",
+ AddCookieToList(GURL("http://www.google.com"),
"Y=a; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
Time::Now() + TimeDelta::FromDays(10), &initial_cookies);
// Inject our initial cookies into the mock PersistentCookieStore.
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_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).
@@ -1648,20 +1536,28 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCreationTimes) {
// two cookies remaining, but which two (other than that there should
// be one from each set) will be random.
std::vector<CanonicalCookie*> initial_cookies;
- AddCookieToList("www.google.com", "X=1; path=/", now, &initial_cookies);
- AddCookieToList("www.google.com", "X=2; path=/", now, &initial_cookies);
- AddCookieToList("www.google.com", "X=3; path=/", now, &initial_cookies);
- AddCookieToList("www.google.com", "X=4; path=/", now, &initial_cookies);
-
- AddCookieToList("www.google.com", "Y=1; path=/", earlier, &initial_cookies);
- AddCookieToList("www.google.com", "Y=2; path=/", earlier, &initial_cookies);
- AddCookieToList("www.google.com", "Y=3; path=/", earlier, &initial_cookies);
- AddCookieToList("www.google.com", "Y=4; path=/", earlier, &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "X=1; path=/", now,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "X=2; path=/", now,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "X=3; path=/", now,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "X=4; path=/", now,
+ &initial_cookies);
+
+ AddCookieToList(GURL("http://www.google.com"), "Y=1; path=/", earlier,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "Y=2; path=/", earlier,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "Y=3; path=/", earlier,
+ &initial_cookies);
+ AddCookieToList(GURL("http://www.google.com"), "Y=4; path=/", earlier,
+ &initial_cookies);
// Inject our initial cookies into the mock PersistentCookieStore.
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
CookieList list(GetAllCookies(cm.get()));
EXPECT_EQ(2U, list.size());
@@ -1677,8 +1573,7 @@ TEST_F(CookieMonsterTest, CookieMonsterDelegate) {
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
scoped_refptr<MockCookieMonsterDelegate> delegate(
new MockCookieMonsterDelegate);
- scoped_refptr<CookieMonster> cm(
- new CookieMonster(store.get(), delegate.get()));
+ scoped_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"));
@@ -1756,79 +1651,8 @@ TEST_F(CookieMonsterTest, CookieMonsterDelegate) {
delegate->reset();
}
-TEST_F(CookieMonsterTest, SetCookieWithDetails) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
-
- EXPECT_TRUE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_TRUE(SetCookieWithDetails(
- cm.get(), www_google_bar_.url(), "C", "D", www_google_bar_.domain(),
- "/bar", base::Time(), false, true, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_TRUE(SetCookieWithDetails(
- cm.get(), http_www_google_.url(), "E", "F", std::string(), std::string(),
- base::Time(), true, false, false, COOKIE_PRIORITY_DEFAULT));
-
- // Test that malformed attributes fail to set the cookie.
- EXPECT_FALSE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), " A", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_FALSE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A;", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_FALSE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A=", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_FALSE(SetCookieWithDetails(
- cm.get(), www_google_foo_.url(), "A", "B", "google.ozzzzzzle", "foo",
- base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
- EXPECT_FALSE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A=", "B",
- std::string(), "foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
-
- CookieList cookies = GetAllCookiesForURL(cm.get(), www_google_foo_.url());
- CookieList::iterator it = cookies.begin();
-
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ("A", it->Name());
- EXPECT_EQ("B", it->Value());
- EXPECT_EQ(www_google_foo_.host(), it->Domain());
- EXPECT_EQ("/foo", it->Path());
- EXPECT_FALSE(it->IsPersistent());
- EXPECT_FALSE(it->IsSecure());
- EXPECT_FALSE(it->IsHttpOnly());
-
- ASSERT_TRUE(++it == cookies.end());
-
- cookies = GetAllCookiesForURL(cm.get(), www_google_bar_.url());
- it = cookies.begin();
-
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ("C", it->Name());
- EXPECT_EQ("D", it->Value());
- EXPECT_EQ(www_google_bar_.Format(".%D"), it->Domain());
- EXPECT_EQ("/bar", it->Path());
- EXPECT_FALSE(it->IsSecure());
- EXPECT_TRUE(it->IsHttpOnly());
-
- ASSERT_TRUE(++it == cookies.end());
-
- cookies = GetAllCookiesForURL(cm.get(), https_www_google_.url());
- it = cookies.begin();
-
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ("E", it->Name());
- EXPECT_EQ("F", it->Value());
- EXPECT_EQ("/", it->Path());
- EXPECT_EQ(https_www_google_.host(), it->Domain());
- EXPECT_TRUE(it->IsSecure());
- EXPECT_FALSE(it->IsHttpOnly());
-
- ASSERT_TRUE(++it == cookies.end());
-}
-
TEST_F(CookieMonsterTest, DeleteAllForHost) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
// Test probes:
// * Non-secure URL, mid-level (http://w.c.b.a)
@@ -1838,7 +1662,7 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
// 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);
+ 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",
@@ -1851,7 +1675,9 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
std::string("/dir1/dir2/xxx"))));
- EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2)));
+ 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",
@@ -1864,8 +1690,10 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
std::string("/dir1/dir2/xxx"))));
- PopulateCmForDeleteAllForHost(cm);
- EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2Secure)));
+ PopulateCmForDeleteAllForHost(cm.get());
+ EXPECT_EQ(6, DeleteAllCreatedBetweenForHost(
+ cm.get(), base::Time(), base::Time::Now(),
+ GURL(kTopLevelDomainPlus2Secure)));
EXPECT_EQ(8U, GetAllCookies(cm.get()).size());
EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
@@ -1878,9 +1706,11 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
std::string("/dir1/dir2/xxx"))));
- PopulateCmForDeleteAllForHost(cm);
- EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2Secure +
- std::string("/dir1/xxx"))));
+ 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",
@@ -1895,7 +1725,7 @@ TEST_F(CookieMonsterTest, DeleteAllForHost) {
}
TEST_F(CookieMonsterTest, UniqueCreationTime) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
CookieOptions options;
// Add in three cookies through every public interface to the
@@ -1921,16 +1751,16 @@ TEST_F(CookieMonsterTest, UniqueCreationTime) {
EXPECT_TRUE(SetCookieWithDetails(
cm.get(), http_www_google_.url(), "setCookieWithDetails1", "A",
- http_www_google_.Format(".%D"), "/", Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(SetCookieWithDetails(
cm.get(), http_www_google_.url(), "setCookieWithDetails2", "A",
- http_www_google_.Format(".%D"), "/", Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
EXPECT_TRUE(SetCookieWithDetails(
cm.get(), http_www_google_.url(), "setCookieWithDetails3", "A",
- http_www_google_.Format(".%D"), "/", Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ http_www_google_.Format(".%D"), "/", Time(), Time(), Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
// Now we check
CookieList cookie_list(GetAllCookies(cm.get()));
@@ -1958,7 +1788,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_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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"));
@@ -1990,47 +1820,25 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) {
base::Time expires(base::Time::Now() + base::TimeDelta::FromSeconds(100));
const CookiesInputInfo input_info[] = {
- {GURL("http://a.b.google.com"),
- "a",
- "1",
- "",
- "/path/to/cookie",
- expires,
- false,
- false,
- false,
- COOKIE_PRIORITY_DEFAULT},
- {GURL("https://www.google.com"),
- "b",
- "2",
- ".google.com",
- "/path/from/cookie",
- expires + TimeDelta::FromSeconds(10),
- true,
- true,
- false,
- COOKIE_PRIORITY_DEFAULT},
- {GURL("https://google.com"),
- "c",
- "3",
- "",
- "/another/path/to/cookie",
- base::Time::Now() + base::TimeDelta::FromSeconds(100),
- true,
- false,
- true,
- COOKIE_PRIORITY_DEFAULT}};
+ {GURL("http://a.b.google.com"), "a", "1", "", "/path/to/cookie", expires,
+ false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT},
+ {GURL("https://www.google.com"), "b", "2", ".google.com",
+ "/path/from/cookie", expires + TimeDelta::FromSeconds(10), true, true,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT},
+ {GURL("https://google.com"), "c", "3", "", "/another/path/to/cookie",
+ base::Time::Now() + base::TimeDelta::FromSeconds(100), true, false,
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT}};
const int INPUT_DELETE = 1;
// Create new cookies and flush them to the store.
{
- scoped_refptr<CookieMonster> cmout(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cmout(new CookieMonster(store.get(), nullptr));
for (const CookiesInputInfo* p = input_info;
p < &input_info[arraysize(input_info)]; p++) {
- EXPECT_TRUE(SetCookieWithDetails(cmout.get(), p->url, p->name, p->value,
- p->domain, p->path, p->expiration_time,
- p->secure, p->http_only,
- p->first_party_only, p->priority));
+ EXPECT_TRUE(SetCookieWithDetails(
+ cmout.get(), p->url, p->name, p->value, p->domain, p->path,
+ base::Time(), p->expiration_time, base::Time(), p->secure,
+ p->http_only, p->same_site, p->priority));
}
GURL del_url(input_info[INPUT_DELETE]
.url.Resolve(input_info[INPUT_DELETE].path)
@@ -2040,7 +1848,7 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) {
// Create a new cookie monster and make sure that everything is correct
{
- scoped_refptr<CookieMonster> cmin(new CookieMonster(store.get(), NULL));
+ scoped_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
@@ -2059,7 +1867,7 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) {
output->CreationDate().ToInternalValue());
EXPECT_EQ(input->secure, output->IsSecure());
EXPECT_EQ(input->http_only, output->IsHttpOnly());
- EXPECT_EQ(input->first_party_only, output->IsFirstPartyOnly());
+ EXPECT_EQ(input->same_site, output->SameSite());
EXPECT_TRUE(output->IsPersistent());
EXPECT_EQ(input->expiration_time.ToInternalValue(),
output->ExpiryDate().ToInternalValue());
@@ -2070,7 +1878,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_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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"),
@@ -2127,7 +1935,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_refptr<CookieMonster> cm(
+ scoped_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");
@@ -2169,9 +1977,9 @@ 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_refptr<CookieMonster> cm(CreateMonsterFromStoreForGC(
+ scoped_ptr<CookieMonster> cm = CreateMonsterFromStoreForGC(
test_case->num_cookies, test_case->num_old_cookies, 0, 0,
- CookieMonster::kSafeFromGlobalPurgeDays * 2));
+ CookieMonster::kSafeFromGlobalPurgeDays * 2);
EXPECT_EQ(test_case->expected_initial_cookies,
GetAllCookies(cm.get()).size())
<< "For test case " << ci;
@@ -2183,33 +1991,197 @@ TEST_F(CookieMonsterTest, MAYBE_GarbageCollectionTriggers) {
}
}
-// This test checks that keep expired cookies flag is working.
-TEST_F(CookieMonsterTest, KeepExpiredCookies) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- cm->SetKeepExpiredCookies();
- CookieOptions options;
+// Tests that if the main load event happens before the loaded event for a
+// particular key, the tasks for that key run first.
+TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) {
+ const GURL kUrl = GURL(kTopLevelDomainPlus1);
- // Set a persistent cookie.
- ASSERT_TRUE(SetCookieWithOptions(
- cm.get(), http_www_google_.url(),
- std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT",
- options));
+ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+ store->set_store_load_commands(true);
+ scoped_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;
+ cm->SetCookieWithOptionsAsync(
+ kUrl, "a=b", CookieOptions(),
+ base::Bind(&ResultSavingCookieCallback<bool>::Run,
+ base::Unretained(&set_cookie_callback)));
+
+ GetCookieListCallback get_cookie_list_callback1;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback1)));
+
+ // Two load events should have been queued.
+ ASSERT_EQ(2u, store->commands().size());
+ ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+ ASSERT_EQ(CookieStoreCommand::LOAD_COOKIES_FOR_KEY,
+ store->commands()[1].type);
- // Get the canonical cookie.
- CookieList cookie_list = GetAllCookies(cm.get());
- ASSERT_EQ(1U, cookie_list.size());
+ // The main load completes first (With no cookies).
+ store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
- // Use a past expiry date to delete the cookie.
- ASSERT_TRUE(SetCookieWithOptions(
- cm.get(), http_www_google_.url(),
- std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
- options));
+ // The tasks should run in order, and the get should see the cookies.
+
+ set_cookie_callback.WaitUntilDone();
+ EXPECT_TRUE(set_cookie_callback.result());
+
+ get_cookie_list_callback1.WaitUntilDone();
+ EXPECT_EQ(1u, get_cookie_list_callback1.cookies().size());
+
+ // The loaded for key event completes late, with not cookies (Since they
+ // were already loaded).
+ store->commands()[1].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+ // The just set cookie should still be in the store.
+ GetCookieListCallback get_cookie_list_callback2;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback2)));
+ get_cookie_list_callback2.WaitUntilDone();
+ EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
+}
+
+// Tests that case that DeleteAll is waiting for load to complete, and then a
+// get is queued. The get should wait to run until after all the cookies are
+// retrieved, and should return nothing, since all cookies were just deleted.
+TEST_F(CookieMonsterTest, WhileLoadingDeleteAllGetForURL) {
+ const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+ store->set_store_load_commands(true);
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+ ResultSavingCookieCallback<int> delete_callback;
+ cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
+ base::Unretained(&delete_callback)));
+
+ GetCookieListCallback get_cookie_list_callback;
+ cm->GetCookieListWithOptionsAsync(
+ kUrl, CookieOptions(),
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback)));
+
+ // Only the main load should have been queued.
+ ASSERT_EQ(1u, store->commands().size());
+ ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+ std::vector<CanonicalCookie*> cookies;
+ // When passed to the CookieMonster, it takes ownership of the pointed to
+ // cookies.
+ cookies.push_back(
+ CanonicalCookie::Create(kUrl, "a=b", base::Time(), CookieOptions())
+ .release());
+ ASSERT_TRUE(cookies[0]);
+ store->commands()[0].loaded_callback.Run(cookies);
+
+ delete_callback.WaitUntilDone();
+ EXPECT_EQ(1, delete_callback.result());
+
+ get_cookie_list_callback.WaitUntilDone();
+ EXPECT_EQ(0u, get_cookie_list_callback.cookies().size());
+}
+
+// Tests that a set cookie call sandwiched between two get all cookies, all
+// before load completes, affects the first but not the second. The set should
+// also not trigger a LoadCookiesForKey (As that could complete only after the
+// main load for the store).
+TEST_F(CookieMonsterTest, WhileLoadingGetAllSetGetAll) {
+ const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+ store->set_store_load_commands(true);
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
+
+ GetCookieListCallback get_cookie_list_callback1;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback1)));
+
+ ResultSavingCookieCallback<bool> set_cookie_callback;
+ cm->SetCookieWithOptionsAsync(
+ kUrl, "a=b", CookieOptions(),
+ base::Bind(&ResultSavingCookieCallback<bool>::Run,
+ base::Unretained(&set_cookie_callback)));
+
+ GetCookieListCallback get_cookie_list_callback2;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback2)));
+
+ // Only the main load should have been queued.
+ ASSERT_EQ(1u, store->commands().size());
+ ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+ // The load completes (With no cookies).
+ store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+ get_cookie_list_callback1.WaitUntilDone();
+ EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size());
+
+ set_cookie_callback.WaitUntilDone();
+ EXPECT_TRUE(set_cookie_callback.result());
+
+ get_cookie_list_callback2.WaitUntilDone();
+ EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
+}
+
+namespace {
+
+void RunClosureOnCookieListReceived(const base::Closure& closure,
+ const CookieList& cookie_list) {
+ closure.Run();
+}
+
+} // namespace
- // Check that the cookie with the past expiry date is still there.
- // GetAllCookies() also triggers garbage collection.
- cookie_list = GetAllCookies(cm.get());
- ASSERT_EQ(1U, cookie_list.size());
- ASSERT_TRUE(cookie_list[0].IsExpired(Time::Now()));
+// Tests that if a single cookie task is queued as a result of a task performed
+// on all cookies when loading completes, it will be run after any already
+// queued tasks.
+TEST_F(CookieMonsterTest, CheckOrderOfCookieTaskQueueWhenLoadingCompletes) {
+ const GURL kUrl = GURL(kTopLevelDomainPlus1);
+
+ scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
+ store->set_store_load_commands(true);
+ scoped_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;
+ cm->GetAllCookiesAsync(base::Bind(
+ &RunClosureOnCookieListReceived,
+ base::Bind(&CookieStore::SetCookieWithOptionsAsync,
+ base::Unretained(cm.get()), kUrl, "a=b", CookieOptions(),
+ base::Bind(&ResultSavingCookieCallback<bool>::Run,
+ base::Unretained(&set_cookie_callback)))));
+
+ // Get cookie task. Queued before the delete task is executed, so should not
+ // see the set cookie.
+ GetCookieListCallback get_cookie_list_callback1;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback1)));
+
+ // Only the main load should have been queued.
+ ASSERT_EQ(1u, store->commands().size());
+ ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
+
+ // The load completes.
+ store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>());
+
+ // The get cookies call should see no cookies set.
+ get_cookie_list_callback1.WaitUntilDone();
+ EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size());
+
+ set_cookie_callback.WaitUntilDone();
+ EXPECT_TRUE(set_cookie_callback.result());
+
+ // A subsequent get cookies call should see the new cookie.
+ GetCookieListCallback get_cookie_list_callback2;
+ cm->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&get_cookie_list_callback2)));
+ get_cookie_list_callback2.WaitUntilDone();
+ EXPECT_EQ(1u, get_cookie_list_callback2.cookies().size());
}
namespace {
@@ -2273,7 +2245,7 @@ class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> {
TEST_F(CookieMonsterTest, FlushStore) {
scoped_refptr<CallbackCounter> counter(new CallbackCounter());
scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
ASSERT_EQ(0, store->flush_count());
ASSERT_EQ(0, counter->callback_count());
@@ -2308,7 +2280,7 @@ TEST_F(CookieMonsterTest, FlushStore) {
ASSERT_EQ(2, counter->callback_count());
// If there's no backing store, FlushStore() is always a safe no-op.
- cm = new CookieMonster(NULL, NULL);
+ cm.reset(new CookieMonster(nullptr, nullptr));
GetAllCookies(cm.get()); // Force init.
cm->FlushStore(base::Closure());
base::MessageLoop::current()->RunUntilIdle();
@@ -2323,7 +2295,7 @@ TEST_F(CookieMonsterTest, FlushStore) {
TEST_F(CookieMonsterTest, SetAllCookies) {
scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
cm->SetPersistSessionCookies(true);
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "U=V; path=/"));
@@ -2331,18 +2303,18 @@ TEST_F(CookieMonsterTest, SetAllCookies) {
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "Y=Z; path=/"));
CookieList list;
- list.push_back(CanonicalCookie(http_www_google_.url(), "A", "B",
- http_www_google_.url().host(), "/",
- base::Time::Now(), base::Time(), base::Time(),
- false, false, false, COOKIE_PRIORITY_DEFAULT));
- list.push_back(CanonicalCookie(http_www_google_.url(), "W", "X",
- http_www_google_.url().host(), "/bar",
- base::Time::Now(), base::Time(), base::Time(),
- false, false, false, COOKIE_PRIORITY_DEFAULT));
- list.push_back(CanonicalCookie(http_www_google_.url(), "Y", "Z",
- http_www_google_.url().host(), "/",
- base::Time::Now(), base::Time(), base::Time(),
- false, false, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "A", "B", http_www_google_.url().host(), "/",
+ base::Time::Now(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "W", "X", http_www_google_.url().host(), "/bar",
+ base::Time::Now(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
+ list.push_back(*CanonicalCookie::Create(
+ http_www_google_.url(), "Y", "Z", http_www_google_.url().host(), "/",
+ base::Time::Now(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT));
// SetAllCookies must not flush.
ASSERT_EQ(0, store->flush_count());
@@ -2369,71 +2341,73 @@ TEST_F(CookieMonsterTest, SetAllCookies) {
}
TEST_F(CookieMonsterTest, ComputeCookieDiff) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(nullptr, nullptr));
base::Time now = base::Time::Now();
base::Time creation_time = now - base::TimeDelta::FromSeconds(1);
- CanonicalCookie cookie1(http_www_google_.url(), "A", "B",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie2(http_www_google_.url(), "C", "D",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie3(http_www_google_.url(), "E", "F",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie4(http_www_google_.url(), "G", "H",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie4_with_new_value(
+ scoped_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(
+ 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(
+ 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(
+ 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(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie5(http_www_google_.url(), "I", "J",
- http_www_google_.url().host(), "/", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie5_with_new_creation_time(
- http_www_google_.url(), "I", "J", http_www_google_.url().host(), "/", now,
- base::Time(), base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie6(http_www_google_.url(), "K", "L",
- http_www_google_.url().host(), "/foo", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie6_with_new_path(
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_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(
+ 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(
+ 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(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie7(http_www_google_.url(), "M", "N",
- http_www_google_.url().host(), "/foo", creation_time,
- base::Time(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- CanonicalCookie cookie7_with_new_path(
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
+ scoped_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(), base::Time(), false, false, false,
- COOKIE_PRIORITY_DEFAULT);
+ creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT));
CookieList old_cookies;
- old_cookies.push_back(cookie1);
- old_cookies.push_back(cookie2);
- old_cookies.push_back(cookie4);
- old_cookies.push_back(cookie5);
- old_cookies.push_back(cookie6);
- old_cookies.push_back(cookie7);
+ old_cookies.push_back(*cookie1);
+ old_cookies.push_back(*cookie2);
+ old_cookies.push_back(*cookie4);
+ old_cookies.push_back(*cookie5);
+ old_cookies.push_back(*cookie6);
+ old_cookies.push_back(*cookie7);
CookieList new_cookies;
- new_cookies.push_back(cookie1);
- new_cookies.push_back(cookie3);
- new_cookies.push_back(cookie4_with_new_value);
- new_cookies.push_back(cookie5_with_new_creation_time);
- new_cookies.push_back(cookie6_with_new_path);
- new_cookies.push_back(cookie7);
- new_cookies.push_back(cookie7_with_new_path);
+ new_cookies.push_back(*cookie1);
+ new_cookies.push_back(*cookie3);
+ new_cookies.push_back(*cookie4_with_new_value);
+ new_cookies.push_back(*cookie5_with_new_creation_time);
+ new_cookies.push_back(*cookie6_with_new_path);
+ new_cookies.push_back(*cookie7);
+ new_cookies.push_back(*cookie7_with_new_path);
CookieList cookies_to_add;
CookieList cookies_to_delete;
@@ -2442,51 +2416,51 @@ TEST_F(CookieMonsterTest, ComputeCookieDiff) {
&cookies_to_delete);
// |cookie1| has not changed.
- EXPECT_FALSE(IsCookieInList(cookie1, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie1, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie1, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie1, cookies_to_delete));
// |cookie2| has been deleted.
- EXPECT_FALSE(IsCookieInList(cookie2, cookies_to_add));
- EXPECT_TRUE(IsCookieInList(cookie2, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie2, cookies_to_add));
+ EXPECT_TRUE(IsCookieInList(*cookie2, cookies_to_delete));
// |cookie3| has been added.
- EXPECT_TRUE(IsCookieInList(cookie3, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie3, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie3, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie3, cookies_to_delete));
// |cookie4| has a new value: new cookie overrides the old one (which does not
// need to be explicitly removed).
- EXPECT_FALSE(IsCookieInList(cookie4, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie4, cookies_to_delete));
- EXPECT_TRUE(IsCookieInList(cookie4_with_new_value, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie4_with_new_value, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie4, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie4, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie4_with_new_value, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie4_with_new_value, cookies_to_delete));
// |cookie5| has a new creation time: new cookie overrides the old one (which
// does not need to be explicitly removed).
- EXPECT_FALSE(IsCookieInList(cookie5, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie5, cookies_to_delete));
- EXPECT_TRUE(IsCookieInList(cookie5_with_new_creation_time, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie5, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie5, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie5_with_new_creation_time, cookies_to_add));
EXPECT_FALSE(
- IsCookieInList(cookie5_with_new_creation_time, cookies_to_delete));
+ IsCookieInList(*cookie5_with_new_creation_time, cookies_to_delete));
// |cookie6| has a new path: the new cookie does not overrides the old one,
// which needs to be explicitly removed.
- EXPECT_FALSE(IsCookieInList(cookie6, cookies_to_add));
- EXPECT_TRUE(IsCookieInList(cookie6, cookies_to_delete));
- EXPECT_TRUE(IsCookieInList(cookie6_with_new_path, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie6_with_new_path, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie6, cookies_to_add));
+ EXPECT_TRUE(IsCookieInList(*cookie6, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie6_with_new_path, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie6_with_new_path, cookies_to_delete));
// |cookie7| is kept and |cookie7_with_new_path| is added as a new cookie.
- EXPECT_FALSE(IsCookieInList(cookie7, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie7, cookies_to_delete));
- EXPECT_TRUE(IsCookieInList(cookie7_with_new_path, cookies_to_add));
- EXPECT_FALSE(IsCookieInList(cookie7_with_new_path, cookies_to_delete));
+ EXPECT_FALSE(IsCookieInList(*cookie7, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie7, cookies_to_delete));
+ EXPECT_TRUE(IsCookieInList(*cookie7_with_new_path, cookies_to_add));
+ EXPECT_FALSE(IsCookieInList(*cookie7_with_new_path, cookies_to_delete));
}
// Check that DeleteAll does flush (as a sanity check that flush_count()
// works).
TEST_F(CookieMonsterTest, DeleteAll) {
scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
cm->SetPersistSessionCookies(true);
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "X=Y; path=/"));
@@ -2497,7 +2471,7 @@ TEST_F(CookieMonsterTest, DeleteAll) {
}
TEST_F(CookieMonsterTest, HistogramCheck) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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.
@@ -2508,9 +2482,9 @@ TEST_F(CookieMonsterTest, HistogramCheck) {
scoped_ptr<base::HistogramSamples> samples1(
expired_histogram->SnapshotSamples());
ASSERT_TRUE(SetCookieWithDetails(
- cm.get(), GURL("http://fake.a.url"), "a", "b", "a.url", "/",
- base::Time::Now() + base::TimeDelta::FromMinutes(59), false, false, false,
- COOKIE_PRIORITY_DEFAULT));
+ 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(
expired_histogram->SnapshotSamples());
@@ -2524,356 +2498,6 @@ TEST_F(CookieMonsterTest, HistogramCheck) {
EXPECT_EQ(samples2->TotalCount(), samples3->TotalCount());
}
-namespace {
-
-class MultiThreadedCookieMonsterTest : public CookieMonsterTest {
- public:
- MultiThreadedCookieMonsterTest() : other_thread_("CMTthread") {}
-
- // Helper methods for calling the asynchronous CookieMonster methods
- // from a different thread.
-
- void GetAllCookiesTask(CookieMonster* cm, GetCookieListCallback* callback) {
- cm->GetAllCookiesAsync(
- base::Bind(&GetCookieListCallback::Run, base::Unretained(callback)));
- }
-
- void GetAllCookiesForURLTask(CookieMonster* cm,
- const GURL& url,
- GetCookieListCallback* callback) {
- cm->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
- base::Unretained(callback)));
- }
-
- void GetAllCookiesForURLWithOptionsTask(CookieMonster* cm,
- const GURL& url,
- const CookieOptions& options,
- GetCookieListCallback* callback) {
- cm->GetAllCookiesForURLWithOptionsAsync(
- url, options,
- base::Bind(&GetCookieListCallback::Run, base::Unretained(callback)));
- }
-
- void SetCookieWithDetailsTask(CookieMonster* cm,
- const GURL& url,
- ResultSavingCookieCallback<bool>* callback) {
- // Define the parameters here instead of in the calling fucntion.
- // The maximum number of parameters for Bind function is 6.
- std::string name = "A";
- std::string value = "B";
- std::string domain = std::string();
- std::string path = "/foo";
- base::Time expiration_time = base::Time();
- bool secure = false;
- bool http_only = false;
- bool first_party_only = false;
- CookiePriority priority = COOKIE_PRIORITY_DEFAULT;
- cm->SetCookieWithDetailsAsync(
- url, name, value, domain, path, expiration_time, secure, http_only,
- first_party_only, false /* enforce prefixes */,
- false /* enforces strict secure cookies */, priority,
- base::Bind(&ResultSavingCookieCallback<bool>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteAllCreatedBetweenTask(CookieMonster* cm,
- const base::Time& delete_begin,
- const base::Time& delete_end,
- ResultSavingCookieCallback<int>* callback) {
- cm->DeleteAllCreatedBetweenAsync(
- delete_begin, delete_end,
- base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteAllForHostTask(CookieMonster* cm,
- const GURL& url,
- ResultSavingCookieCallback<int>* callback) {
- cm->DeleteAllForHostAsync(url,
- base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteAllCreatedBetweenForHostTask(
- CookieMonster* cm,
- const base::Time delete_begin,
- const base::Time delete_end,
- const GURL& url,
- ResultSavingCookieCallback<int>* callback) {
- cm->DeleteAllCreatedBetweenForHostAsync(
- delete_begin, delete_end, url,
- base::Bind(&ResultSavingCookieCallback<int>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteCanonicalCookieTask(CookieMonster* cm,
- const CanonicalCookie& cookie,
- ResultSavingCookieCallback<bool>* callback) {
- cm->DeleteCanonicalCookieAsync(
- cookie, base::Bind(&ResultSavingCookieCallback<bool>::Run,
- base::Unretained(callback)));
- }
-
- protected:
- void RunOnOtherThread(const base::Closure& task) {
- other_thread_.Start();
- other_thread_.task_runner()->PostTask(FROM_HERE, task);
- RunFor(kTimeout);
- other_thread_.Stop();
- }
-
- Thread other_thread_;
-};
-
-} // namespace
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookies) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
- CookieList cookies = GetAllCookies(cm.get());
- CookieList::const_iterator it = cookies.begin();
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == cookies.end());
- GetCookieListCallback callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::GetAllCookiesTask,
- base::Unretained(this), cm, &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- it = callback.cookies().begin();
- ASSERT_TRUE(it != callback.cookies().end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == callback.cookies().end());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURL) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
- CookieList cookies = GetAllCookiesForURL(cm.get(), http_www_google_.url());
- CookieList::const_iterator it = cookies.begin();
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == cookies.end());
- GetCookieListCallback callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::GetAllCookiesForURLTask,
- base::Unretained(this), cm, http_www_google_.url(), &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- it = callback.cookies().begin();
- ASSERT_TRUE(it != callback.cookies().end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == callback.cookies().end());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURLWithOpt) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(), "A=B"));
- CookieOptions options;
- CookieList cookies =
- GetAllCookiesForURLWithOptions(cm.get(), http_www_google_.url(), options);
- CookieList::const_iterator it = cookies.begin();
- ASSERT_TRUE(it != cookies.end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == cookies.end());
- GetCookieListCallback callback(&other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieMonsterTest::GetAllCookiesForURLWithOptionsTask,
- base::Unretained(this), cm, http_www_google_.url(), options, &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- it = callback.cookies().begin();
- ASSERT_TRUE(it != callback.cookies().end());
- EXPECT_EQ(http_www_google_.host(), it->Domain());
- EXPECT_EQ("A", it->Name());
- ASSERT_TRUE(++it == callback.cookies().end());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckSetCookieWithDetails) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- EXPECT_TRUE(SetCookieWithDetails(cm.get(), www_google_foo_.url(), "A", "B",
- std::string(), "/foo", base::Time(), false,
- false, false, COOKIE_PRIORITY_DEFAULT));
- ResultSavingCookieCallback<bool> callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::SetCookieWithDetailsTask,
- base::Unretained(this), cm, www_google_foo_.url(), &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_TRUE(callback.result());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllCreatedBetween) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- CookieOptions options;
- Time now = Time::Now();
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- EXPECT_EQ(1, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(99),
- Time()));
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- ResultSavingCookieCallback<int> callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenTask,
- base::Unretained(this), cm, now - TimeDelta::FromDays(99),
- Time(), &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ(1, callback.result());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllForHost) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- CookieOptions options;
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- EXPECT_EQ(1, DeleteAllForHost(cm.get(), http_www_google_.url()));
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- ResultSavingCookieCallback<int> callback(&other_thread_);
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::DeleteAllForHostTask,
- base::Unretained(this), cm, http_www_google_.url(), &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ(1, callback.result());
-}
-
-TEST_F(MultiThreadedCookieMonsterTest,
- ThreadCheckDeleteAllCreatedBetweenForHost) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- GURL url_not_google("http://www.notgoogle.com");
-
- CookieOptions options;
- Time now = Time::Now();
- // ago1 < ago2 < ago3 < now.
- Time ago1 = now - TimeDelta::FromDays(101);
- Time ago2 = now - TimeDelta::FromDays(100);
- Time ago3 = now - TimeDelta::FromDays(99);
-
- // These 3 cookies match the first deletion.
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "C=D", options));
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "Y=Z", options));
-
- // This cookie does not match host.
- EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_not_google, "E=F", options));
-
- // This cookie does not match time range: [ago3, inf], for first deletion, but
- // matches for the second deletion.
- EXPECT_TRUE(
- cm->SetCookieWithCreationTime(http_www_google_.url(), "G=H", ago2));
-
- // 1. First set of deletions.
- EXPECT_EQ(3, // Deletes A=B, C=D, Y=Z
- DeleteAllCreatedBetweenForHost(cm.get(), ago3, Time::Max(),
- http_www_google_.url()));
-
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- ResultSavingCookieCallback<int> callback(&other_thread_);
-
- // 2. Second set of deletions.
- base::Closure task = base::Bind(
- &MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenForHostTask,
- base::Unretained(this), cm, ago1, Time(), http_www_google_.url(),
- &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ(2, callback.result()); // Deletes A=B, G=H.
-}
-
-TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteCanonicalCookie) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
- CookieOptions options;
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- CookieList cookies = GetAllCookies(cm.get());
- CookieList::iterator it = cookies.begin();
- EXPECT_TRUE(DeleteCanonicalCookie(cm.get(), *it));
-
- EXPECT_TRUE(
- SetCookieWithOptions(cm.get(), http_www_google_.url(), "A=B", options));
- ResultSavingCookieCallback<bool> callback(&other_thread_);
- cookies = GetAllCookies(cm.get());
- it = cookies.begin();
- base::Closure task =
- base::Bind(&MultiThreadedCookieMonsterTest::DeleteCanonicalCookieTask,
- base::Unretained(this), cm, *it, &callback);
- RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_TRUE(callback.result());
-}
-
-// Ensure that cookies for http, https, ws, and wss all share the same storage
-// and policies when GetAllCookiesForURLAsync is used. This test is part of
-// MultiThreadedCookieMonsterTest in order to test and use
-// GetAllCookiesForURLAsync, but it does not use any additional threads.
-TEST_F(MultiThreadedCookieMonsterTest, GetAllCookiesForURLEffectiveDomain) {
- std::vector<CanonicalCookie*> cookies;
- // This cookie will be freed by the CookieMonster.
- cookies.push_back(CanonicalCookie::Create(
- http_www_google_.url(), kValidCookieLine, Time::Now(), CookieOptions()));
- CanonicalCookie cookie = *cookies[0];
- scoped_refptr<NewMockPersistentCookieStore> store(
- new NewMockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
-
- CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback;
- ::testing::StrictMock<::testing::MockFunction<void(int)>> checkpoint;
- const std::string key = cookie_util::GetEffectiveDomain(
- http_www_google_.url().scheme(), http_www_google_.url().host());
-
- ::testing::InSequence s;
- EXPECT_CALL(checkpoint, Call(0));
- EXPECT_CALL(*store, Load(::testing::_));
- EXPECT_CALL(*store, LoadCookiesForKey(key, ::testing::_))
- .WillOnce(::testing::SaveArg<1>(&loaded_callback));
- EXPECT_CALL(checkpoint, Call(1));
- // LoadCookiesForKey will never be called after checkpoint.Call(1) although
- // we will call GetAllCookiesForURLAsync again, because all URLs below share
- // the same key.
- EXPECT_CALL(*store, LoadCookiesForKey(::testing::_, ::testing::_)).Times(0);
-
- GetCookieListCallback callback;
- checkpoint.Call(0);
- GetAllCookiesForURLTask(cm.get(), http_www_google_.url(), &callback);
- checkpoint.Call(1);
- ASSERT_FALSE(callback.did_run());
- // Pass the cookies to the CookieMonster.
- loaded_callback.Run(cookies);
- // Now GetAllCookiesForURLTask is done.
- ASSERT_TRUE(callback.did_run());
- // See that the callback was called with the cookies.
- ASSERT_EQ(1u, callback.cookies().size());
- EXPECT_TRUE(cookie.IsEquivalent(callback.cookies()[0]));
-
- // All urls in |urls| should share the same cookie domain.
- const GURL kUrls[] = {
- http_www_google_.url(), https_www_google_.url(), ws_www_google_.url(),
- wss_www_google_.url(),
- };
- for (const GURL& url : kUrls) {
- // Call the function with |url| and verify it is done synchronously without
- // calling LoadCookiesForKey.
- GetCookieListCallback callback;
- GetAllCookiesForURLTask(cm.get(), url, &callback);
- ASSERT_TRUE(callback.did_run());
- ASSERT_EQ(1u, callback.cookies().size());
- EXPECT_TRUE(cookie.IsEquivalent(callback.cookies()[0]));
- }
-}
-
TEST_F(CookieMonsterTest, InvalidExpiryTime) {
std::string cookie_line =
std::string(kValidCookieLine) + "; expires=Blarg arg arg";
@@ -2886,7 +2510,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_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
cm->SetPersistSessionCookies(true);
// All cookies set with SetCookie are session cookies.
@@ -2922,7 +2546,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_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
// Add a cookie.
EXPECT_TRUE(SetCookie(cm.get(), http_www_google_.url(),
@@ -2974,24 +2598,24 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) {
std::vector<CanonicalCookie*> initial_cookies;
- AddCookieToList(domain, "foo=bar; path=" + path, now1, &initial_cookies);
+ AddCookieToList(url, "foo=bar; path=" + path, now1, &initial_cookies);
// We have to manually build this cookie because it contains a control
// character, and our cookie line parser rejects control characters.
- CanonicalCookie* cc =
- new CanonicalCookie(url, "baz",
- "\x05"
- "boo",
- domain, path, now2, later, now2, false, false, false,
- COOKIE_PRIORITY_DEFAULT);
- initial_cookies.push_back(cc);
+ scoped_ptr<CanonicalCookie> cc = CanonicalCookie::Create(
+ url, "baz",
+ "\x05"
+ "boo",
+ domain, path, now2, later, false, false, CookieSameSite::DEFAULT_MODE,
+ false, COOKIE_PRIORITY_DEFAULT);
+ initial_cookies.push_back(cc.release());
- AddCookieToList(domain, "hello=world; path=" + path, now3, &initial_cookies);
+ AddCookieToList(url, "hello=world; path=" + path, now3, &initial_cookies);
// Inject our initial cookies into the mock PersistentCookieStore.
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
EXPECT_EQ("foo=bar; hello=world", GetCookies(cm.get(), url));
}
@@ -3002,7 +2626,7 @@ TEST_F(CookieMonsterTest, CookieSourceHistogram) {
const std::string cookie_source_histogram = "Cookie.CookieSourceScheme";
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr));
histograms.ExpectTotalCount(cookie_source_histogram, 0);
@@ -3069,7 +2693,7 @@ TEST_F(CookieMonsterTest, CookieDeleteEquivalentHistogramTest) {
const std::string cookie_source_histogram = "Cookie.CookieDeleteEquivalent";
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_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"));
@@ -3134,7 +2758,7 @@ TEST_F(CookieMonsterTest, CookieDeleteEquivalentHistogramTest) {
}
TEST_F(CookieMonsterStrictSecureTest, SetSecureCookies) {
- scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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");
@@ -3327,7 +2951,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_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
+ scoped_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");
@@ -3352,7 +2976,7 @@ TEST_F(CookieMonsterStrictSecureTest, CookieDeleteEquivalentHistogramTest) {
const std::string cookie_source_histogram = "Cookie.CookieDeleteEquivalent";
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
+ scoped_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"));
@@ -3427,7 +3051,7 @@ class CookieMonsterNotificationTest : public CookieMonsterTest {
CookieMonsterNotificationTest()
: test_url_("http://www.google.com/foo"),
store_(new MockPersistentCookieStore),
- monster_(new CookieMonster(store_.get(), NULL)) {}
+ monster_(new CookieMonster(store_.get(), nullptr)) {}
~CookieMonsterNotificationTest() override {}
@@ -3438,7 +3062,7 @@ class CookieMonsterNotificationTest : public CookieMonsterTest {
private:
scoped_refptr<MockPersistentCookieStore> store_;
- scoped_refptr<CookieMonster> monster_;
+ scoped_ptr<CookieMonster> monster_;
};
void RecordCookieChanges(std::vector<CanonicalCookie>* out_cookies,
diff --git a/chromium/net/cookies/cookie_options.cc b/chromium/net/cookies/cookie_options.cc
index d29d51186f1..8698afdbd7b 100644
--- a/chromium/net/cookies/cookie_options.cc
+++ b/chromium/net/cookies/cookie_options.cc
@@ -10,8 +10,9 @@ namespace net {
CookieOptions::CookieOptions()
: exclude_httponly_(true),
- include_first_party_only_cookies_(false),
+ same_site_cookie_mode_(SameSiteCookieMode::DO_NOT_INCLUDE),
enforce_strict_secure_(false),
+ update_access_time_(true),
server_time_() {}
} // namespace net
diff --git a/chromium/net/cookies/cookie_options.h b/chromium/net/cookies/cookie_options.h
index 4d2a774c1bc..d1c6afc6371 100644
--- a/chromium/net/cookies/cookie_options.h
+++ b/chromium/net/cookies/cookie_options.h
@@ -9,35 +9,45 @@
#include "base/time/time.h"
#include "net/base/net_export.h"
+#include "net/cookies/cookie_constants.h"
#include "url/gurl.h"
namespace net {
class NET_EXPORT CookieOptions {
public:
+ enum class SameSiteCookieMode {
+ INCLUDE_STRICT_AND_LAX,
+ INCLUDE_LAX,
+ DO_NOT_INCLUDE
+ };
+
// Creates a CookieOptions object which:
//
// * Excludes HttpOnly cookies
- // * Excludes First-Party-Only cookies
+ // * Excludes SameSite cookies
// * Does not enforce prefix restrictions (e.g. "$Secure-*")
+ // * Updates last-accessed time.
//
// These settings can be altered by calling:
//
// * |set_{include,exclude}_httponly()|
- // * |set_include_first_party_only_cookies()|
+ // * |set_same_site_cookie_mode(
+ // CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX)|
// * |set_enforce_prefixes()|
+ // * |set_do_not_update_access_time()|
CookieOptions();
void set_exclude_httponly() { exclude_httponly_ = true; }
void set_include_httponly() { exclude_httponly_ = false; }
bool exclude_httponly() const { return exclude_httponly_; }
- // Default is to exclude 'first-party-only' cookies.
- void set_include_first_party_only_cookies() {
- include_first_party_only_cookies_ = true;
+ // Default is to exclude 'same_site' cookies.
+ void set_same_site_cookie_mode(SameSiteCookieMode mode) {
+ same_site_cookie_mode_ = mode;
}
- bool include_first_party_only_cookies() const {
- return include_first_party_only_cookies_;
+ SameSiteCookieMode same_site_cookie_mode() const {
+ return same_site_cookie_mode_;
}
// TODO(jww): Remove once we decide whether to ship modifying 'secure' cookies
@@ -54,10 +64,14 @@ class NET_EXPORT CookieOptions {
bool has_server_time() const { return !server_time_.is_null(); }
base::Time server_time() const { return server_time_; }
+ void set_do_not_update_access_time() { update_access_time_ = false; }
+ bool update_access_time() const { return update_access_time_; }
+
private:
bool exclude_httponly_;
- bool include_first_party_only_cookies_;
+ SameSiteCookieMode same_site_cookie_mode_;
bool enforce_strict_secure_;
+ bool update_access_time_;
base::Time server_time_;
};
diff --git a/chromium/net/cookies/cookie_store.cc b/chromium/net/cookies/cookie_store.cc
index e1b2e091001..f1dff9ada43 100644
--- a/chromium/net/cookies/cookie_store.cc
+++ b/chromium/net/cookies/cookie_store.cc
@@ -8,8 +8,68 @@
namespace net {
-CookieStore::CookieStore() {}
-
CookieStore::~CookieStore() {}
+std::string CookieStore::BuildCookieLine(
+ const std::vector<CanonicalCookie>& cookies) {
+ std::string cookie_line;
+ for (const auto& cookie : cookies) {
+ if (!cookie_line.empty())
+ cookie_line += "; ";
+ // In Mozilla, if you set a cookie like "AAA", it will have an empty token
+ // and a value of "AAA". When it sends the cookie back, it will send "AAA",
+ // so we need to avoid sending "=AAA" for a blank token value.
+ if (!cookie.Name().empty())
+ cookie_line += cookie.Name() + "=";
+ cookie_line += cookie.Value();
+ }
+ return cookie_line;
+}
+
+std::string CookieStore::BuildCookieLine(
+ const std::vector<CanonicalCookie*>& cookies) {
+ std::string cookie_line;
+ for (const auto& cookie : cookies) {
+ if (!cookie_line.empty())
+ cookie_line += "; ";
+ // In Mozilla, if you set a cookie like "AAA", it will have an empty token
+ // and a value of "AAA". When it sends the cookie back, it will send "AAA",
+ // so we need to avoid sending "=AAA" for a blank token value.
+ if (!cookie->Name().empty())
+ cookie_line += cookie->Name() + "=";
+ cookie_line += cookie->Value();
+ }
+ return cookie_line;
+}
+
+void CookieStore::DeleteAllAsync(const DeleteCallback& callback) {
+ DeleteAllCreatedBetweenAsync(base::Time(), base::Time::Max(), callback);
+}
+
+void CookieStore::SetForceKeepSessionState() {
+ // By default, do nothing.
+}
+
+void CookieStore::GetAllCookiesForURLAsync(
+ const GURL& url,
+ const GetCookieListCallback& callback) {
+ CookieOptions options;
+ options.set_include_httponly();
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ options.set_do_not_update_access_time();
+ GetCookieListWithOptionsAsync(url, options, callback);
+}
+
+void CookieStore::SetChannelIDServiceID(int id) {
+ DCHECK_EQ(-1, channel_id_service_id_);
+ channel_id_service_id_ = id;
+}
+
+int CookieStore::GetChannelIDServiceID() {
+ return channel_id_service_id_;
+}
+
+CookieStore::CookieStore() : channel_id_service_id_(-1) {}
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_store.h b/chromium/net/cookies/cookie_store.h
index e2e24406365..f6426c5d695 100644
--- a/chromium/net/cookies/cookie_store.h
+++ b/chromium/net/cookies/cookie_store.h
@@ -12,7 +12,7 @@
#include "base/callback.h"
#include "base/callback_list.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/cookies/canonical_cookie.h"
@@ -24,9 +24,14 @@ namespace net {
class CookieMonster;
-// An interface for storing and retrieving cookies. Implementations need to
-// be thread safe as its methods can be accessed from IO as well as UI threads.
-class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
+// An interface for storing and retrieving cookies. Implementations are not
+// thread safe, as with most other net classes. All methods must be invoked on
+// the network thread, and all callbacks will be calle there.
+//
+// All async functions may either invoke the callback asynchronously, or they
+// may be invoked immediately (prior to return of the asynchronous function).
+// Destroying the CookieStore will cancel pending async callbacks.
+class NET_EXPORT CookieStore {
public:
// Callback definitions.
typedef base::Callback<void(const CookieList& cookies)> GetCookieListCallback;
@@ -39,7 +44,21 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
CookieChangedCallbackList;
typedef CookieChangedCallbackList::Subscription CookieChangedSubscription;
- // Sets a single cookie. Expects a cookie line, like "a=1; domain=b.com".
+ virtual ~CookieStore();
+
+ // Returns the cookie line (e.g. "cookie1=value1; cookie2=value2") represented
+ // by |cookies|. The string is built in the same order as the given list.
+ //
+ // TODO(mkwst): We really should standardize on either
+ // 'std::vector<CanonicalCookie>' or 'std::vector<CanonicalCookie*>'.
+ static std::string BuildCookieLine(
+ const std::vector<CanonicalCookie>& cookies);
+ static std::string BuildCookieLine(
+ const std::vector<CanonicalCookie*>& cookies);
+
+ // Sets the cookies specified by |cookie_list| returned from |url|
+ // with options |options| in effect. Expects a cookie line, like
+ // "a=1; domain=b.com".
//
// Fails either if the cookie is invalid or if this is a non-HTTPONLY cookie
// and it would overwrite an existing HTTPONLY cookie.
@@ -50,28 +69,85 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
const CookieOptions& options,
const SetCookiesCallback& callback) = 0;
+ // Sets a cookie given explicit user-provided cookie attributes. The cookie
+ // name, value, domain, etc. are each provided as separate strings. This
+ // function expects each attribute to be well-formed. It will check for
+ // disallowed characters (e.g. the ';' character is disallowed within the
+ // cookie value attribute) and will return false without setting the cookie
+ // if such characters are found.
+ //
+ // If |creation_time| is null, it will be set to the time the cookie is set.
+ // If |last_access_time| is null, it be set to |creation_time|.
+ //
+ // If unable to set a cookie, will invoke |callback| with false.
+ virtual void SetCookieWithDetailsAsync(
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ bool enforce_strict_secure,
+ CookiePriority priority,
+ const SetCookiesCallback& callback) = 0;
+
// TODO(???): what if the total size of all the cookies >4k, can we have a
// header that big or do we need multiple Cookie: headers?
// Note: Some sites, such as Facebook, occasionally use Cookie headers >4k.
//
// Simple interface, gets a cookie string "a=b; c=d" for the given URL.
- // Use options to access httponly cookies.
+ // Gets all cookies that apply to |url| given |options|. Use options to
+ // access httponly cookies.
+ //
+ // The returned cookies are ordered by longest path, then earliest
+ // creation date.
+ //
+ // TODO(mkwst): This method is deprecated; callsites should be updated to
+ // use 'GetCookieListWithOptionsAsync'.
virtual void GetCookiesWithOptionsAsync(
const GURL& url,
const CookieOptions& options,
const GetCookiesCallback& callback) = 0;
- // Returns all matching cookies without marking them as accessed,
- // including HTTP only cookies.
- virtual void GetAllCookiesForURLAsync(
+ // Obtains a CookieList for the given |url| and |options|. The returned
+ // cookies are passed into |callback|, ordered by longest path, then earliest
+ // creation date.
+ virtual void GetCookieListWithOptionsAsync(
const GURL& url,
+ const CookieOptions& options,
const GetCookieListCallback& callback) = 0;
- // Deletes the passed in cookie for the specified URL.
+ // Returns all cookies associated with |url|, including http-only, and
+ // same-site cookies. The returned cookies are ordered by longest path, then
+ // by earliest creation date, and are not marked as having been accessed.
+ //
+ // TODO(mkwst): This method is deprecated, and should be removed, either by
+ // updating callsites to use 'GetCookieListWithOptionsAsync' with an explicit
+ // CookieOptions, or by changing CookieOptions' defaults.
+ void GetAllCookiesForURLAsync(const GURL& url,
+ const GetCookieListCallback& callback);
+
+ // Returns all the cookies, for use in management UI, etc. This does not mark
+ // the cookies as having been accessed. The returned cookies are ordered by
+ // longest path, then by earliest creation date.
+ virtual void GetAllCookiesAsync(const GetCookieListCallback& callback) = 0;
+
+ // Deletes all cookies that might apply to |url| that have |cookie_name|.
virtual void DeleteCookieAsync(const GURL& url,
const std::string& cookie_name,
const base::Closure& callback) = 0;
+ // Deletes one specific cookie. |cookie| must have been returned by a previous
+ // query on this CookieStore. Invokes |callback| with 1 if a cookie was
+ // deleted, 0 otherwise.
+ virtual void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+ const DeleteCallback& callback) = 0;
+
// 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.
@@ -93,8 +169,17 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
virtual void DeleteSessionCookiesAsync(const DeleteCallback&) = 0;
- // Returns the underlying CookieMonster.
- virtual CookieMonster* GetCookieMonster() = 0;
+ // Deletes all cookies in the store.
+ void DeleteAllAsync(const DeleteCallback& callback);
+
+ // Flush the backing store (if any) to disk and post the given callback when
+ // done.
+ virtual void FlushStore(const base::Closure& callback) = 0;
+
+ // Protects session cookies from deletion on shutdown, if the underlying
+ // CookieStore implemention is currently configured to store them to disk.
+ // Otherwise, does nothing.
+ virtual void SetForceKeepSessionState();
// Add a callback to be notified when the set of cookies named |name| that
// would be sent for a request to |url| changes. The returned handle is
@@ -117,10 +202,16 @@ class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
const std::string& name,
const CookieChangedCallback& callback) = 0;
+ // Returns true if this cookie store is ephemeral, and false if it is backed
+ // by some sort of persistence layer.
+ // TODO(nharper): Remove this method once crbug.com/548423 has been closed.
+ virtual bool IsEphemeral() = 0;
+ void SetChannelIDServiceID(int id);
+ int GetChannelIDServiceID();
+
protected:
- friend class base::RefCountedThreadSafe<CookieStore>;
CookieStore();
- virtual ~CookieStore();
+ int channel_id_service_id_;
};
} // namespace net
diff --git a/chromium/net/cookies/cookie_store_test_callbacks.cc b/chromium/net/cookies/cookie_store_test_callbacks.cc
index 491fe0e8bf9..9e36e706201 100644
--- a/chromium/net/cookies/cookie_store_test_callbacks.cc
+++ b/chromium/net/cookies/cookie_store_test_callbacks.cc
@@ -13,18 +13,12 @@
namespace net {
CookieCallback::CookieCallback(base::Thread* run_in_thread)
- : did_run_(false),
- run_in_thread_(run_in_thread),
- run_in_loop_(NULL),
- parent_loop_(base::MessageLoop::current()),
- loop_to_quit_(base::MessageLoop::current()) {}
+ : run_in_thread_(run_in_thread), run_in_loop_(NULL) {}
CookieCallback::CookieCallback()
- : did_run_(false),
- run_in_thread_(NULL),
- run_in_loop_(base::MessageLoop::current()),
- parent_loop_(NULL),
- loop_to_quit_(base::MessageLoop::current()) {}
+ : run_in_thread_(NULL), run_in_loop_(base::MessageLoop::current()) {}
+
+CookieCallback::~CookieCallback() {}
void CookieCallback::CallbackEpilogue() {
base::MessageLoop* expected_loop = NULL;
@@ -36,10 +30,12 @@ void CookieCallback::CallbackEpilogue() {
}
ASSERT_TRUE(expected_loop != NULL);
- did_run_ = true;
EXPECT_EQ(expected_loop, base::MessageLoop::current());
- loop_to_quit_->task_runner()->PostTask(
- FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
+ loop_to_quit_.Quit();
+}
+
+void CookieCallback::WaitUntilDone() {
+ loop_to_quit_.Run();
}
StringResultCookieCallback::StringResultCookieCallback() {}
@@ -51,4 +47,15 @@ NoResultCookieCallback::NoResultCookieCallback() {}
NoResultCookieCallback::NoResultCookieCallback(base::Thread* run_in_thread)
: CookieCallback(run_in_thread) {}
+GetCookieListCallback::GetCookieListCallback() {}
+GetCookieListCallback::GetCookieListCallback(base::Thread* run_in_thread)
+ : CookieCallback(run_in_thread) {}
+
+GetCookieListCallback::~GetCookieListCallback() {}
+
+void GetCookieListCallback::Run(const CookieList& cookies) {
+ cookies_ = cookies;
+ CallbackEpilogue();
+}
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_store_test_callbacks.h b/chromium/net/cookies/cookie_store_test_callbacks.h
index eccdf1bff26..207eb02f28b 100644
--- a/chromium/net/cookies/cookie_store_test_callbacks.h
+++ b/chromium/net/cookies/cookie_store_test_callbacks.h
@@ -8,6 +8,8 @@
#include <string>
#include <vector>
+#include "base/run_loop.h"
+#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_store.h"
namespace base {
@@ -22,28 +24,27 @@ namespace net {
// quit to the thread in which it was constructed.
class CookieCallback {
public:
- // Indicates whether the callback has been called.
- bool did_run() { return did_run_; }
+ // Waits until the callback is invoked.
+ void WaitUntilDone();
protected:
- // Constructs a callback that expects to be called in the given thread and
- // will, upon execution, send a QUIT to the constructing thread.
+ // Constructs a callback that expects to be called in the given thread.
explicit CookieCallback(base::Thread* run_in_thread);
// Constructs a callback that expects to be called in current thread and will
// send a QUIT to the constructing thread.
CookieCallback();
+ ~CookieCallback();
+
// Tests whether the current thread was the caller's thread.
// Sends a QUIT to the constructing thread.
void CallbackEpilogue();
private:
- bool did_run_;
base::Thread* run_in_thread_;
base::MessageLoop* run_in_loop_;
- base::MessageLoop* parent_loop_;
- base::MessageLoop* loop_to_quit_;
+ base::RunLoop loop_to_quit_;
};
// Callback implementations for the asynchronous CookieStore methods.
@@ -94,6 +95,21 @@ class NoResultCookieCallback : public CookieCallback {
}
};
+class GetCookieListCallback : public CookieCallback {
+ public:
+ GetCookieListCallback();
+ explicit GetCookieListCallback(base::Thread* run_in_thread);
+
+ ~GetCookieListCallback();
+
+ void Run(const CookieList& cookies);
+
+ const CookieList& cookies() { return cookies_; }
+
+ private:
+ CookieList cookies_;
+};
+
} // namespace net
#endif // NET_COOKIES_COOKIE_STORE_TEST_CALLBACKS_H_
diff --git a/chromium/net/cookies/cookie_store_test_helpers.cc b/chromium/net/cookies/cookie_store_test_helpers.cc
index e75039c1484..d2dc2106192 100644
--- a/chromium/net/cookies/cookie_store_test_helpers.cc
+++ b/chromium/net/cookies/cookie_store_test_helpers.cc
@@ -34,10 +34,9 @@ namespace net {
const int kDelayedTime = 0;
DelayedCookieMonster::DelayedCookieMonster()
- : cookie_monster_(new CookieMonster(NULL, NULL)),
- did_run_(false),
- result_(false) {
-}
+ : cookie_monster_(new CookieMonster(nullptr, nullptr)),
+ did_run_(false),
+ result_(false) {}
DelayedCookieMonster::~DelayedCookieMonster() {
}
@@ -53,6 +52,12 @@ void DelayedCookieMonster::GetCookiesWithOptionsInternalCallback(
did_run_ = true;
}
+void DelayedCookieMonster::GetCookieListWithOptionsInternalCallback(
+ const CookieList& cookie_list) {
+ cookie_list_ = cookie_list;
+ did_run_ = true;
+}
+
void DelayedCookieMonster::SetCookieWithOptionsAsync(
const GURL& url,
const std::string& cookie_line,
@@ -70,6 +75,24 @@ void DelayedCookieMonster::SetCookieWithOptionsAsync(
base::TimeDelta::FromMilliseconds(kDelayedTime));
}
+void DelayedCookieMonster::SetCookieWithDetailsAsync(
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ bool enforce_strict_secure,
+ CookiePriority priority,
+ const SetCookiesCallback& callback) {
+ NOTREACHED();
+}
+
void DelayedCookieMonster::GetCookiesWithOptionsAsync(
const GURL& url,
const CookieOptions& options,
@@ -87,10 +110,26 @@ void DelayedCookieMonster::GetCookiesWithOptionsAsync(
base::TimeDelta::FromMilliseconds(kDelayedTime));
}
-void DelayedCookieMonster::GetAllCookiesForURLAsync(
+void DelayedCookieMonster::GetCookieListWithOptionsAsync(
const GURL& url,
+ const CookieOptions& options,
+ const CookieMonster::GetCookieListCallback& callback) {
+ did_run_ = false;
+ cookie_monster_->GetCookieListWithOptionsAsync(
+ url, options,
+ base::Bind(
+ &DelayedCookieMonster::GetCookieListWithOptionsInternalCallback,
+ base::Unretained(this)));
+ DCHECK_EQ(did_run_, true);
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&DelayedCookieMonster::InvokeGetCookieListCallback,
+ base::Unretained(this), callback),
+ base::TimeDelta::FromMilliseconds(kDelayedTime));
+}
+
+void DelayedCookieMonster::GetAllCookiesAsync(
const GetCookieListCallback& callback) {
- cookie_monster_->GetAllCookiesForURLAsync(url, callback);
+ cookie_monster_->GetAllCookiesAsync(callback);
}
void DelayedCookieMonster::InvokeSetCookiesCallback(
@@ -105,6 +144,12 @@ void DelayedCookieMonster::InvokeGetCookieStringCallback(
callback.Run(cookie_);
}
+void DelayedCookieMonster::InvokeGetCookieListCallback(
+ const CookieMonster::GetCookieListCallback& callback) {
+ if (!callback.is_null())
+ callback.Run(cookie_list_);
+}
+
bool DelayedCookieMonster::SetCookieWithOptions(
const GURL& url,
const std::string& cookie_line,
@@ -131,6 +176,12 @@ void DelayedCookieMonster::DeleteCookieAsync(const GURL& url,
ADD_FAILURE();
}
+void DelayedCookieMonster::DeleteCanonicalCookieAsync(
+ const CanonicalCookie& cookie,
+ const DeleteCallback& callback) {
+ ADD_FAILURE();
+}
+
void DelayedCookieMonster::DeleteAllCreatedBetweenAsync(
const base::Time& delete_begin,
const base::Time& delete_end,
@@ -150,8 +201,8 @@ void DelayedCookieMonster::DeleteSessionCookiesAsync(const DeleteCallback&) {
ADD_FAILURE();
}
-CookieMonster* DelayedCookieMonster::GetCookieMonster() {
- return cookie_monster_.get();
+void DelayedCookieMonster::FlushStore(const base::Closure& callback) {
+ ADD_FAILURE();
}
scoped_ptr<CookieStore::CookieChangedSubscription>
@@ -163,6 +214,10 @@ DelayedCookieMonster::AddCallbackForCookie(
return scoped_ptr<CookieStore::CookieChangedSubscription>();
}
+bool DelayedCookieMonster::IsEphemeral() {
+ return true;
+}
+
//
// CookieURLHelper
//
diff --git a/chromium/net/cookies/cookie_store_test_helpers.h b/chromium/net/cookies/cookie_store_test_helpers.h
index 1750c7f07bd..0ebae5bb9e2 100644
--- a/chromium/net/cookies/cookie_store_test_helpers.h
+++ b/chromium/net/cookies/cookie_store_test_helpers.h
@@ -19,6 +19,8 @@ class DelayedCookieMonster : public CookieStore {
public:
DelayedCookieMonster();
+ ~DelayedCookieMonster() override;
+
// Call the asynchronous CookieMonster function, expect it to immediately
// invoke the internal callback.
// Post a delayed task to invoke the original callback with the results.
@@ -29,13 +31,32 @@ class DelayedCookieMonster : public CookieStore {
const CookieOptions& options,
const CookieMonster::SetCookiesCallback& callback) override;
+ void SetCookieWithDetailsAsync(const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ base::Time creation_time,
+ base::Time expiration_time,
+ base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ bool enforce_strict_secure,
+ CookiePriority priority,
+ const SetCookiesCallback& callback) override;
+
void GetCookiesWithOptionsAsync(
const GURL& url,
const CookieOptions& options,
const CookieMonster::GetCookiesCallback& callback) override;
- void GetAllCookiesForURLAsync(const GURL& url,
- const GetCookieListCallback& callback) override;
+ void GetCookieListWithOptionsAsync(
+ const GURL& url,
+ const CookieOptions& options,
+ const GetCookieListCallback& callback) override;
+
+ void GetAllCookiesAsync(const GetCookieListCallback& callback) override;
virtual bool SetCookieWithOptions(const GURL& url,
const std::string& cookie_line,
@@ -51,6 +72,9 @@ class DelayedCookieMonster : public CookieStore {
const std::string& cookie_name,
const base::Closure& callback) override;
+ void DeleteCanonicalCookieAsync(const CanonicalCookie& cookie,
+ const DeleteCallback& callback) override;
+
void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin,
const base::Time& delete_end,
const DeleteCallback& callback) override;
@@ -63,18 +87,21 @@ class DelayedCookieMonster : public CookieStore {
void DeleteSessionCookiesAsync(const DeleteCallback&) override;
- CookieMonster* GetCookieMonster() override;
+ void FlushStore(const base::Closure& callback) override;
scoped_ptr<CookieStore::CookieChangedSubscription>
AddCallbackForCookie(const GURL& url, const std::string& name,
const CookieChangedCallback& callback) override;
+ bool IsEphemeral() override;
+
private:
// Be called immediately from CookieMonster.
void SetCookiesInternalCallback(bool result);
void GetCookiesWithOptionsInternalCallback(const std::string& cookie);
+ void GetCookieListWithOptionsInternalCallback(const CookieList& cookie);
// Invoke the original callbacks.
@@ -84,15 +111,18 @@ class DelayedCookieMonster : public CookieStore {
void InvokeGetCookieStringCallback(
const CookieMonster::GetCookiesCallback& callback);
+ void InvokeGetCookieListCallback(
+ const CookieMonster::GetCookieListCallback& callback);
+
friend class base::RefCountedThreadSafe<DelayedCookieMonster>;
- ~DelayedCookieMonster() override;
- scoped_refptr<CookieMonster> cookie_monster_;
+ scoped_ptr<CookieMonster> cookie_monster_;
bool did_run_;
bool result_;
std::string cookie_;
std::string cookie_line_;
+ CookieList cookie_list_;
};
class CookieURLHelper {
diff --git a/chromium/net/cookies/cookie_store_unittest.cc b/chromium/net/cookies/cookie_store_unittest.cc
new file mode 100644
index 00000000000..739336594a7
--- /dev/null
+++ b/chromium/net/cookies/cookie_store_unittest.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#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"
+#include "url/gurl.h"
+
+namespace net {
+
+namespace {
+
+// Helper for testing BuildCookieLine
+void MatchCookieLineToVector(
+ const std::string& line,
+ const std::vector<scoped_ptr<CanonicalCookie>>& cookies) {
+ // Test the std::vector<CanonicalCookie> variant
+ // ('CookieMonster::CookieList'):
+ std::vector<CanonicalCookie> list;
+ for (const auto& cookie : cookies)
+ list.push_back(*cookie);
+ EXPECT_EQ(line, CookieStore::BuildCookieLine(list));
+
+ // Test the std::vector<CanonicalCookie*> variant
+ // ('CookieMonster::CanonicalCookieVector' (yes, this is absurd)):
+ std::vector<CanonicalCookie*> ptr_list;
+ for (const auto& cookie : cookies)
+ ptr_list.push_back(cookie.get());
+ EXPECT_EQ(line, CookieStore::BuildCookieLine(ptr_list));
+}
+
+} // namespace
+
+TEST(CookieStoreBaseTest, BuildCookieLine) {
+ std::vector<scoped_ptr<CanonicalCookie>> cookies;
+ GURL url("https://example.com/");
+ CookieOptions options;
+ base::Time now = base::Time::Now();
+ MatchCookieLineToVector("", cookies);
+
+ cookies.push_back(CanonicalCookie::Create(url, "A=B", now, options));
+ MatchCookieLineToVector("A=B", cookies);
+ // Nameless cookies are sent back without a prefixed '='.
+ cookies.push_back(CanonicalCookie::Create(url, "C", now, options));
+ MatchCookieLineToVector("A=B; C", cookies);
+ // Cookies separated by ';'.
+ cookies.push_back(CanonicalCookie::Create(url, "D=E", now, options));
+ MatchCookieLineToVector("A=B; C; D=E", cookies);
+ // BuildCookieLine doesn't reorder the list, it relies on the caller to do so.
+ cookies.push_back(CanonicalCookie::Create(
+ url, "F=G", now - base::TimeDelta::FromSeconds(1), options));
+ MatchCookieLineToVector("A=B; C; D=E; F=G", cookies);
+ // BuildCookieLine doesn't deduplicate.
+ cookies.push_back(CanonicalCookie::Create(
+ url, "D=E", now - base::TimeDelta::FromSeconds(2), options));
+ MatchCookieLineToVector("A=B; C; D=E; F=G; D=E", cookies);
+}
+
+} // namespace net
diff --git a/chromium/net/cookies/cookie_store_unittest.h b/chromium/net/cookies/cookie_store_unittest.h
index fb78d89bbbc..ce8008f21b5 100644
--- a/chromium/net/cookies/cookie_store_unittest.h
+++ b/chromium/net/cookies/cookie_store_unittest.h
@@ -41,12 +41,8 @@ const char kValidCookieLine[] = "A=B; path=/";
// The CookieStoreTestTraits must have the following members:
// struct CookieStoreTestTraits {
-// // Factory function.
-// static scoped_refptr<CookieStore> Create();
-//
-// // The cookie store is a CookieMonster. Only used to test
-// // GetCookieMonster().
-// static const bool is_cookie_monster;
+// // Factory function. Will be called at most once per test.
+// static scoped_ptr<CookieStore> Create();
//
// // The cookie store supports cookies with the exclude_httponly() option.
// static const bool supports_http_only;
@@ -84,7 +80,9 @@ class CookieStoreTest : public testing::Test {
ws_www_google_("ws://www.google.izzle"),
wss_www_google_("wss://www.google.izzle"),
www_google_foo_("http://www.google.izzle/foo"),
- www_google_bar_("http://www.google.izzle/bar") {
+ www_google_bar_("http://www.google.izzle/bar"),
+ http_foo_com_("http://foo.com"),
+ http_bar_com_("http://bar.com") {
// This test may be used outside of the net test suite, and thus may not
// have a message loop.
if (!base::MessageLoop::current())
@@ -102,27 +100,49 @@ class CookieStoreTest : public testing::Test {
CookieOptions options;
if (!CookieStoreTestTraits::supports_http_only)
options.set_include_httponly();
- StringResultCookieCallback callback;
- cs->GetCookiesWithOptionsAsync(
- url, options,
- base::Bind(&StringResultCookieCallback::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
+ return GetCookiesWithOptions(cs, url, options);
}
std::string GetCookiesWithOptions(CookieStore* cs,
const GURL& url,
const CookieOptions& options) {
DCHECK(cs);
- StringResultCookieCallback callback;
- cs->GetCookiesWithOptionsAsync(
- url, options, base::Bind(&StringResultCookieCallback::Run,
- base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
- return callback.result();
+ GetCookieListCallback callback;
+ cs->GetCookieListWithOptionsAsync(
+ url, options,
+ base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return CookieStore::BuildCookieLine(callback.cookies());
+ }
+
+ CookieList GetCookieListWithOptions(CookieStore* cs,
+ const GURL& url,
+ const CookieOptions& options) {
+ DCHECK(cs);
+ GetCookieListCallback callback;
+ cs->GetCookieListWithOptionsAsync(
+ url, options,
+ base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.cookies();
+ }
+
+ CookieList GetAllCookiesForURL(CookieStore* cs, const GURL& url) {
+ DCHECK(cs);
+ GetCookieListCallback callback;
+ cs->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.cookies();
+ }
+
+ CookieList GetAllCookies(CookieStore* cs) {
+ DCHECK(cs);
+ GetCookieListCallback callback;
+ cs->GetAllCookiesAsync(
+ base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.cookies();
}
bool SetCookieWithOptions(CookieStore* cs,
@@ -136,8 +156,32 @@ class CookieStoreTest : public testing::Test {
base::Bind(
&ResultSavingCookieCallback<bool>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
+ return callback.result();
+ }
+
+ bool SetCookieWithDetails(CookieStore* cs,
+ const GURL& url,
+ const std::string& name,
+ const std::string& value,
+ const std::string& domain,
+ const std::string& path,
+ const base::Time creation_time,
+ const base::Time expiration_time,
+ const base::Time last_access_time,
+ bool secure,
+ bool http_only,
+ CookieSameSite same_site,
+ CookiePriority priority) {
+ DCHECK(cs);
+ ResultSavingCookieCallback<bool> callback;
+ cs->SetCookieWithDetailsAsync(
+ url, name, value, domain, path, creation_time, expiration_time,
+ last_access_time, secure, http_only, same_site,
+ false /* enforces strict secure cookies */, priority,
+ base::Bind(&ResultSavingCookieCallback<bool>::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
return callback.result();
}
@@ -171,8 +215,17 @@ class CookieStoreTest : public testing::Test {
cs->DeleteCookieAsync(
url, cookie_name,
base::Bind(&NoResultCookieCallback::Run, base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
+ }
+
+ int DeleteCanonicalCookie(CookieStore* cs, const CanonicalCookie& cookie) {
+ DCHECK(cs);
+ ResultSavingCookieCallback<int> callback;
+ cs->DeleteCanonicalCookieAsync(
+ cookie, base::Bind(&ResultSavingCookieCallback<int>::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.result();
}
int DeleteCreatedBetween(CookieStore* cs,
@@ -185,8 +238,7 @@ class CookieStoreTest : public testing::Test {
base::Bind(
&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
@@ -201,8 +253,7 @@ class CookieStoreTest : public testing::Test {
base::Bind(
&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
@@ -213,23 +264,24 @@ class CookieStoreTest : public testing::Test {
base::Bind(
&ResultSavingCookieCallback<int>::Run,
base::Unretained(&callback)));
- RunFor(kTimeout);
- EXPECT_TRUE(callback.did_run());
+ callback.WaitUntilDone();
return callback.result();
}
- void RunFor(int ms) {
- // Runs the test thread message loop for up to |ms| milliseconds.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&base::MessageLoop::QuitWhenIdle,
- weak_factory_->GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(ms));
- base::MessageLoop::current()->Run();
- weak_factory_->InvalidateWeakPtrs();
+ int DeleteAll(CookieStore* cs) {
+ DCHECK(cs);
+ ResultSavingCookieCallback<int> callback;
+ cs->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.result();
}
- scoped_refptr<CookieStore> GetCookieStore() {
- return CookieStoreTestTraits::Create();
+ // Returns the CookieStore for the test - each test only uses one CookieStore.
+ CookieStore* GetCookieStore() {
+ if (!cookie_store_)
+ cookie_store_ = CookieStoreTestTraits::Create();
+ return cookie_store_.get();
}
// Compares two cookie lines.
@@ -264,6 +316,8 @@ class CookieStoreTest : public testing::Test {
const CookieURLHelper wss_www_google_;
const CookieURLHelper www_google_foo_;
const CookieURLHelper www_google_bar_;
+ const CookieURLHelper http_foo_com_;
+ const CookieURLHelper http_bar_com_;
scoped_ptr<base::WeakPtrFactory<base::MessageLoop> > weak_factory_;
scoped_ptr<base::MessageLoop> message_loop_;
@@ -277,383 +331,467 @@ class CookieStoreTest : public testing::Test {
EXPECT_TRUE(tokens.insert(tokenizer.token()).second);
return tokens;
}
+
+ scoped_ptr<CookieStore> cookie_store_;
};
TYPED_TEST_CASE_P(CookieStoreTest);
-TYPED_TEST_P(CookieStoreTest, TypeTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_EQ(cs->GetCookieMonster(),
- (TypeParam::is_cookie_monster) ?
- static_cast<CookieMonster*>(cs.get()) : NULL);
+TYPED_TEST_P(CookieStoreTest, SetCookieWithDetailsAsync) {
+ CookieStore* cs = this->GetCookieStore();
+
+ base::Time two_hours_ago = base::Time::Now() - base::TimeDelta::FromHours(2);
+ base::Time one_hour_ago = base::Time::Now() - base::TimeDelta::FromHours(1);
+ base::Time one_hour_from_now =
+ base::Time::Now() + base::TimeDelta::FromHours(1);
+
+ EXPECT_TRUE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A", "B", std::string(), "/foo",
+ one_hour_ago, one_hour_from_now, base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ // Note that for the creation time to be set exactly, without modification,
+ // it must be different from the one set by the line above.
+ EXPECT_TRUE(this->SetCookieWithDetails(
+ cs, this->www_google_bar_.url(), "C", "D", this->www_google_bar_.domain(),
+ "/bar", two_hours_ago, base::Time(), one_hour_ago, false, true,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_TRUE(this->SetCookieWithDetails(
+ cs, this->http_www_google_.url(), "E", "F", std::string(), std::string(),
+ base::Time(), base::Time(), base::Time(), true, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+
+ // Test that malformed attributes fail to set the cookie.
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), " A", "B", std::string(), "/foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A;", "B", std::string(), "/foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A=", "B", std::string(), "/foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A", "B", "google.ozzzzzzle", "foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+ EXPECT_FALSE(this->SetCookieWithDetails(
+ cs, this->www_google_foo_.url(), "A=", "B", std::string(), "foo",
+ base::Time(), base::Time(), base::Time(), false, false,
+ CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT));
+
+ // Get all the cookies for a given URL, regardless of properties. This 'get()'
+ // operation shouldn't update the access time, as the test checks that the
+ // access time is set properly upon creation. Updating the access time would
+ // make that difficult.
+ CookieOptions options;
+ options.set_include_httponly();
+ options.set_same_site_cookie_mode(
+ CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ options.set_do_not_update_access_time();
+
+ CookieList cookies =
+ this->GetCookieListWithOptions(cs, this->www_google_foo_.url(), options);
+ CookieList::iterator it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ("A", it->Name());
+ EXPECT_EQ("B", it->Value());
+ EXPECT_EQ(this->www_google_foo_.host(), it->Domain());
+ EXPECT_EQ("/foo", it->Path());
+ EXPECT_EQ(one_hour_ago, it->CreationDate());
+ EXPECT_TRUE(it->IsPersistent());
+ // Expect expiration date is in the right range. Some cookie implementations
+ // may not record it with millisecond accuracy.
+ EXPECT_LE((one_hour_from_now - it->ExpiryDate()).magnitude().InSeconds(), 5);
+ // Some CookieStores don't store last access date.
+ if (!it->LastAccessDate().is_null())
+ EXPECT_EQ(one_hour_ago, it->LastAccessDate());
+ EXPECT_FALSE(it->IsSecure());
+ EXPECT_FALSE(it->IsHttpOnly());
+
+ ASSERT_TRUE(++it == cookies.end());
+
+ // Verify that the cookie was set as 'httponly' by passing in a CookieOptions
+ // that excludes them and getting an empty result.
+ if (TypeParam::supports_http_only) {
+ cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+ CookieOptions());
+ it = cookies.begin();
+ ASSERT_TRUE(it == cookies.end());
+ }
+
+ // Get the cookie using the wide open |options|:
+ cookies =
+ this->GetCookieListWithOptions(cs, this->www_google_bar_.url(), options);
+ it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ("C", it->Name());
+ EXPECT_EQ("D", it->Value());
+ EXPECT_EQ(this->www_google_bar_.Format(".%D"), it->Domain());
+ EXPECT_EQ("/bar", it->Path());
+ EXPECT_EQ(two_hours_ago, it->CreationDate());
+ EXPECT_FALSE(it->IsPersistent());
+ // Some CookieStores don't store last access date.
+ if (!it->LastAccessDate().is_null())
+ EXPECT_EQ(one_hour_ago, it->LastAccessDate());
+ EXPECT_FALSE(it->IsSecure());
+ EXPECT_TRUE(it->IsHttpOnly());
+
+ EXPECT_TRUE(++it == cookies.end());
+
+ cookies = this->GetCookieListWithOptions(cs, this->https_www_google_.url(),
+ options);
+ it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ("E", it->Name());
+ EXPECT_EQ("F", it->Value());
+ EXPECT_EQ("/", it->Path());
+ EXPECT_EQ(this->https_www_google_.host(), it->Domain());
+ // Cookie should have its creation time set, and be in a reasonable range.
+ EXPECT_LE((base::Time::Now() - it->CreationDate()).magnitude().InMinutes(),
+ 2);
+ EXPECT_FALSE(it->IsPersistent());
+ // Some CookieStores don't store last access date.
+ if (!it->LastAccessDate().is_null())
+ EXPECT_EQ(it->CreationDate(), it->LastAccessDate());
+ EXPECT_TRUE(it->IsSecure());
+ EXPECT_FALSE(it->IsHttpOnly());
+
+ EXPECT_TRUE(++it == cookies.end());
}
TYPED_TEST_P(CookieStoreTest, DomainTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
EXPECT_TRUE(
- this->SetCookie(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(),
this->http_www_google_.Format("C=D; domain=.%D")));
- this->MatchCookieLines(
- "A=B; C=D", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; C=D",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Verify that A=B was set as a host cookie rather than a domain
// cookie -- should not be accessible from a sub sub-domain.
this->MatchCookieLines(
- "C=D",
- this->GetCookies(
- cs.get(), GURL(this->http_www_google_.Format("http://foo.www.%D"))));
+ "C=D", this->GetCookies(
+ cs, GURL(this->http_www_google_.Format("http://foo.www.%D"))));
// Test and make sure we find domain cookies on the same domain.
EXPECT_TRUE(
- this->SetCookie(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(),
this->http_www_google_.Format("E=F; domain=.www.%D")));
- this->MatchCookieLines(
- "A=B; C=D; E=F",
- this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; C=D; E=F",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Test setting a domain= that doesn't start w/ a dot, should
// treat it as a domain cookie, as if there was a pre-pended dot.
EXPECT_TRUE(
- this->SetCookie(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(),
this->http_www_google_.Format("G=H; domain=www.%D")));
- this->MatchCookieLines(
- "A=B; C=D; E=F; G=H",
- this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; C=D; E=F; G=H",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Test domain enforcement, should fail on a sub-domain or something too deep.
EXPECT_FALSE(
- this->SetCookie(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(),
this->http_www_google_.Format("I=J; domain=.%R")));
this->MatchCookieLines(
std::string(),
- this->GetCookies(cs.get(),
- GURL(this->http_www_google_.Format("http://a.%R"))));
+ this->GetCookies(cs, GURL(this->http_www_google_.Format("http://a.%R"))));
EXPECT_FALSE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
this->http_www_google_.Format("K=L; domain=.bla.www.%D")));
this->MatchCookieLines(
"C=D; E=F; G=H",
this->GetCookies(
- cs.get(), GURL(this->http_www_google_.Format("http://bla.www.%D"))));
- this->MatchCookieLines(
- "A=B; C=D; E=F; G=H",
- this->GetCookies(cs.get(), this->http_www_google_.url()));
+ cs, GURL(this->http_www_google_.Format("http://bla.www.%D"))));
+ this->MatchCookieLines("A=B; C=D; E=F; G=H",
+ this->GetCookies(cs, this->http_www_google_.url()));
}
// FireFox recognizes domains containing trailing periods as valid.
// IE and Safari do not. Assert the expected policy here.
TYPED_TEST_P(CookieStoreTest, DomainWithTrailingDotTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_FALSE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(),
"a=1; domain=.www.google.com."));
- EXPECT_FALSE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(),
"b=2; domain=.www.google.com.."));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
}
// Test that cookies can bet set on higher level domains.
-// http://b/issue?id=896491
TYPED_TEST_P(CookieStoreTest, ValidSubdomainTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
GURL url_abcd("http://a.b.c.d.com");
GURL url_bcd("http://b.c.d.com");
GURL url_cd("http://c.d.com");
GURL url_d("http://d.com");
- EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "a=1; domain=.a.b.c.d.com"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "b=2; domain=.b.c.d.com"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "c=3; domain=.c.d.com"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "d=4; domain=.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_abcd, "a=1; domain=.a.b.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_abcd, "b=2; domain=.b.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_abcd, "c=3; domain=.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_abcd, "d=4; domain=.d.com"));
- this->MatchCookieLines("a=1; b=2; c=3; d=4",
- this->GetCookies(cs.get(), url_abcd));
- this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs.get(), url_bcd));
- this->MatchCookieLines("c=3; d=4", this->GetCookies(cs.get(), url_cd));
- this->MatchCookieLines("d=4", this->GetCookies(cs.get(), url_d));
+ this->MatchCookieLines("a=1; b=2; c=3; d=4", this->GetCookies(cs, url_abcd));
+ this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs, url_bcd));
+ this->MatchCookieLines("c=3; d=4", this->GetCookies(cs, url_cd));
+ this->MatchCookieLines("d=4", this->GetCookies(cs, url_d));
// Check that the same cookie can exist on different sub-domains.
- EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=bcd; domain=.b.c.d.com"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=cd; domain=.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_bcd, "X=bcd; domain=.b.c.d.com"));
+ EXPECT_TRUE(this->SetCookie(cs, url_bcd, "X=cd; domain=.c.d.com"));
this->MatchCookieLines("b=2; c=3; d=4; X=bcd; X=cd",
- this->GetCookies(cs.get(), url_bcd));
- this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs.get(), url_cd));
+ this->GetCookies(cs, url_bcd));
+ this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs, url_cd));
}
// Test that setting a cookie which specifies an invalid domain has
// no side-effect. An invalid domain in this context is one which does
// not match the originating domain.
-// http://b/issue?id=896472
TYPED_TEST_P(CookieStoreTest, InvalidDomainTest) {
- {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url_foobar("http://foo.bar.com");
-
- // More specific sub-domain than allowed.
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "a=1; domain=.yo.foo.bar.com"));
-
- EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "b=2; domain=.foo.com"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "c=3; domain=.bar.foo.com"));
-
- // Different TLD, but the rest is a substring.
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "d=4; domain=.foo.bar.com.net"));
-
- // A substring that isn't really a parent domain.
- EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "e=5; domain=ar.com"));
-
- // Completely invalid domains:
- EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "f=6; domain=."));
- EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "g=7; domain=/"));
- EXPECT_FALSE(this->SetCookie(
- cs.get(), url_foobar, "h=8; domain=http://foo.bar.com"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "i=9; domain=..foo.bar.com"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "j=10; domain=..bar.com"));
-
- // Make sure there isn't something quirky in the domain canonicalization
- // that supports full URL semantics.
- EXPECT_FALSE(this->SetCookie(
- cs.get(), url_foobar, "k=11; domain=.foo.bar.com?blah"));
- EXPECT_FALSE(this->SetCookie(
- cs.get(), url_foobar, "l=12; domain=.foo.bar.com/blah"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "m=13; domain=.foo.bar.com:80"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "n=14; domain=.foo.bar.com:"));
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foobar, "o=15; domain=.foo.bar.com#sup"));
+ CookieStore* cs = this->GetCookieStore();
+ GURL url_foobar("http://foo.bar.com");
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), url_foobar));
- }
+ // More specific sub-domain than allowed.
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "a=1; domain=.yo.foo.bar.com"));
- {
- // Make sure the cookie code hasn't gotten its subdomain string handling
- // reversed, missed a suffix check, etc. It's important here that the two
- // hosts below have the same domain + registry.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url_foocom("http://foo.com.com");
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_foocom, "a=1; domain=.foo.com.com.com"));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), url_foocom));
- }
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "b=2; domain=.foo.com"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "c=3; domain=.bar.foo.com"));
+
+ // Different TLD, but the rest is a substring.
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "d=4; domain=.foo.bar.com.net"));
+
+ // A substring that isn't really a parent domain.
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "e=5; domain=ar.com"));
+
+ // Completely invalid domains:
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "f=6; domain=."));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "g=7; domain=/"));
+ EXPECT_FALSE(
+ this->SetCookie(cs, url_foobar, "h=8; domain=http://foo.bar.com"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "i=9; domain=..foo.bar.com"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "j=10; domain=..bar.com"));
+
+ // Make sure there isn't something quirky in the domain canonicalization
+ // that supports full URL semantics.
+ EXPECT_FALSE(
+ this->SetCookie(cs, url_foobar, "k=11; domain=.foo.bar.com?blah"));
+ EXPECT_FALSE(
+ this->SetCookie(cs, url_foobar, "l=12; domain=.foo.bar.com/blah"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "m=13; domain=.foo.bar.com:80"));
+ EXPECT_FALSE(this->SetCookie(cs, url_foobar, "n=14; domain=.foo.bar.com:"));
+ EXPECT_FALSE(
+ this->SetCookie(cs, url_foobar, "o=15; domain=.foo.bar.com#sup"));
+
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url_foobar));
}
-// Test the behavior of omitting dot prefix from domain, should
-// function the same as FireFox.
-// http://b/issue?id=889898
-TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotTest) {
- { // The omission of dot results in setting a domain cookie.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url_hosted("http://manage.hosted.filefront.com");
- GURL url_filefront("http://www.filefront.com");
- EXPECT_TRUE(
- this->SetCookie(cs.get(), url_hosted, "sawAd=1; domain=filefront.com"));
- this->MatchCookieLines("sawAd=1", this->GetCookies(cs.get(), url_hosted));
- this->MatchCookieLines("sawAd=1",
- this->GetCookies(cs.get(), url_filefront));
- }
+// Make sure the cookie code hasn't gotten its subdomain string handling
+// reversed, missed a suffix check, etc. It's important here that the two
+// hosts below have the same domain + registry.
+TYPED_TEST_P(CookieStoreTest, InvalidDomainSameDomainAndRegistry) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url_foocom("http://foo.com.com");
+ EXPECT_FALSE(this->SetCookie(cs, url_foocom, "a=1; domain=.foo.com.com.com"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url_foocom));
+}
- { // Even when the domains match exactly, don't consider it host cookie.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://www.google.com");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=www.google.com"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- this->MatchCookieLines(
- "a=1", this->GetCookies(cs.get(), GURL("http://sub.www.google.com")));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://something-else.com")));
- }
+// Setting the domain without a dot on a parent domain should add a domain
+// cookie.
+TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotParentDomain) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url_hosted("http://manage.hosted.filefront.com");
+ GURL url_filefront("http://www.filefront.com");
+ EXPECT_TRUE(this->SetCookie(cs, url_hosted, "sawAd=1; domain=filefront.com"));
+ this->MatchCookieLines("sawAd=1", this->GetCookies(cs, url_hosted));
+ this->MatchCookieLines("sawAd=1", this->GetCookies(cs, url_filefront));
+}
+
+// Even when the specified domain matches the domain of the URL exactly, treat
+// it as setting a domain cookie.
+TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotSameDomain) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://www.google.com");
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=www.google.com"));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+ this->MatchCookieLines(
+ "a=1", this->GetCookies(cs, GURL("http://sub.www.google.com")));
+ this->MatchCookieLines(
+ std::string(), this->GetCookies(cs, GURL("http://something-else.com")));
}
// Test that the domain specified in cookie string is treated case-insensitive
-// http://b/issue?id=896475.
TYPED_TEST_P(CookieStoreTest, CaseInsensitiveDomainTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
GURL url("http://www.google.com");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=.GOOGLE.COM"));
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "b=2; domain=.wWw.gOOgLE.coM"));
- this->MatchCookieLines("a=1; b=2", this->GetCookies(cs.get(), url));
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=.GOOGLE.COM"));
+ EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.wWw.gOOgLE.coM"));
+ this->MatchCookieLines("a=1; b=2", this->GetCookies(cs, url));
}
TYPED_TEST_P(CookieStoreTest, TestIpAddress) {
GURL url_ip("http://1.2.3.4/weee");
- {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, kValidCookieLine));
- this->MatchCookieLines("A=B", this->GetCookies(cs.get(), url_ip));
- }
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_TRUE(this->SetCookie(cs, url_ip, kValidCookieLine));
+ this->MatchCookieLines("A=B", this->GetCookies(cs, url_ip));
+}
- { // IP addresses should not be able to set domain cookies.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=.1.2.3.4"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "c=3; domain=.3.4"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
- // It should be allowed to set a cookie if domain= matches the IP address
- // exactly. This matches IE/Firefox, even though it seems a bit wrong.
- EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.3"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
- EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.4"));
- this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_ip));
- }
+// IP addresses should not be able to set domain cookies.
+TYPED_TEST_P(CookieStoreTest, TestIpAddressNoDomainCookies) {
+ GURL url_ip("http://1.2.3.4/weee");
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_FALSE(this->SetCookie(cs, url_ip, "b=2; domain=.1.2.3.4"));
+ EXPECT_FALSE(this->SetCookie(cs, url_ip, "c=3; domain=.3.4"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url_ip));
+ // It should be allowed to set a cookie if domain= matches the IP address
+ // exactly. This matches IE/Firefox, even though it seems a bit wrong.
+ EXPECT_FALSE(this->SetCookie(cs, url_ip, "b=2; domain=1.2.3.3"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url_ip));
+ EXPECT_TRUE(this->SetCookie(cs, url_ip, "b=2; domain=1.2.3.4"));
+ this->MatchCookieLines("b=2", this->GetCookies(cs, url_ip));
}
-// Test host cookies, and setting of cookies on TLD.
-TYPED_TEST_P(CookieStoreTest, TestNonDottedAndTLD) {
- if (TypeParam::supports_non_dotted_domains) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://com/");
- // Allow setting on "com", (but only as a host cookie).
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.com"));
-
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- // Make sure it doesn't show up for a normal .com, it should be a host
- // not a domain cookie.
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL("http://.com/")));
- }
+// Test a TLD setting cookies on itself.
+TYPED_TEST_P(CookieStoreTest, TestTLD) {
+ if (!TypeParam::supports_non_dotted_domains)
+ return;
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://com/");
- if (TypeParam::supports_non_dotted_domains) {
- // Exact matches between the domain attribute and the host are treated as
- // host cookies, not domain cookies.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://com/");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=com"));
+ // Allow setting on "com", (but only as a host cookie).
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
+ // Domain cookies can't be set.
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.com"));
+ // Exact matches between the domain attribute and the host are treated as
+ // host cookies, not domain cookies.
+ EXPECT_TRUE(this->SetCookie(cs, url, "c=3; domain=com"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- // Make sure it doesn't show up for a normal .com, it should be a host
- // not a domain cookie.
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL("http://.com/")));
- }
+ this->MatchCookieLines("a=1; c=3", this->GetCookies(cs, url));
- {
- // http://com. should be treated the same as http://com.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://com./index.html");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(),
- GURL("http://hopefully-no-cookies.com./")));
- }
+ // Make sure they don't show up for a normal .com, they should be host,
+ // domain, cookies.
+ this->MatchCookieLines(
+ std::string(),
+ this->GetCookies(cs, GURL("http://hopefully-no-cookies.com/")));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, GURL("http://.com/")));
+}
- { // Should not be able to set host cookie from a subdomain.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://a.b");
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.b"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=b"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
- }
+// http://com. should be treated the same as http://com.
+TYPED_TEST_P(CookieStoreTest, TestTLDWithTerminalDot) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://com./index.html");
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.com."));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+ this->MatchCookieLines(
+ std::string(),
+ this->GetCookies(cs, GURL("http://hopefully-no-cookies.com./")));
+}
- { // Same test as above, but explicitly on a known TLD (com).
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://google.com");
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.com"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=com"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
- }
+TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnUnknownTLD) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://a.b");
+ EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.b"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=b"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
+}
- { // Make sure can't set cookie on TLD which is dotted.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://google.co.uk");
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.co.uk"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.uk"));
- this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://something-else.co.uk")));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://something-else.uk")));
- }
+TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnKnownTLD) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://google.com");
+ EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.com"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=com"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
+}
- { // Intranet URLs should only be able to set host cookies.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://b");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
- EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.b"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- }
+TYPED_TEST_P(CookieStoreTest, TestSubdomainSettingCookiesOnKnownDottedTLD) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://google.co.uk");
+ EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.co.uk"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.uk"));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, url));
+ this->MatchCookieLines(
+ std::string(), this->GetCookies(cs, GURL("http://something-else.co.uk")));
+ this->MatchCookieLines(
+ std::string(), this->GetCookies(cs, GURL("http://something-else.uk")));
+}
- if (TypeParam::supports_non_dotted_domains) {
- // Exact matches between the domain attribute and an intranet host are
- // treated as host cookies, not domain cookies.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- GURL url("http://b/");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=b"));
+// Intranet URLs should only be able to set host cookies.
+TYPED_TEST_P(CookieStoreTest, TestSettingCookiesOnUnknownTLD) {
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://b");
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.b"));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+}
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- // Make sure it doesn't show up for an intranet subdomain, it should be a
- // host not a domain cookie.
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.b/")));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL("http://.b/")));
- }
+// Exact matches between the domain attribute and an intranet host are
+// treated as host cookies, not domain cookies.
+TYPED_TEST_P(CookieStoreTest, TestSettingCookiesWithHostDomainOnUnknownTLD) {
+ if (!TypeParam::supports_non_dotted_domains)
+ return;
+ CookieStore* cs = this->GetCookieStore();
+ GURL url("http://b");
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=b"));
+
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+
+ // Make sure it doesn't show up for an intranet subdomain, it should be
+ // a host, not domain, cookie.
+ this->MatchCookieLines(
+ std::string(),
+ this->GetCookies(cs, GURL("http://hopefully-no-cookies.b/")));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, GURL("http://.b/")));
}
// Test reading/writing cookies when the domain ends with a period,
// as in "www.google.com."
TYPED_TEST_P(CookieStoreTest, TestHostEndsWithDot) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
GURL url("http://www.google.com");
GURL url_with_dot("http://www.google.com.");
- EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
+ EXPECT_TRUE(this->SetCookie(cs, url, "a=1"));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
// Do not share cookie space with the dot version of domain.
// Note: this is not what FireFox does, but it _is_ what IE+Safari do.
if (TypeParam::preserves_trailing_dots) {
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
- this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
- EXPECT_TRUE(
- this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
- this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_with_dot));
+ EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.www.google.com."));
+ this->MatchCookieLines("a=1", this->GetCookies(cs, url));
+ EXPECT_TRUE(this->SetCookie(cs, url_with_dot, "b=2; domain=.google.com."));
+ this->MatchCookieLines("b=2", this->GetCookies(cs, url_with_dot));
} else {
- EXPECT_TRUE(
- this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
- this->MatchCookieLines("a=1 b=2", this->GetCookies(cs.get(), url));
+ EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.www.google.com."));
+ this->MatchCookieLines("a=1 b=2", this->GetCookies(cs, url));
// Setting this cookie should fail, since the trailing dot on the domain
// isn't preserved, and then the domain mismatches the URL.
- EXPECT_FALSE(
- this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
+ EXPECT_FALSE(this->SetCookie(cs, url_with_dot, "b=2; domain=.google.com."));
}
// Make sure there weren't any side effects.
this->MatchCookieLines(
std::string(),
- this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
+ this->GetCookies(cs, GURL("http://hopefully-no-cookies.com/")));
this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL("http://.com/")));
+ this->GetCookies(cs, GURL("http://.com/")));
}
TYPED_TEST_P(CookieStoreTest, InvalidScheme) {
if (!TypeParam::filters_schemes)
return;
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_FALSE(
- this->SetCookie(cs.get(), this->ftp_google_.url(), kValidCookieLine));
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_FALSE(this->SetCookie(cs, this->ftp_google_.url(), kValidCookieLine));
}
TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
@@ -663,39 +801,38 @@ TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
const std::string kValidDomainCookieLine =
this->http_www_google_.Format("A=B; path=/; domain=%D");
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
kValidDomainCookieLine));
this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), this->ftp_google_.url()));
+ this->GetCookies(cs, this->ftp_google_.url()));
+ EXPECT_EQ(0U, this->GetCookieListWithOptions(cs, this->ftp_google_.url(),
+ CookieOptions())
+ .size());
}
TYPED_TEST_P(CookieStoreTest, PathTest) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
std::string url("http://www.google.izzle");
- EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=B; path=/wee"));
- this->MatchCookieLines("A=B", this->GetCookies(cs.get(), GURL(url + "/wee")));
- this->MatchCookieLines("A=B",
- this->GetCookies(cs.get(), GURL(url + "/wee/")));
- this->MatchCookieLines("A=B",
- this->GetCookies(cs.get(), GURL(url + "/wee/war")));
+ EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=B; path=/wee"));
+ this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee")));
+ this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/")));
+ this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/war")));
this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), GURL(url + "/wee/war/more/more")));
+ "A=B", this->GetCookies(cs, GURL(url + "/wee/war/more/more")));
if (!TypeParam::has_path_prefix_bug)
this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL(url + "/weehee")));
- this->MatchCookieLines(std::string(),
- this->GetCookies(cs.get(), GURL(url + "/")));
+ this->GetCookies(cs, GURL(url + "/weehee")));
+ this->MatchCookieLines(std::string(), this->GetCookies(cs, GURL(url + "/")));
// If we add a 0 length path, it should default to /
- EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=C; path="));
- this->MatchCookieLines("A=B; A=C",
- this->GetCookies(cs.get(), GURL(url + "/wee")));
- this->MatchCookieLines("A=C", this->GetCookies(cs.get(), GURL(url + "/")));
+ EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=C; path="));
+ this->MatchCookieLines("A=B; A=C", this->GetCookies(cs, GURL(url + "/wee")));
+ this->MatchCookieLines("A=C", this->GetCookies(cs, GURL(url + "/")));
}
TYPED_TEST_P(CookieStoreTest, EmptyExpires) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
CookieOptions options;
if (!TypeParam::supports_http_only)
options.set_include_httponly();
@@ -704,152 +841,168 @@ TYPED_TEST_P(CookieStoreTest, EmptyExpires) {
"ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
std::string cookie_line = "ACSTM=20130308043820420042";
- this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
+ this->SetCookieWithOptions(cs, url, set_cookie_line, options);
this->MatchCookieLines(cookie_line,
- this->GetCookiesWithOptions(cs.get(), url, options));
+ this->GetCookiesWithOptions(cs, url, options));
options.set_server_time(base::Time::Now() - base::TimeDelta::FromHours(1));
- this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
+ this->SetCookieWithOptions(cs, url, set_cookie_line, options);
this->MatchCookieLines(cookie_line,
- this->GetCookiesWithOptions(cs.get(), url, options));
+ this->GetCookiesWithOptions(cs, url, options));
options.set_server_time(base::Time::Now() + base::TimeDelta::FromHours(1));
- this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
+ this->SetCookieWithOptions(cs, url, set_cookie_line, options);
this->MatchCookieLines(cookie_line,
- this->GetCookiesWithOptions(cs.get(), url, options));
+ this->GetCookiesWithOptions(cs, url, options));
}
TYPED_TEST_P(CookieStoreTest, HttpOnlyTest) {
if (!TypeParam::supports_http_only)
return;
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
CookieOptions options;
options.set_include_httponly();
// Create a httponly cookie.
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
"A=B; httponly", options));
// Check httponly read protection.
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B", this->GetCookiesWithOptions(cs.get(), this->http_www_google_.url(),
- options));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B", this->GetCookiesWithOptions(
+ cs, this->http_www_google_.url(), options));
// Check httponly overwrite protection.
- EXPECT_FALSE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=C"));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B", this->GetCookiesWithOptions(cs.get(), this->http_www_google_.url(),
- options));
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
+ EXPECT_FALSE(this->SetCookie(cs, this->http_www_google_.url(), "A=C"));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B", this->GetCookiesWithOptions(
+ cs, this->http_www_google_.url(), options));
+ EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
"A=C", options));
- this->MatchCookieLines(
- "A=C", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=C",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Check httponly create protection.
EXPECT_FALSE(
- this->SetCookie(cs.get(), this->http_www_google_.url(), "B=A; httponly"));
- this->MatchCookieLines(
- "A=C", this->GetCookiesWithOptions(cs.get(), this->http_www_google_.url(),
- options));
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
+ this->SetCookie(cs, this->http_www_google_.url(), "B=A; httponly"));
+ this->MatchCookieLines("A=C", this->GetCookiesWithOptions(
+ cs, this->http_www_google_.url(), options));
+ EXPECT_TRUE(this->SetCookieWithOptions(cs, this->http_www_google_.url(),
"B=A; httponly", options));
- this->MatchCookieLines("A=C; B=A",
- this->GetCookiesWithOptions(
- cs.get(), this->http_www_google_.url(), options));
this->MatchCookieLines(
- "A=C", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ "A=C; B=A",
+ this->GetCookiesWithOptions(cs, this->http_www_google_.url(), options));
+ this->MatchCookieLines("A=C",
+ this->GetCookies(cs, this->http_www_google_.url()));
}
TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
// Create a session cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
- kValidCookieLine));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Max-Age.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; max-age=0"));
- this->MatchCookieLineWithTimeout(cs.get(), this->http_www_google_.url(),
+ this->MatchCookieLineWithTimeout(cs, this->http_www_google_.url(),
std::string());
// Create a session cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
- kValidCookieLine));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Expires.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) +
"; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
// Create a persistent cookie.
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Max-Age.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; max-age=0"));
- this->MatchCookieLineWithTimeout(cs.get(), this->http_www_google_.url(),
+ this->MatchCookieLineWithTimeout(cs, this->http_www_google_.url(),
std::string());
// Create a persistent cookie.
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Expires.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) +
"; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
// Create a persistent cookie.
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Check that it is not deleted with significant enough clock skew.
base::Time server_time;
EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT",
&server_time));
EXPECT_TRUE(this->SetCookieWithServerTime(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
server_time));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Create a persistent cookie.
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete it via Expires, with a unix epoch of 0.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine) +
"; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+}
+
+TYPED_TEST_P(CookieStoreTest, TestDeleteAll) {
+ CookieStore* cs = this->GetCookieStore();
+
+ // Set a session cookie.
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), kValidCookieLine));
+ EXPECT_EQ("A=B", this->GetCookies(cs, this->http_www_google_.url()));
+
+ // Set a persistent cookie.
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
+ "C=D; expires=Mon, 18-Apr-22 22:50:13 GMT"));
+
+ EXPECT_EQ(2u, this->GetAllCookies(cs).size());
+
+ // Delete both, and make sure it works
+ EXPECT_EQ(2, this->DeleteAll(cs));
+ EXPECT_EQ(0u, this->GetAllCookies(cs).size());
}
TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
const base::Time last_month = base::Time::Now() -
base::TimeDelta::FromDays(30);
const base::Time last_minute = base::Time::Now() -
@@ -860,90 +1013,86 @@ TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) {
base::TimeDelta::FromDays(30);
// Add a cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
// Check that the cookie is in the store.
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Remove cookies in empty intervals.
- EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), last_month, last_minute));
- EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), next_minute, next_month));
+ EXPECT_EQ(0, this->DeleteCreatedBetween(cs, last_month, last_minute));
+ EXPECT_EQ(0, this->DeleteCreatedBetween(cs, next_minute, next_month));
// Check that the cookie is still there.
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Remove the cookie with an interval defined by two dates.
- EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, next_minute));
+ EXPECT_EQ(1, this->DeleteCreatedBetween(cs, last_minute, next_minute));
// Check that the cookie disappeared.
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
// Add another cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "C=D"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "C=D"));
// Check that the cookie is in the store.
- this->MatchCookieLines(
- "C=D", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("C=D",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Remove the cookie with a null ending time.
- EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, base::Time()));
+ EXPECT_EQ(1, this->DeleteCreatedBetween(cs, last_minute, base::Time()));
// Check that the cookie disappeared.
- this->MatchCookieLines(
- std::string(), this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
}
TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetweenForHost) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
GURL url_not_google("http://www.notgoogle.com");
base::Time now = base::Time::Now();
// These 3 cookies match the time range and host.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "C=D"));
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "Y=Z"));
+ 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.get(), url_not_google, "E=F"));
+ EXPECT_TRUE(this->SetCookie(cs, url_not_google, "E=F"));
// Delete cookies.
- EXPECT_EQ(
- 3, // Deletes A=B, C=D, Y=Z
- this->DeleteAllCreatedBetweenForHost(cs.get(), now, base::Time::Max(),
- this->http_www_google_.url()));
+ EXPECT_EQ(3, // Deletes A=B, C=D, Y=Z
+ this->DeleteAllCreatedBetweenForHost(cs, now, base::Time::Max(),
+ this->http_www_google_.url()));
}
TYPED_TEST_P(CookieStoreTest, TestSecure) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->https_www_google_.url()));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(), "A=B"));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->https_www_google_.url()));
- EXPECT_TRUE(this->SetCookie(cs.get(), this->https_www_google_.url(),
- "A=B; secure"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->https_www_google_.url(), "A=B; secure"));
// The secure should overwrite the non-secure.
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->https_www_google_.url()));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->https_www_google_.url()));
- EXPECT_TRUE(this->SetCookie(cs.get(), this->https_www_google_.url(),
- "D=E; secure"));
- this->MatchCookieLines(
- std::string(),
- this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "A=B; D=E", this->GetCookies(cs.get(), this->https_www_google_.url()));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->https_www_google_.url(), "D=E; secure"));
+ this->MatchCookieLines(std::string(),
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; D=E",
+ this->GetCookies(cs, this->https_www_google_.url()));
- EXPECT_TRUE(
- this->SetCookie(cs.get(), this->https_www_google_.url(), "A=B"));
+ EXPECT_TRUE(this->SetCookie(cs, this->https_www_google_.url(), "A=B"));
// The non-secure should overwrite the secure.
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
- this->MatchCookieLines(
- "D=E; A=B", this->GetCookies(cs.get(), this->https_www_google_.url()));
+ this->MatchCookieLines("A=B",
+ this->GetCookies(cs, this->http_www_google_.url()));
+ this->MatchCookieLines("D=E; A=B",
+ this->GetCookies(cs, this->https_www_google_.url()));
}
static const int kLastAccessThresholdMilliseconds = 200;
@@ -952,17 +1101,17 @@ static const int kLastAccessThresholdMilliseconds = 200;
TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
const GURL test_url("http://mojo.jojo.google.izzle/");
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
- EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "foo=bar"));
- std::string value = this->GetCookies(cs.get(), test_url);
+ EXPECT_TRUE(this->SetCookie(cs, test_url, "foo=bar"));
+ std::string value = this->GetCookies(cs, test_url);
this->MatchCookieLines("foo=bar", value);
// test that we can retrieve all cookies:
- EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "x=1"));
- EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "y=2"));
+ EXPECT_TRUE(this->SetCookie(cs, test_url, "x=1"));
+ EXPECT_TRUE(this->SetCookie(cs, test_url, "y=2"));
- std::string result = this->GetCookies(cs.get(), test_url);
+ std::string result = this->GetCookies(cs, test_url);
EXPECT_FALSE(result.empty());
EXPECT_NE(result.find("x=1"), std::string::npos) << result;
EXPECT_NE(result.find("y=2"), std::string::npos) << result;
@@ -971,17 +1120,15 @@ TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
GURL url_google("http://www.google.com/");
GURL url_chromium("http://chromium.org");
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
// Insert a cookie "a" for path "/path1"
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookie(cs, url_google,
"a=val1; path=/path1; "
"expires=Mon, 18-Apr-22 22:50:13 GMT"));
// Insert a cookie "b" for path "/path1"
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookie(cs, url_google,
"b=val1; path=/path1; "
"expires=Mon, 18-Apr-22 22:50:14 GMT"));
@@ -989,105 +1136,233 @@ TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
// overwrite the non-http-only version.
CookieOptions allow_httponly;
allow_httponly.set_include_httponly();
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookieWithOptions(cs, url_google,
"b=val2; path=/path1; httponly; "
"expires=Mon, 18-Apr-22 22:50:14 GMT",
allow_httponly));
// Insert a cookie "a" for path "/path1". This should overwrite.
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookie(cs, url_google,
"a=val33; path=/path1; "
"expires=Mon, 18-Apr-22 22:50:14 GMT"));
// Insert a cookie "a" for path "/path2". This should NOT overwrite
// cookie "a", since the path is different.
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_google,
+ EXPECT_TRUE(this->SetCookie(cs, url_google,
"a=val9; path=/path2; "
"expires=Mon, 18-Apr-22 22:50:14 GMT"));
// Insert a cookie "a" for path "/path1", but this time for "chromium.org".
// Although the name and path match, the hostnames do not, so shouldn't
// overwrite.
- EXPECT_TRUE(this->SetCookie(cs.get(),
- url_chromium,
+ EXPECT_TRUE(this->SetCookie(cs, url_chromium,
"a=val99; path=/path1; "
"expires=Mon, 18-Apr-22 22:50:14 GMT"));
if (TypeParam::supports_http_only) {
this->MatchCookieLines(
- "a=val33",
- this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
+ "a=val33", this->GetCookies(cs, GURL("http://www.google.com/path1")));
} else {
this->MatchCookieLines(
"a=val33; b=val2",
- this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
+ this->GetCookies(cs, GURL("http://www.google.com/path1")));
}
this->MatchCookieLines(
- "a=val9",
- this->GetCookies(cs.get(), GURL("http://www.google.com/path2")));
+ "a=val9", this->GetCookies(cs, GURL("http://www.google.com/path2")));
this->MatchCookieLines(
- "a=val99", this->GetCookies(cs.get(), GURL("http://chromium.org/path1")));
+ "a=val99", this->GetCookies(cs, GURL("http://chromium.org/path1")));
}
TYPED_TEST_P(CookieStoreTest, CookieOrdering) {
// Put a random set of cookies into a store and make sure they're returned in
// the right order.
// Cookies should be sorted by path length and creation time, as per RFC6265.
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(
- cs.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
- EXPECT_TRUE(this->SetCookie(cs.get(),
- GURL("http://b.a.google.com/aa/bb/cc/x.html"),
+ CookieStore* cs = this->GetCookieStore();
+ EXPECT_TRUE(
+ this->SetCookie(cs, GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
+ EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.google.com/aa/bb/cc/x.html"),
"d=1; domain=b.a.google.com"));
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
TypeParam::creation_time_granularity_in_ms));
- EXPECT_TRUE(this->SetCookie(cs.get(),
- GURL("http://b.a.google.com/aa/bb/cc/x.html"),
+ EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.google.com/aa/bb/cc/x.html"),
"a=4; domain=b.a.google.com"));
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
TypeParam::creation_time_granularity_in_ms));
- EXPECT_TRUE(this->SetCookie(cs.get(),
+ EXPECT_TRUE(this->SetCookie(cs,
GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
"e=1; domain=c.b.a.google.com"));
EXPECT_TRUE(this->SetCookie(
- cs.get(), GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
- EXPECT_TRUE(this->SetCookie(
- cs.get(), GURL("http://news.bbc.co.uk/midpath/x.html"), "g=10"));
- EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
- this->GetCookies(cs.get(),
- GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
+ cs, GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
+ EXPECT_TRUE(this->SetCookie(cs, GURL("http://news.bbc.co.uk/midpath/x.html"),
+ "g=10"));
+ EXPECT_EQ(
+ "d=1; a=4; e=1; b=1; c=1",
+ this->GetCookies(cs, GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
+
+ CookieOptions options;
+ CookieList cookies = this->GetCookieListWithOptions(
+ cs, GURL("http://d.c.b.a.google.com/aa/bb/cc/dd"), options);
+ CookieList::const_iterator it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ("d", it->Name());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ("a", it->Name());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ("e", it->Name());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ("b", it->Name());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ("c", it->Name());
+
+ EXPECT_TRUE(++it == cookies.end());
+}
+
+// Check that GetAllCookiesAsync returns cookies from multiple domains, in the
+// correct order.
+TYPED_TEST_P(CookieStoreTest, GetAllCookiesAsync) {
+ CookieStore* cs = this->GetCookieStore();
+
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=B; path=/a"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_foo_com_.url(), "C=D;/"));
+ EXPECT_TRUE(this->SetCookie(cs, this->http_bar_com_.url(), "E=F; path=/bar"));
+
+ // Check cookies for url.
+ CookieList cookies = this->GetAllCookies(cs);
+ CookieList::const_iterator it = cookies.begin();
+
+ ASSERT_TRUE(it != cookies.end());
+ EXPECT_EQ(this->http_bar_com_.host(), it->Domain());
+ EXPECT_EQ("/bar", it->Path());
+ EXPECT_EQ("E", it->Name());
+ EXPECT_EQ("F", it->Value());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ(this->http_www_google_.host(), it->Domain());
+ EXPECT_EQ("/a", it->Path());
+ EXPECT_EQ("A", it->Name());
+ EXPECT_EQ("B", it->Value());
+
+ ASSERT_TRUE(++it != cookies.end());
+ EXPECT_EQ(this->http_foo_com_.host(), it->Domain());
+ EXPECT_EQ("/", it->Path());
+ EXPECT_EQ("C", it->Name());
+ EXPECT_EQ("D", it->Value());
+
+ ASSERT_TRUE(++it == cookies.end());
+}
+
+TYPED_TEST_P(CookieStoreTest, DeleteCookieAsync) {
+ CookieStore* cs = this->GetCookieStore();
+
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=A1; path=/"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=A2; path=/foo"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=A3; path=/bar"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "B=B1; path=/"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "B=B2; path=/foo"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "B=B3; path=/bar"));
+
+ this->DeleteCookie(cs, this->http_www_google_.AppendPath("foo/bar"), "A");
+
+ CookieList cookies = this->GetAllCookies(cs);
+ size_t expected_size = 4;
+ EXPECT_EQ(expected_size, cookies.size());
+ for (const auto& cookie : cookies) {
+ EXPECT_NE("A1", cookie.Value());
+ EXPECT_NE("A2", cookie.Value());
+ }
+}
+
+TYPED_TEST_P(CookieStoreTest, DeleteCanonicalCookieAsync) {
+ CookieStore* cs = this->GetCookieStore();
+
+ // Set two cookies with the same name, and make sure both are set.
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=B;Path=/foo"));
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=C;Path=/bar"));
+ EXPECT_EQ(2u, this->GetAllCookies(cs).size());
+ EXPECT_EQ("A=B", this->GetCookies(cs, this->www_google_foo_.url()));
+ EXPECT_EQ("A=C", this->GetCookies(cs, this->www_google_bar_.url()));
+
+ // Delete the "/foo" cookie, and make sure only it was deleted.
+ CookieList cookies = this->GetCookieListWithOptions(
+ cs, this->www_google_foo_.url(), CookieOptions());
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_EQ(1, this->DeleteCanonicalCookie(cs, cookies[0]));
+ EXPECT_EQ(1u, this->GetAllCookies(cs).size());
+ EXPECT_EQ("", this->GetCookies(cs, this->www_google_foo_.url()));
+ EXPECT_EQ("A=C", this->GetCookies(cs, this->www_google_bar_.url()));
+
+ // Deleting the "/foo" cookie again should fail.
+ EXPECT_EQ(0, this->DeleteCanonicalCookie(cs, cookies[0]));
+
+ // Try to delete the "/bar" cookie after overwriting it with a new cookie.
+ cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+ CookieOptions());
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_TRUE(
+ this->SetCookie(cs, this->http_www_google_.url(), "A=D;Path=/bar"));
+ EXPECT_EQ(0, this->DeleteCanonicalCookie(cs, cookies[0]));
+ EXPECT_EQ(1u, this->GetAllCookies(cs).size());
+ EXPECT_EQ("A=D", this->GetCookies(cs, this->www_google_bar_.url()));
+
+ // Delete the new "/bar" cookie.
+ cookies = this->GetCookieListWithOptions(cs, this->www_google_bar_.url(),
+ CookieOptions());
+ ASSERT_EQ(1u, cookies.size());
+ EXPECT_EQ(1, this->DeleteCanonicalCookie(cs, cookies[0]));
+ EXPECT_EQ(0u, this->GetAllCookies(cs).size());
+ EXPECT_EQ("", this->GetCookies(cs, this->www_google_bar_.url()));
}
TYPED_TEST_P(CookieStoreTest, DeleteSessionCookie) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
+ CookieStore* cs = this->GetCookieStore();
// Create a session cookie and a persistent cookie.
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(),
+ EXPECT_TRUE(this->SetCookie(cs, this->http_www_google_.url(),
std::string(kValidCookieLine)));
EXPECT_TRUE(this->SetCookie(
- cs.get(), this->http_www_google_.url(),
+ cs, this->http_www_google_.url(),
this->http_www_google_.Format("C=D; path=/; domain=%D;"
"expires=Mon, 18-Apr-22 22:50:13 GMT")));
- this->MatchCookieLines(
- "A=B; C=D", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ this->MatchCookieLines("A=B; C=D",
+ this->GetCookies(cs, this->http_www_google_.url()));
// Delete the session cookie.
- this->DeleteSessionCookies(cs.get());
+ this->DeleteSessionCookies(cs);
// Check that the session cookie has been deleted but not the persistent one.
- EXPECT_EQ("C=D", this->GetCookies(cs.get(), this->http_www_google_.url()));
+ EXPECT_EQ("C=D", this->GetCookies(cs, this->http_www_google_.url()));
}
REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
- TypeTest,
+ SetCookieWithDetailsAsync,
DomainTest,
DomainWithTrailingDotTest,
ValidSubdomainTest,
InvalidDomainTest,
- DomainWithoutLeadingDotTest,
+ InvalidDomainSameDomainAndRegistry,
+ DomainWithoutLeadingDotParentDomain,
+ DomainWithoutLeadingDotSameDomain,
CaseInsensitiveDomainTest,
TestIpAddress,
- TestNonDottedAndTLD,
+ TestIpAddressNoDomainCookies,
+ TestTLD,
+ TestTLDWithTerminalDot,
+ TestSubdomainSettingCookiesOnUnknownTLD,
+ TestSubdomainSettingCookiesOnKnownTLD,
+ TestSubdomainSettingCookiesOnKnownDottedTLD,
+ TestSettingCookiesOnUnknownTLD,
+ TestSettingCookiesWithHostDomainOnUnknownTLD,
TestHostEndsWithDot,
InvalidScheme,
InvalidScheme_Read,
@@ -1095,188 +1370,18 @@ REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
EmptyExpires,
HttpOnlyTest,
TestCookieDeletion,
+ TestDeleteAll,
TestDeleteAllCreatedBetween,
TestDeleteAllCreatedBetweenForHost,
TestSecure,
NetUtilCookieTest,
OverwritePersistentCookie,
CookieOrdering,
+ GetAllCookiesAsync,
+ DeleteCookieAsync,
+ DeleteCanonicalCookieAsync,
DeleteSessionCookie);
-template<class CookieStoreTestTraits>
-class MultiThreadedCookieStoreTest :
- public CookieStoreTest<CookieStoreTestTraits> {
- public:
- MultiThreadedCookieStoreTest() : other_thread_("CMTthread") {}
-
- // Helper methods for calling the asynchronous CookieStore methods
- // from a different thread.
-
- void GetCookiesTask(CookieStore* cs,
- const GURL& url,
- StringResultCookieCallback* callback) {
- CookieOptions options;
- if (!CookieStoreTestTraits::supports_http_only)
- options.set_include_httponly();
- cs->GetCookiesWithOptionsAsync(
- url, options,
- base::Bind(&StringResultCookieCallback::Run,
- base::Unretained(callback)));
- }
-
- void GetCookiesWithOptionsTask(CookieStore* cs,
- const GURL& url,
- const CookieOptions& options,
- StringResultCookieCallback* callback) {
- cs->GetCookiesWithOptionsAsync(
- url, options,
- base::Bind(&StringResultCookieCallback::Run,
- base::Unretained(callback)));
- }
-
- void SetCookieWithOptionsTask(CookieStore* cs,
- const GURL& url,
- const std::string& cookie_line,
- const CookieOptions& options,
- ResultSavingCookieCallback<bool>* callback) {
- cs->SetCookieWithOptionsAsync(
- url, cookie_line, options,
- base::Bind(
- &ResultSavingCookieCallback<bool>::Run,
- base::Unretained(callback)));
- }
-
- void DeleteCookieTask(CookieStore* cs,
- const GURL& url,
- const std::string& cookie_name,
- NoResultCookieCallback* callback) {
- cs->DeleteCookieAsync(
- url, cookie_name,
- base::Bind(&NoResultCookieCallback::Run, base::Unretained(callback)));
- }
-
- void DeleteSessionCookiesTask(CookieStore* cs,
- ResultSavingCookieCallback<int>* callback) {
- cs->DeleteSessionCookiesAsync(
- base::Bind(
- &ResultSavingCookieCallback<int>::Run,
- base::Unretained(callback)));
- }
-
- protected:
- void RunOnOtherThread(const base::Closure& task) {
- other_thread_.Start();
- other_thread_.task_runner()->PostTask(FROM_HERE, task);
- CookieStoreTest<CookieStoreTestTraits>::RunFor(kTimeout);
- other_thread_.Stop();
- }
-
- Thread other_thread_;
-};
-
-TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest);
-
-// TODO(ycxiao): Eventually, we will need to create a separate thread, create
-// the cookie store on that thread (or at least its store, i.e., the DB
-// thread).
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookies) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- this->MatchCookieLines(
- "A=B", this->GetCookies(cs.get(), this->http_www_google_.url()));
- StringResultCookieCallback callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::GetCookiesTask,
- base::Unretained(this), cs, this->http_www_google_.url(), &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ("A=B", callback.result());
-}
-
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookiesWithOptions) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- CookieOptions options;
- if (!TypeParam::supports_http_only)
- options.set_include_httponly();
- EXPECT_TRUE(this->SetCookie(cs.get(), this->http_www_google_.url(), "A=B"));
- this->MatchCookieLines(
- "A=B", this->GetCookiesWithOptions(cs.get(), this->http_www_google_.url(),
- options));
- StringResultCookieCallback callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithOptionsTask,
- base::Unretained(this), cs, this->http_www_google_.url(), options,
- &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ("A=B", callback.result());
-}
-
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckSetCookieWithOptions) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- CookieOptions options;
- if (!TypeParam::supports_http_only)
- options.set_include_httponly();
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- ResultSavingCookieCallback<bool> callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::SetCookieWithOptionsTask,
- base::Unretained(this), cs, this->http_www_google_.url(), "A=B", options,
- &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_TRUE(callback.result());
-}
-
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteCookie) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- CookieOptions options;
- if (!TypeParam::supports_http_only)
- options.set_include_httponly();
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- this->DeleteCookie(cs.get(), this->http_www_google_.url(), "A");
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- NoResultCookieCallback callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::DeleteCookieTask,
- base::Unretained(this), cs, this->http_www_google_.url(), "A", &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
-}
-
-TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteSessionCookies) {
- scoped_refptr<CookieStore> cs(this->GetCookieStore());
- CookieOptions options;
- if (!TypeParam::supports_http_only)
- options.set_include_httponly();
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- EXPECT_TRUE(this->SetCookieWithOptions(
- cs.get(), this->http_www_google_.url(),
- "B=C; expires=Mon, 18-Apr-22 22:50:13 GMT", options));
- EXPECT_EQ(1, this->DeleteSessionCookies(cs.get()));
- EXPECT_EQ(0, this->DeleteSessionCookies(cs.get()));
- EXPECT_TRUE(this->SetCookieWithOptions(cs.get(), this->http_www_google_.url(),
- "A=B", options));
- ResultSavingCookieCallback<int> callback(&this->other_thread_);
- base::Closure task = base::Bind(
- &MultiThreadedCookieStoreTest<TypeParam>::DeleteSessionCookiesTask,
- base::Unretained(this), cs, &callback);
- this->RunOnOtherThread(task);
- EXPECT_TRUE(callback.did_run());
- EXPECT_EQ(1, callback.result());
-}
-
-REGISTER_TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest,
- ThreadCheckGetCookies,
- ThreadCheckGetCookiesWithOptions,
- ThreadCheckSetCookieWithOptions,
- ThreadCheckDeleteCookie,
- ThreadCheckDeleteSessionCookies);
-
} // namespace net
#endif // NET_COOKIES_COOKIE_STORE_UNITTEST_H_
diff --git a/chromium/net/cookies/cookie_util.cc b/chromium/net/cookies/cookie_util.cc
index 4071e6fd380..210b8d479af 100644
--- a/chromium/net/cookies/cookie_util.cc
+++ b/chromium/net/cookies/cookie_util.cc
@@ -11,8 +11,8 @@
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
-#include "net/base/net_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/base/url_util.h"
#include "url/gurl.h"
namespace net {
diff --git a/chromium/net/cookies/parse_cookie_line_fuzzer.cc b/chromium/net/cookies/parse_cookie_line_fuzzer.cc
new file mode 100644
index 00000000000..997839841ba
--- /dev/null
+++ b/chromium/net/cookies/parse_cookie_line_fuzzer.cc
@@ -0,0 +1,15 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "net/cookies/parsed_cookie.h"
+
+// Entry point for LibFuzzer.
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ std::string input(data, data + size);
+ net::ParsedCookie parsed_cookie(input);
+ return 0;
+}
diff --git a/chromium/net/cookies/parsed_cookie.cc b/chromium/net/cookies/parsed_cookie.cc
index bd8b0dc2270..2175692f534 100644
--- a/chromium/net/cookies/parsed_cookie.cc
+++ b/chromium/net/cookies/parsed_cookie.cc
@@ -55,7 +55,7 @@ const char kExpiresTokenName[] = "expires";
const char kMaxAgeTokenName[] = "max-age";
const char kSecureTokenName[] = "secure";
const char kHttpOnlyTokenName[] = "httponly";
-const char kFirstPartyOnlyTokenName[] = "first-party-only";
+const char kSameSiteTokenName[] = "samesite";
const char kPriorityTokenName[] = "priority";
const char kTerminator[] = "\n\r\0";
@@ -163,7 +163,7 @@ ParsedCookie::ParsedCookie(const std::string& cookie_line)
maxage_index_(0),
secure_index_(0),
httponly_index_(0),
- firstpartyonly_index_(0),
+ same_site_index_(0),
priority_index_(0) {
if (cookie_line.size() > kMaxCookieSize) {
VLOG(1) << "Not parsing cookie, too large: " << cookie_line.size();
@@ -179,7 +179,13 @@ ParsedCookie::~ParsedCookie() {
}
bool ParsedCookie::IsValid() const {
- return !pairs_.empty();
+ return !pairs_.empty() && IsSameSiteAttributeValid();
+}
+
+CookieSameSite ParsedCookie::SameSite() const {
+ return (same_site_index_ == 0)
+ ? CookieSameSite::DEFAULT_MODE
+ : StringToCookieSameSite(pairs_[same_site_index_].second);
}
CookiePriority ParsedCookie::Priority() const {
@@ -230,9 +236,8 @@ bool ParsedCookie::SetIsHttpOnly(bool is_http_only) {
return SetBool(&httponly_index_, kHttpOnlyTokenName, is_http_only);
}
-bool ParsedCookie::SetIsFirstPartyOnly(bool is_first_party_only) {
- return SetBool(&firstpartyonly_index_, kFirstPartyOnlyTokenName,
- is_first_party_only);
+bool ParsedCookie::SetSameSite(const std::string& is_same_site) {
+ return SetString(&same_site_index_, kSameSiteTokenName, is_same_site);
}
bool ParsedCookie::SetPriority(const std::string& priority) {
@@ -245,8 +250,7 @@ std::string ParsedCookie::ToCookieLine() const {
if (!out.empty())
out.append("; ");
out.append(it->first);
- if (it->first != kSecureTokenName && it->first != kHttpOnlyTokenName &&
- it->first != kFirstPartyOnlyTokenName) {
+ if (it->first != kSecureTokenName && it->first != kHttpOnlyTokenName) {
out.append("=");
out.append(it->second);
}
@@ -437,8 +441,8 @@ void ParsedCookie::SetupAttributes() {
secure_index_ = i;
} else if (pairs_[i].first == kHttpOnlyTokenName) {
httponly_index_ = i;
- } else if (pairs_[i].first == kFirstPartyOnlyTokenName) {
- firstpartyonly_index_ = i;
+ } else if (pairs_[i].first == kSameSiteTokenName) {
+ same_site_index_ = i;
} else if (pairs_[i].first == kPriorityTokenName) {
priority_index_ = i;
} else {
@@ -490,14 +494,9 @@ void ParsedCookie::ClearAttributePair(size_t index) {
if (index == 0)
return;
- size_t* indexes[] = {&path_index_,
- &domain_index_,
- &expires_index_,
- &maxage_index_,
- &secure_index_,
- &httponly_index_,
- &firstpartyonly_index_,
- &priority_index_};
+ size_t* indexes[] = {&path_index_, &domain_index_, &expires_index_,
+ &maxage_index_, &secure_index_, &httponly_index_,
+ &same_site_index_, &priority_index_};
for (size_t i = 0; i < arraysize(indexes); ++i) {
if (*indexes[i] == index)
*indexes[i] = 0;
@@ -507,4 +506,8 @@ void ParsedCookie::ClearAttributePair(size_t index) {
pairs_.erase(pairs_.begin() + index);
}
+bool ParsedCookie::IsSameSiteAttributeValid() const {
+ return same_site_index_ == 0 || SameSite() != CookieSameSite::DEFAULT_MODE;
+}
+
} // namespace
diff --git a/chromium/net/cookies/parsed_cookie.h b/chromium/net/cookies/parsed_cookie.h
index 8317609be5f..f48015dbd2f 100644
--- a/chromium/net/cookies/parsed_cookie.h
+++ b/chromium/net/cookies/parsed_cookie.h
@@ -50,7 +50,7 @@ class NET_EXPORT ParsedCookie {
const std::string& MaxAge() const { return pairs_[maxage_index_].second; }
bool IsSecure() const { return secure_index_ != 0; }
bool IsHttpOnly() const { return httponly_index_ != 0; }
- bool IsFirstPartyOnly() const { return firstpartyonly_index_ != 0; }
+ CookieSameSite SameSite() const;
CookiePriority Priority() const;
// Returns the number of attributes, for example, returning 2 for:
@@ -70,7 +70,7 @@ class NET_EXPORT ParsedCookie {
bool SetMaxAge(const std::string& maxage);
bool SetIsSecure(bool is_secure);
bool SetIsHttpOnly(bool is_http_only);
- bool SetIsFirstPartyOnly(bool is_first_party_only);
+ bool SetSameSite(const std::string& same_site);
bool SetPriority(const std::string& priority);
// Returns the cookie description as it appears in a HTML response header.
@@ -129,6 +129,10 @@ class NET_EXPORT ParsedCookie {
// |index| refers to a position in |pairs_|.
void ClearAttributePair(size_t index);
+ // Returns false if a 'SameSite' attribute is present, but has an unrecognized
+ // value. In particular, this includes attributes with empty values.
+ bool IsSameSiteAttributeValid() const;
+
PairList pairs_;
// These will default to 0, but that should never be valid since the
// 0th index is the user supplied token/value, not an attribute.
@@ -140,7 +144,7 @@ class NET_EXPORT ParsedCookie {
size_t maxage_index_;
size_t secure_index_;
size_t httponly_index_;
- size_t firstpartyonly_index_;
+ size_t same_site_index_;
size_t priority_index_;
DISALLOW_COPY_AND_ASSIGN(ParsedCookie);
diff --git a/chromium/net/cookies/parsed_cookie_unittest.cc b/chromium/net/cookies/parsed_cookie_unittest.cc
index 61a61677799..27efb99adfc 100644
--- a/chromium/net/cookies/parsed_cookie_unittest.cc
+++ b/chromium/net/cookies/parsed_cookie_unittest.cc
@@ -93,11 +93,11 @@ TEST(ParsedCookieTest, TestNameless) {
TEST(ParsedCookieTest, TestAttributeCase) {
ParsedCookie pc(
- "BLAHHH; Path=/; sECuRe; httpONLY; first-PaRty-only; pRIoRitY=hIgH");
+ "BLAHHH; Path=/; sECuRe; httpONLY; sAmESitE=StrIct; pRIoRitY=hIgH");
EXPECT_TRUE(pc.IsValid());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
- EXPECT_TRUE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, pc.SameSite());
EXPECT_TRUE(pc.HasPath());
EXPECT_EQ("/", pc.Path());
EXPECT_EQ("", pc.Name());
@@ -148,7 +148,7 @@ TEST(ParsedCookieTest, MissingValue) {
}
TEST(ParsedCookieTest, Whitespace) {
- ParsedCookie pc(" A = BC ;secure;;; first-party-only ");
+ ParsedCookie pc(" A = BC ;secure;;; samesite = lax ");
EXPECT_TRUE(pc.IsValid());
EXPECT_EQ("A", pc.Name());
EXPECT_EQ("BC", pc.Value());
@@ -156,7 +156,7 @@ TEST(ParsedCookieTest, Whitespace) {
EXPECT_FALSE(pc.HasDomain());
EXPECT_TRUE(pc.IsSecure());
EXPECT_FALSE(pc.IsHttpOnly());
- EXPECT_TRUE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
EXPECT_EQ(COOKIE_PRIORITY_DEFAULT, pc.Priority());
// We parse anything between ; as attributes, so we end up with two
// attributes with an empty string name and value.
@@ -171,7 +171,7 @@ TEST(ParsedCookieTest, MultipleEquals) {
EXPECT_FALSE(pc.HasDomain());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
- EXPECT_FALSE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::DEFAULT_MODE, pc.SameSite());
EXPECT_EQ(COOKIE_PRIORITY_DEFAULT, pc.Priority());
EXPECT_EQ(4U, pc.NumberOfAttributes());
}
@@ -357,12 +357,12 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_TRUE(pc.SetIsSecure(true));
EXPECT_TRUE(pc.SetIsHttpOnly(true));
EXPECT_TRUE(pc.SetIsHttpOnly(true));
- EXPECT_TRUE(pc.SetIsFirstPartyOnly(true));
+ EXPECT_TRUE(pc.SetSameSite("LAX"));
EXPECT_TRUE(pc.SetPriority("HIGH"));
EXPECT_EQ(
"name=value; domain=domain.com; path=/; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; first-party-only; priority=HIGH",
+ "httponly; samesite=LAX; priority=HIGH",
pc.ToCookieLine());
EXPECT_TRUE(pc.HasDomain());
EXPECT_TRUE(pc.HasPath());
@@ -370,7 +370,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_TRUE(pc.HasMaxAge());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
- EXPECT_TRUE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
EXPECT_EQ(COOKIE_PRIORITY_HIGH, pc.Priority());
// Clear one attribute from the middle.
@@ -383,7 +383,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_EQ(
"name=value; domain=domain.com; path=/foo; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; first-party-only; priority=HIGH",
+ "httponly; samesite=LAX; priority=HIGH",
pc.ToCookieLine());
// Set priority to medium.
@@ -391,7 +391,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_EQ(
"name=value; domain=domain.com; path=/foo; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; first-party-only; priority=medium",
+ "httponly; samesite=LAX; priority=medium",
pc.ToCookieLine());
// Clear the rest and change the name and value.
@@ -401,7 +401,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_TRUE(pc.SetMaxAge(std::string()));
EXPECT_TRUE(pc.SetIsSecure(false));
EXPECT_TRUE(pc.SetIsHttpOnly(false));
- EXPECT_TRUE(pc.SetIsFirstPartyOnly(false));
+ EXPECT_TRUE(pc.SetSameSite(std::string()));
EXPECT_TRUE(pc.SetName("name2"));
EXPECT_TRUE(pc.SetValue("value2"));
EXPECT_TRUE(pc.SetPriority(std::string()));
@@ -411,7 +411,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_FALSE(pc.HasMaxAge());
EXPECT_FALSE(pc.IsSecure());
EXPECT_FALSE(pc.IsHttpOnly());
- EXPECT_FALSE(pc.IsFirstPartyOnly());
+ EXPECT_EQ(CookieSameSite::NO_RESTRICTION, pc.SameSite());
EXPECT_EQ("name2=value2", pc.ToCookieLine());
}
@@ -449,6 +449,56 @@ TEST(ParsedCookieTest, SetPriority) {
EXPECT_EQ(COOKIE_PRIORITY_DEFAULT, pc.Priority());
}
+TEST(ParsedCookieTest, SetSameSite) {
+ ParsedCookie pc("name=value");
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_EQ("name=value", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::DEFAULT_MODE, pc.SameSite());
+
+ // Test each priority, expect case-insensitive compare.
+ EXPECT_TRUE(pc.SetSameSite("strict"));
+ EXPECT_EQ("name=value; samesite=strict", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::STRICT_MODE, pc.SameSite());
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_TRUE(pc.SetSameSite("lAx"));
+ EXPECT_EQ("name=value; samesite=lAx", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_TRUE(pc.SetSameSite("LAX"));
+ EXPECT_EQ("name=value; samesite=LAX", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_TRUE(pc.SetSameSite(""));
+ EXPECT_EQ("name=value", pc.ToCookieLine());
+ EXPECT_EQ(CookieSameSite::DEFAULT_MODE, pc.SameSite());
+ EXPECT_TRUE(pc.IsValid());
+
+ EXPECT_TRUE(pc.SetSameSite("Blah"));
+ EXPECT_FALSE(pc.IsValid());
+}
+
+TEST(ParsedCookieTest, InvalidSameSiteValue) {
+ struct TestCase {
+ const char* cookie;
+ bool valid;
+ CookieSameSite mode;
+ } cases[]{{"n=v; samesite=strict", true, CookieSameSite::STRICT_MODE},
+ {"n=v; samesite=lax", true, CookieSameSite::LAX_MODE},
+ {"n=v; samesite=boo", false, CookieSameSite::DEFAULT_MODE},
+ {"n=v; samesite", false, CookieSameSite::DEFAULT_MODE}};
+
+ for (const auto& test : cases) {
+ SCOPED_TRACE(test.cookie);
+ ParsedCookie pc(test.cookie);
+ EXPECT_EQ(test.valid, pc.IsValid());
+ EXPECT_EQ(test.mode, pc.SameSite());
+ }
+}
+
TEST(ParsedCookieTest, InvalidNonAlphanumericChars) {
ParsedCookie pc1("name=\x05");
ParsedCookie pc2(