// Copyright (c) 2012 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 "net/cookies/canonical_cookie.h" #include #include "base/test/histogram_tester.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_options.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" namespace net { TEST(CanonicalCookieTest, Constructor) { GURL url("http://www.example.com/test"); base::Time current_time = base::Time::Now(); std::unique_ptr cookie(CanonicalCookie::Create( url, "A", "2", std::string(), "/test", current_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_EQ("A", cookie->Name()); EXPECT_EQ("2", cookie->Value()); EXPECT_EQ("www.example.com", cookie->Domain()); EXPECT_EQ("/test", cookie->Path()); EXPECT_FALSE(cookie->IsSecure()); EXPECT_FALSE(cookie->IsHttpOnly()); EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite()); std::unique_ptr cookie2(CanonicalCookie::Create( url, "A", "2", ".www.example.com", std::string(), current_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_EQ("A", cookie2->Name()); EXPECT_EQ("2", cookie2->Value()); EXPECT_EQ(".www.example.com", cookie2->Domain()); EXPECT_EQ("/", cookie2->Path()); EXPECT_FALSE(cookie2->IsSecure()); EXPECT_FALSE(cookie2->IsHttpOnly()); EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2->SameSite()); } TEST(CanonicalCookieTest, Create) { // Test creating cookies from a cookie string. GURL url("http://www.example.com/test/foo.html"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::unique_ptr cookie( CanonicalCookie::Create(url, "A=2", creation_time, options)); EXPECT_EQ("A", cookie->Name()); EXPECT_EQ("2", cookie->Value()); EXPECT_EQ("www.example.com", cookie->Domain()); EXPECT_EQ("/test", cookie->Path()); EXPECT_FALSE(cookie->IsSecure()); GURL url2("http://www.foo.com"); cookie = CanonicalCookie::Create(url2, "B=1", creation_time, options); EXPECT_EQ("B", cookie->Name()); EXPECT_EQ("1", cookie->Value()); EXPECT_EQ("www.foo.com", cookie->Domain()); EXPECT_EQ("/", cookie->Path()); EXPECT_FALSE(cookie->IsSecure()); // Test creating secure cookies. // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone disallows // insecure URLs from setting secure cookies. cookie = CanonicalCookie::Create(url, "A=2; Secure", creation_time, options); EXPECT_FALSE(cookie.get()); // Test creating http only cookies. cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, options); EXPECT_FALSE(cookie.get()); CookieOptions httponly_options; httponly_options.set_include_httponly(); cookie = CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, httponly_options); EXPECT_TRUE(cookie->IsHttpOnly()); // 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_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 = CanonicalCookie::Create( url, "A", "2", "www.example.com", "/test", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT); EXPECT_EQ("A", cookie->Name()); EXPECT_EQ("2", cookie->Value()); EXPECT_EQ(".www.example.com", cookie->Domain()); EXPECT_EQ("/test", cookie->Path()); EXPECT_FALSE(cookie->IsSecure()); EXPECT_FALSE(cookie->IsHttpOnly()); EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite()); cookie = CanonicalCookie::Create( url, "A", "2", ".www.example.com", "/test", creation_time, base::Time(), false, false, CookieSameSite::DEFAULT_MODE, COOKIE_PRIORITY_DEFAULT); EXPECT_EQ("A", cookie->Name()); EXPECT_EQ("2", cookie->Value()); EXPECT_EQ(".www.example.com", cookie->Domain()); EXPECT_EQ("/test", cookie->Path()); EXPECT_FALSE(cookie->IsSecure()); EXPECT_FALSE(cookie->IsHttpOnly()); 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(); std::unique_ptr 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) { GURL url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::string cookie_line = "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires="; std::unique_ptr cookie( CanonicalCookie::Create(url, cookie_line, creation_time, options)); EXPECT_TRUE(cookie.get()); EXPECT_FALSE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Time(), cookie->ExpiryDate()); // With a stale server time options.set_server_time(creation_time - base::TimeDelta::FromHours(1)); cookie = CanonicalCookie::Create(url, cookie_line, creation_time, options); EXPECT_TRUE(cookie.get()); EXPECT_FALSE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Time(), cookie->ExpiryDate()); // With a future server time options.set_server_time(creation_time + base::TimeDelta::FromHours(1)); cookie = CanonicalCookie::Create(url, cookie_line, creation_time, options); EXPECT_TRUE(cookie.get()); EXPECT_FALSE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Time(), cookie->ExpiryDate()); } TEST(CanonicalCookieTest, IsEquivalent) { GURL url("https://www.example.com/"); std::string cookie_name = "A"; std::string cookie_value = "2EDA-EF"; std::string cookie_domain = ".www.example.com"; std::string cookie_path = "/path"; base::Time creation_time = base::Time::Now(); base::Time expiration_time = creation_time + base::TimeDelta::FromDays(2); bool secure(false); bool httponly(false); CookieSameSite same_site(CookieSameSite::NO_RESTRICTION); // Test that a cookie is equivalent to itself. std::unique_ptr cookie(CanonicalCookie::Create( url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM)); EXPECT_TRUE(cookie->IsEquivalent(*cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*cookie)); // Test that two identical cookies are equivalent. std::unique_ptr other_cookie(CanonicalCookie::Create( url, cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM)); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); // Tests that use different variations of attribute values that // DON'T affect cookie equivalence. other_cookie = CanonicalCookie::Create( url, cookie_name, "2", cookie_domain, cookie_path, creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_HIGH); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); base::Time other_creation_time = creation_time + base::TimeDelta::FromMinutes(2); other_cookie = CanonicalCookie::Create( url, cookie_name, "2", cookie_domain, cookie_path, other_creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); other_cookie = CanonicalCookie::Create( url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, expiration_time, true, httponly, same_site, COOKIE_PRIORITY_LOW); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); other_cookie = CanonicalCookie::Create( url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, expiration_time, secure, true, same_site, COOKIE_PRIORITY_LOW); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); other_cookie = CanonicalCookie::Create( url, cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, expiration_time, secure, httponly, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_LOW); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); // Cookies whose names mismatch are not equivalent. other_cookie = CanonicalCookie::Create( url, "B", cookie_value, cookie_domain, cookie_path, creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_FALSE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); // A domain cookie at 'www.example.com' is not equivalent to a host cookie // at the same domain. These are, however, equivalent according to the laxer // rules of 'IsEquivalentForSecureCookieMatching'. other_cookie = CanonicalCookie::Create( url, cookie_name, cookie_value, std::string(), cookie_path, creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM); EXPECT_TRUE(cookie->IsDomainCookie()); EXPECT_FALSE(other_cookie->IsDomainCookie()); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); // Likewise, a cookie on 'example.com' is not equivalent to a cookie on // 'www.example.com', but they are equivalent for secure cookie matching. other_cookie = CanonicalCookie::Create( url, cookie_name, cookie_value, ".example.com", cookie_path, creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); // Paths are a bit more complicated. 'IsEquivalent' requires an exact path // match, while secure cookie matching uses a more relaxed 'IsOnPath' check. // That is, |cookie| set on '/path' is not equivalent in either way to // |other_cookie| set on '/test' or '/path/subpath'. It is, however, // equivalent for secure cookie matching to |other_cookie| set on '/'. other_cookie = CanonicalCookie::Create( url, cookie_name, cookie_value, cookie_domain, "/test", creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_FALSE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); other_cookie = CanonicalCookie::Create( url, cookie_name, cookie_value, cookie_domain, cookie_path + "/subpath", creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); other_cookie = CanonicalCookie::Create( url, cookie_name, cookie_value, cookie_domain, "/", creation_time, expiration_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_FALSE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); } TEST(CanonicalCookieTest, IsDomainMatch) { GURL url("http://www.example.com/test/foo.html"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::unique_ptr cookie( CanonicalCookie::Create(url, "A=2", creation_time, options)); EXPECT_TRUE(cookie->IsHostCookie()); EXPECT_TRUE(cookie->IsDomainMatch("www.example.com")); EXPECT_TRUE(cookie->IsDomainMatch("www.example.com")); EXPECT_FALSE(cookie->IsDomainMatch("foo.www.example.com")); EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com")); EXPECT_FALSE(cookie->IsDomainMatch("example.com")); 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")); EXPECT_TRUE(cookie->IsDomainMatch("foo.www.example.com")); EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com")); EXPECT_FALSE(cookie->IsDomainMatch("example.com")); 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")); EXPECT_FALSE(cookie->IsDomainMatch("www0.example.com")); EXPECT_FALSE(cookie->IsDomainMatch("example.com")); } TEST(CanonicalCookieTest, IsOnPath) { base::Time creation_time = base::Time::Now(); CookieOptions options; std::unique_ptr cookie(CanonicalCookie::Create( GURL("http://www.example.com"), "A=2", creation_time, options)); EXPECT_TRUE(cookie->IsOnPath("/")); EXPECT_TRUE(cookie->IsOnPath("/test")); EXPECT_TRUE(cookie->IsOnPath("/test/bar.html")); // Test the empty string edge case. EXPECT_FALSE(cookie->IsOnPath(std::string())); 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")); EXPECT_TRUE(cookie->IsOnPath("/test/sample/bar.html")); } TEST(CanonicalCookieTest, IncludeForRequestURL) { GURL url("http://www.example.com"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::unique_ptr cookie( CanonicalCookie::Create(url, "A=2", creation_time, options)); EXPECT_TRUE(cookie->IncludeForRequestURL(url, options)); EXPECT_TRUE(cookie->IncludeForRequestURL( GURL("http://www.example.com/foo/bar"), options)); EXPECT_TRUE(cookie->IncludeForRequestURL( GURL("https://www.example.com/foo/bar"), options)); EXPECT_FALSE( cookie->IncludeForRequestURL(GURL("https://sub.example.com"), options)); EXPECT_FALSE(cookie->IncludeForRequestURL(GURL("https://sub.www.example.com"), options)); // Test that cookie with a cookie path that does not match the url path are // not included. 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 = 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)); // Test that http only cookies are only included if the include httponly flag // is set on the cookie options. options.set_include_httponly(); 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, IncludeSameSiteForSameSiteURL) { GURL url("https://example.test"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::unique_ptr cookie; // `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)); // `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) { GURL url("http://www.example.com"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::unique_ptr cookie( CanonicalCookie::Create(url, "a=b", creation_time, options)); std::unique_ptr cookie_different_path( CanonicalCookie::Create(url, "a=b; path=/foo", creation_time, options)); std::unique_ptr cookie_different_value( CanonicalCookie::Create(url, "a=c", creation_time, options)); // Cookie is equivalent to itself. EXPECT_FALSE(cookie->PartialCompare(*cookie)); // Changing the path affects the ordering. EXPECT_TRUE(cookie->PartialCompare(*cookie_different_path)); EXPECT_FALSE(cookie_different_path->PartialCompare(*cookie)); // Changing the value does not affect the ordering. EXPECT_FALSE(cookie->PartialCompare(*cookie_different_value)); EXPECT_FALSE(cookie_different_value->PartialCompare(*cookie)); // Cookies identical for PartialCompare() are equivalent. EXPECT_TRUE(cookie->IsEquivalent(*cookie_different_value)); EXPECT_TRUE(cookie->IsEquivalent(*cookie)); } TEST(CanonicalCookieTest, FullCompare) { GURL url("http://www.example.com"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::unique_ptr cookie( CanonicalCookie::Create(url, "a=b", creation_time, options)); std::unique_ptr cookie_different_path( CanonicalCookie::Create(url, "a=b; path=/foo", creation_time, options)); std::unique_ptr cookie_different_value( CanonicalCookie::Create(url, "a=c", creation_time, options)); // Cookie is equivalent to itself. EXPECT_FALSE(cookie->FullCompare(*cookie)); // Changing the path affects the ordering. EXPECT_TRUE(cookie->FullCompare(*cookie_different_path)); EXPECT_FALSE(cookie_different_path->FullCompare(*cookie)); // Changing the value affects the ordering. EXPECT_TRUE(cookie->FullCompare(*cookie_different_value)); EXPECT_FALSE(cookie_different_value->FullCompare(*cookie)); // FullCompare() implies PartialCompare(). auto check_consistency = [](const CanonicalCookie& a, const CanonicalCookie& b) { if (a.FullCompare(b)) EXPECT_FALSE(b.PartialCompare(a)); else if (b.FullCompare(a)) EXPECT_FALSE(a.PartialCompare(b)); }; check_consistency(*cookie, *cookie_different_path); check_consistency(*cookie, *cookie_different_value); check_consistency(*cookie_different_path, *cookie_different_value); } TEST(CanonicalCookieTest, SecureCookiePrefix) { GURL https_url("https://www.example.test"); GURL http_url("http://www.example.test"); base::Time creation_time = base::Time::Now(); CookieOptions options; // A __Secure- cookie must be Secure. 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_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_FALSE(CanonicalCookie::Create(http_url, "__Secure-A=B; Secure", creation_time, options)); } TEST(CanonicalCookieTest, HostCookiePrefix) { GURL https_url("https://www.example.test"); GURL http_url("http://www.example.test"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::string domain = https_url.host(); // A __Host- cookie must be Secure. 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_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_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_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_TRUE(CanonicalCookie::Create( http_url, "__host-A=B; Domain=" + domain + "; Path=/;", creation_time, options)); EXPECT_TRUE(CanonicalCookie::Create( https_url, "__HostA=B; Domain=" + domain + "; Secure;", creation_time, options)); } TEST(CanonicalCookieTest, EnforceSecureCookiesRequireSecureScheme) { GURL http_url("http://www.example.com"); GURL https_url("https://www.example.com"); base::Time creation_time = base::Time::Now(); CookieOptions options; std::unique_ptr http_cookie_no_secure( CanonicalCookie::Create(http_url, "a=b", creation_time, options)); std::unique_ptr http_cookie_secure( CanonicalCookie::Create(http_url, "a=b; Secure", creation_time, options)); std::unique_ptr https_cookie_no_secure( CanonicalCookie::Create(https_url, "a=b", creation_time, options)); std::unique_ptr https_cookie_secure(CanonicalCookie::Create( https_url, "a=b; Secure", creation_time, options)); EXPECT_TRUE(http_cookie_no_secure.get()); EXPECT_FALSE(http_cookie_secure.get()); EXPECT_TRUE(https_cookie_no_secure.get()); EXPECT_TRUE(https_cookie_secure.get()); std::unique_ptr http_cookie_no_secure_extended( CanonicalCookie::Create( http_url, "a", "b", "", "", creation_time, creation_time, false, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT)); std::unique_ptr http_cookie_secure_extended( CanonicalCookie::Create( http_url, "a", "b", "", "", creation_time, creation_time, true, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT)); std::unique_ptr https_cookie_no_secure_extended( CanonicalCookie::Create( https_url, "a", "b", "", "", creation_time, creation_time, false, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT)); std::unique_ptr https_cookie_secure_extended( CanonicalCookie::Create( https_url, "a", "b", "", "", creation_time, creation_time, true, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT)); EXPECT_TRUE(http_cookie_no_secure_extended.get()); EXPECT_FALSE(http_cookie_secure_extended.get()); EXPECT_TRUE(https_cookie_no_secure_extended.get()); EXPECT_TRUE(https_cookie_secure_extended.get()); } TEST(CanonicalCookieTest, TestPrefixHistograms) { base::HistogramTester histograms; const char kCookiePrefixHistogram[] = "Cookie.CookiePrefix"; const char kCookiePrefixBlockedHistogram[] = "Cookie.CookiePrefixBlocked"; GURL https_url("https://www.example.test"); base::Time creation_time = base::Time::Now(); CookieOptions options; 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_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_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); 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_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_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Path=/; Secure", creation_time, options)); histograms.ExpectBucketCount(kCookiePrefixHistogram, CanonicalCookie::COOKIE_PREFIX_SECURE, 2); histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram, CanonicalCookie::COOKIE_PREFIX_SECURE, 1); } } // namespace net