diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-09-07 13:12:05 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-11-09 10:02:59 +0000 |
commit | 33fc33aa94d4add0878ec30dc818e34e1dd3cc2a (patch) | |
tree | f6af110909c79b2759136554f1143d8b0572af0a /chromium/net/cookies | |
parent | 7d2c5d177e9813077a621df8d18c0deda73099b3 (diff) | |
download | qtwebengine-chromium-33fc33aa94d4add0878ec30dc818e34e1dd3cc2a.tar.gz |
BASELINE: Update Chromium to 104.0.5112.120
Change-Id: I5d2726c2ab018d75d055739b6ba64317904f05bb
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/438935
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/cookies')
23 files changed, 1124 insertions, 529 deletions
diff --git a/chromium/net/cookies/canonical_cookie.cc b/chromium/net/cookies/canonical_cookie.cc index d0120b13c5c..f31ac89afbe 100644 --- a/chromium/net/cookies/canonical_cookie.cc +++ b/chromium/net/cookies/canonical_cookie.cc @@ -75,6 +75,8 @@ using base::Time; namespace net { +static constexpr int kMinutesInTwelveHours = 12 * 60; + namespace { // Determine the cookie domain to use for setting the specified cookie. @@ -347,8 +349,7 @@ int ValidateAndAdjustSourcePort(int port) { } // Tests that a cookie has the attributes for a valid __Host- prefix without -// testing that the prefix is in the cookie name. This is used to verify the -// Partitioned attribute. +// testing that the prefix is in the cookie name. bool HasValidHostPrefixAttributes(const GURL& url, bool secure, const std::string& domain, @@ -358,25 +359,15 @@ bool HasValidHostPrefixAttributes(const GURL& url, return domain.empty() || (url.HostIsIPAddress() && url.host() == domain); } -// Per rfc6265bis the maximum expiry date is no further than 400 days in the -// future. Clamping only occurs when kClampCookieExpiryTo400Days is enabled. -base::Time ValidateAndAdjustExpiryDate(const base::Time& expiry_date, - const base::Time& creation_date) { - if (expiry_date.is_null()) - return expiry_date; - base::Time fixed_creation_date = creation_date; - if (fixed_creation_date.is_null()) { - // TODO(crbug.com/1264458): This shouldn't be necessary, let's examine - // where creation_date is null but expiry_date isn't and figure out - // what's happening. This blocks the launch until resolved. - fixed_creation_date = base::Time::Now(); - } - if (base::FeatureList::IsEnabled(features::kClampCookieExpiryTo400Days)) { - base::Time maximum_expiry_date = fixed_creation_date + base::Days(400); - if (expiry_date > maximum_expiry_date) - return maximum_expiry_date; - } - return expiry_date; +// Test that a cookie has the attributes for a valid Parititioned attribute. +// For M104, we do not require that Partitioned cookies do not have the Domain +// attribute. +// TODO(crbug.com/1296161): Determine if we need to delete this function. +bool HasValidAttributesForPartitioned(const GURL& url, + bool secure, + const std::string& path, + bool is_same_party) { + return url.SchemeIsCryptographic() && secure && path == "/" && !is_same_party; } } // namespace @@ -407,6 +398,7 @@ CanonicalCookie::CanonicalCookie( base::Time creation, base::Time expiration, base::Time last_access, + base::Time last_update, bool secure, bool httponly, CookieSameSite same_site, @@ -422,6 +414,7 @@ CanonicalCookie::CanonicalCookie( creation_date_(creation), expiry_date_(expiration), last_access_date_(last_access), + last_update_date_(last_update), secure_(secure), httponly_(httponly), same_site_(same_site), @@ -493,10 +486,31 @@ Time CanonicalCookie::ParseExpiration(const ParsedCookie& pc, // Try the Expires attribute. if (pc.HasExpires() && !pc.Expires().empty()) { // Adjust for clock skew between server and host. - base::Time parsed_expiry = - cookie_util::ParseCookieExpirationTime(pc.Expires()); - if (!parsed_expiry.is_null()) - return parsed_expiry + (current - server_time); + Time parsed_expiry = cookie_util::ParseCookieExpirationTime(pc.Expires()); + if (!parsed_expiry.is_null()) { + // Record metrics related to prevalence of clock skew. + base::TimeDelta clock_skew = (current - server_time); + // Record the magnitude (absolute value) of the skew in minutes. + int clock_skew_magnitude = clock_skew.magnitude().InMinutes(); + if (clock_skew.is_positive() || clock_skew.is_zero()) { + UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ClockSkew.AddMinutes", + clock_skew_magnitude, 1, + kMinutesInTwelveHours, 100); + } else if (clock_skew.is_negative()) { + // These histograms only support positive numbers, so negative skews + // will be converted to positive (via magnitude) before recording. + UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ClockSkew.SubtractMinutes", + clock_skew_magnitude, 1, + kMinutesInTwelveHours, 100); + } + Time adjusted_expiry = parsed_expiry + (current - server_time); + // Record if we were going to expire the cookie before we added the clock + // skew. + UMA_HISTOGRAM_BOOLEAN( + "Cookie.ClockSkew.ExpiredWithoutSkew", + parsed_expiry <= Time::Now() && adjusted_expiry > Time::Now()); + return adjusted_expiry; + } } // Invalid or no expiration, session cookie. @@ -504,6 +518,32 @@ Time CanonicalCookie::ParseExpiration(const ParsedCookie& pc, } // static +base::Time CanonicalCookie::ValidateAndAdjustExpiryDate( + const base::Time& expiry_date, + const base::Time& creation_date) { + if (expiry_date.is_null()) + return expiry_date; + base::Time fixed_creation_date = creation_date; + if (fixed_creation_date.is_null()) { + // TODO(crbug.com/1264458): Push this logic into + // CanonicalCookie::CreateSanitizedCookie. The four sites that call it + // with a null `creation_date` (CanonicalCookie::Create cannot be called + // this way) are: + // * GaiaCookieManagerService::ForceOnCookieChangeProcessing + // * CookiesSetFunction::Run + // * cookie_store.cc::ToCanonicalCookie + // * network_handler.cc::MakeCookieFromProtocolValues + fixed_creation_date = base::Time::Now(); + } + if (base::FeatureList::IsEnabled(features::kClampCookieExpiryTo400Days)) { + base::Time maximum_expiry_date = fixed_creation_date + base::Days(400); + if (expiry_date > maximum_expiry_date) + return maximum_expiry_date; + } + return expiry_date; +} + +// static std::unique_ptr<CanonicalCookie> CanonicalCookie::Create( const GURL& url, const std::string& cookie_line, @@ -611,7 +651,8 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::Create( std::unique_ptr<CanonicalCookie> cc = base::WrapUnique(new CanonicalCookie( parsed_cookie.Name(), parsed_cookie.Value(), cookie_domain, cookie_path, - creation_time, cookie_expires, creation_time, parsed_cookie.IsSecure(), + creation_time, cookie_expires, creation_time, + /*last_update=*/base::Time::Now(), parsed_cookie.IsSecure(), parsed_cookie.IsHttpOnly(), samesite, parsed_cookie.Priority(), parsed_cookie.IsSameParty(), cookie_partition_key, source_scheme, source_port)); @@ -783,7 +824,7 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateSanitizedCookie( status->AddExclusionReason( net::CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY); } - if (!IsCookiePartitionedValid(url, secure, domain_attribute, cookie_path, + if (!IsCookiePartitionedValid(url, secure, cookie_path, /*is_partitioned=*/partition_key.has_value(), /*is_same_party=*/same_party, /*partition_has_nonce=*/ @@ -803,8 +844,9 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateSanitizedCookie( std::unique_ptr<CanonicalCookie> cc = base::WrapUnique(new CanonicalCookie( name, value, cookie_domain, encoded_cookie_path, creation_time, - expiration_time, last_access_time, secure, http_only, same_site, priority, - same_party, partition_key, source_scheme, source_port)); + expiration_time, last_access_time, /*last_update=*/base::Time::Now(), + secure, http_only, same_site, priority, same_party, partition_key, + source_scheme, source_port)); DCHECK(cc->IsCanonical()); return cc; @@ -819,6 +861,7 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::FromStorage( base::Time creation, base::Time expiration, base::Time last_access, + base::Time last_update, bool secure, bool httponly, CookieSameSite same_site, @@ -837,8 +880,9 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::FromStorage( std::unique_ptr<CanonicalCookie> cc = base::WrapUnique(new CanonicalCookie( std::move(name), std::move(value), std::move(domain), std::move(path), - creation, expiration, last_access, secure, httponly, same_site, priority, - same_party, partition_key, source_scheme, validated_port)); + creation, expiration, last_access, last_update, secure, httponly, + same_site, priority, same_party, partition_key, source_scheme, + validated_port)); if (cc->IsCanonicalForFromStorage()) { // This will help capture the number of times a cookie is canonical but does @@ -862,6 +906,7 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateUnsafeCookieForTesting( const base::Time& creation, const base::Time& expiration, const base::Time& last_access, + const base::Time& last_update, bool secure, bool httponly, CookieSameSite same_site, @@ -871,9 +916,9 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateUnsafeCookieForTesting( CookieSourceScheme source_scheme, int source_port) { return base::WrapUnique(new CanonicalCookie( - name, value, domain, path, creation, expiration, last_access, secure, - httponly, same_site, priority, same_party, partition_key, source_scheme, - source_port)); + name, value, domain, path, creation, expiration, last_access, last_update, + secure, httponly, same_site, priority, same_party, partition_key, + source_scheme, source_port)); } std::string CanonicalCookie::DomainWithoutDot() const { @@ -1430,6 +1475,12 @@ bool CanonicalCookie::IsCanonical() const { // would fail this check. Note that we still don't want to enforce length // checks on domain or path for the reason stated above. + // TODO(crbug.com/1264458): Eventually we should push this logic into + // IsCanonicalForFromStorage, but for now we allow cookies already stored with + // high expiration dates to be retrieved. + if (ValidateAndAdjustExpiryDate(expiry_date_, creation_date_) != expiry_date_) + return false; + return IsCanonicalForFromStorage(); } @@ -1474,13 +1525,17 @@ bool CanonicalCookie::IsCanonicalForFromStorage() const { return false; CookiePrefix prefix = GetCookiePrefix(name_); - bool partition_key_has_nonce = CookiePartitionKey::HasNonce(partition_key_); - if (prefix == COOKIE_PREFIX_HOST || - (IsPartitioned() && !partition_key_has_nonce)) { - if (!secure_ || path_ != "/" || domain_.empty() || domain_[0] == '.') - return false; - } else if (prefix == COOKIE_PREFIX_SECURE && !secure_) { - return false; + switch (prefix) { + case COOKIE_PREFIX_HOST: + if (!secure_ || path_ != "/" || domain_.empty() || domain_[0] == '.') + return false; + break; + case COOKIE_PREFIX_SECURE: + if (!secure_) + return false; + break; + default: + break; } if (name_ == "" && HasHiddenPrefixName(value_)) @@ -1490,10 +1545,11 @@ bool CanonicalCookie::IsCanonicalForFromStorage() const { return false; if (IsPartitioned()) { - if (partition_key_has_nonce) + if (CookiePartitionKey::HasNonce(partition_key_)) return true; - if (same_party_) + if (!secure_ || path_ != "/" || same_party_) { return false; + } } return true; @@ -1670,7 +1726,6 @@ bool CanonicalCookie::IsCookiePartitionedValid( bool partition_has_nonce) { return IsCookiePartitionedValid( url, /*secure=*/parsed_cookie.IsSecure(), - parsed_cookie.HasDomain() ? parsed_cookie.Domain() : "", parsed_cookie.HasPath() ? parsed_cookie.Path() : "", /*is_partitioned=*/parsed_cookie.IsPartitioned(), /*is_same_party=*/parsed_cookie.IsSameParty(), partition_has_nonce); @@ -1679,7 +1734,6 @@ bool CanonicalCookie::IsCookiePartitionedValid( // static bool CanonicalCookie::IsCookiePartitionedValid(const GURL& url, bool secure, - const std::string& domain, const std::string& path, bool is_partitioned, bool is_same_party, @@ -1689,9 +1743,9 @@ bool CanonicalCookie::IsCookiePartitionedValid(const GURL& url, if (partition_has_nonce) return true; bool result = - HasValidHostPrefixAttributes(url, secure, domain, path) && !is_same_party; + HasValidAttributesForPartitioned(url, secure, path, is_same_party); DLOG_IF(WARNING, !result) - << "CanonicalCookie has invalid Partitioned attribute"; + << "CanonicalCookie has invalid Partitioned attribute "; return result; } diff --git a/chromium/net/cookies/canonical_cookie.h b/chromium/net/cookies/canonical_cookie.h index 0283553acf8..1ddf1b1532b 100644 --- a/chromium/net/cookies/canonical_cookie.h +++ b/chromium/net/cookies/canonical_cookie.h @@ -139,6 +139,7 @@ class NET_EXPORT CanonicalCookie { base::Time creation, base::Time expiration, base::Time last_access, + base::Time last_update, bool secure, bool httponly, CookieSameSite same_site, @@ -158,6 +159,7 @@ class NET_EXPORT CanonicalCookie { const base::Time& creation, const base::Time& expiration, const base::Time& last_access, + const base::Time& last_update, bool secure, bool httponly, CookieSameSite same_site, @@ -182,9 +184,10 @@ class NET_EXPORT CanonicalCookie { const std::string& Domain() const { return domain_; } const std::string& Path() const { return path_; } const base::Time& CreationDate() const { return creation_date_; } + const base::Time& ExpiryDate() const { return expiry_date_; } const base::Time& LastAccessDate() const { return last_access_date_; } + const base::Time& LastUpdateDate() const { return last_update_date_; } bool IsPersistent() const { return !expiry_date_.is_null(); } - const base::Time& ExpiryDate() const { return expiry_date_; } bool IsSecure() const { return secure_; } bool IsHttpOnly() const { return httponly_; } CookieSameSite SameSite() const { return same_site_; } @@ -287,7 +290,7 @@ class NET_EXPORT CanonicalCookie { priority_ == other.priority_ && same_party_ == other.same_party_ && partition_key_ == other.partition_key_ && name_ == other.name_ && value_ == other.value_ && domain_ == other.domain_ && - path_ == other.path_; + path_ == other.path_ && last_update_date_ == other.last_update_date_; } void SetSourceScheme(CookieSourceScheme source_scheme) { @@ -365,6 +368,12 @@ class NET_EXPORT CanonicalCookie { const base::Time& current, const base::Time& server_time); + // Per rfc6265bis the maximum expiry date is no further than 400 days in the + // future. Clamping only occurs when kClampCookieExpiryTo400Days is enabled. + static base::Time ValidateAndAdjustExpiryDate( + const base::Time& expiry_date, + const base::Time& creation_date); + // Cookie ordering methods. // Returns true if the cookie is less than |other|, considering only name, @@ -437,6 +446,7 @@ class NET_EXPORT CanonicalCookie { base::Time creation, base::Time expiration, base::Time last_access, + base::Time last_update, bool secure, bool httponly, CookieSameSite same_site, @@ -509,7 +519,6 @@ class NET_EXPORT CanonicalCookie { bool partition_has_nonce); static bool IsCookiePartitionedValid(const GURL& url, bool secure, - const std::string& domain, const std::string& path, bool is_partitioned, bool is_same_party, @@ -524,6 +533,7 @@ class NET_EXPORT CanonicalCookie { base::Time creation_date_; base::Time expiry_date_; base::Time last_access_date_; + base::Time last_update_date_; bool secure_{false}; bool httponly_{false}; CookieSameSite same_site_{CookieSameSite::NO_RESTRICTION}; diff --git a/chromium/net/cookies/canonical_cookie_unittest.cc b/chromium/net/cookies/canonical_cookie_unittest.cc index da01a7888dc..e49d701ca5c 100644 --- a/chromium/net/cookies/canonical_cookie_unittest.cc +++ b/chromium/net/cookies/canonical_cookie_unittest.cc @@ -49,6 +49,9 @@ using testing::Eq; using testing::Not; using testing::Property; +// Tests which use this class verify the expiry date clamping behavior when +// kClampCookieExpiryTo400Days is enabled. This caps expiry dates on new/updated +// cookies to max of 400 days, but does not affect previously stored cookies. class CanonicalCookieWithClampingTest : public testing::Test, public testing::WithParamInterface<bool> { @@ -74,7 +77,7 @@ TEST(CanonicalCookieTest, Constructor) { // CreateUnsafeCookieForTesting just forwards to the constructor. auto cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, + base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false, absl::nullopt, CookieSourceScheme::kSecure, 443); EXPECT_EQ("A", cookie1->Name()); @@ -92,7 +95,7 @@ TEST(CanonicalCookieTest, Constructor) { auto cookie2 = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", ".www.example.com", "/", current_time, base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, + base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true, CookiePartitionKey::FromURLForTesting(GURL("https://foo.com")), CookieSourceScheme::kNonSecure, 65536); @@ -115,15 +118,15 @@ TEST(CanonicalCookieTest, Constructor) { // Set Secure to true but don't specify source_scheme or port. auto cookie3 = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", ".www.example.com", "/", current_time, base::Time(), - base::Time(), true /* secure */, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false); + base::Time(), base::Time(), true /* secure */, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); EXPECT_TRUE(cookie3->IsSecure()); EXPECT_EQ(cookie3->SourceScheme(), CookieSourceScheme::kUnset); EXPECT_EQ(cookie3->SourcePort(), url::PORT_UNSPECIFIED); auto cookie4 = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", ".www.example.com", "/test", current_time, base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, + base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); EXPECT_EQ("A", cookie4->Name()); EXPECT_EQ("2", cookie4->Value()); @@ -140,17 +143,17 @@ TEST(CanonicalCookieTest, Constructor) { // Test some port edge cases: unspecified. auto cookie5 = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", ".www.example.com", "/", current_time, base::Time(), - base::Time(), true /* secure */, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false, absl::nullopt, CookieSourceScheme::kUnset, - url::PORT_UNSPECIFIED); + base::Time(), base::Time(), true /* secure */, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false, + absl::nullopt, CookieSourceScheme::kUnset, url::PORT_UNSPECIFIED); EXPECT_EQ(cookie5->SourcePort(), url::PORT_UNSPECIFIED); // Test some port edge cases: invalid. auto cookie6 = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", ".www.example.com", "/", current_time, base::Time(), - base::Time(), true /* secure */, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false, absl::nullopt, CookieSourceScheme::kUnset, - url::PORT_INVALID); + base::Time(), base::Time(), true /* secure */, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false, + absl::nullopt, CookieSourceScheme::kUnset, url::PORT_INVALID); EXPECT_EQ(cookie6->SourcePort(), url::PORT_INVALID); } @@ -451,6 +454,49 @@ TEST(CanonicalCookieTest, CreateWithInvalidDomain) { {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN})); } +TEST(CanonicalCookieTest, CreateWithNonASCIIDomain) { + GURL url("http://www.xn--xample-9ua.com/test/foo.html"); + base::Time now = base::Time::Now(); + absl::optional<base::Time> server_time = absl::nullopt; + + // Test with feature flag enabled. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kCookieDomainRejectNonASCII); + CookieInclusionStatus status; + + // Test that non-ascii characters are rejected. + std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create( + url, "A=1; Domain=\xC3\xA9xample.com", now, server_time, + absl::nullopt /* cookie_partition_key */, &status); + EXPECT_EQ(nullptr, cookie.get()); + EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( + {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN})); + } + + // Test with feature flag disabled. + { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(features::kCookieDomainRejectNonASCII); + CookieInclusionStatus status2; + + std::unique_ptr<CanonicalCookie> cookie2 = CanonicalCookie::Create( + url, "A=2; Domain=\xC3\xA9xample.com", now, server_time, + absl::nullopt /* cookie_partition_key */, &status2); + + EXPECT_TRUE(cookie2.get()); + EXPECT_TRUE(status2.IsInclude()); + } + + // Test that regular ascii punycode still works. + CookieInclusionStatus status3; + std::unique_ptr<CanonicalCookie> cookie3 = CanonicalCookie::Create( + url, "A=3; Domain=xn--xample-9ua.com", now, server_time, + absl::nullopt /* cookie_partition_key */, &status3); + EXPECT_TRUE(cookie3.get()); + EXPECT_TRUE(status3.IsInclude()); +} + TEST(CanonicalCookieTest, CreateWithDomainAsIP) { GURL url("http://1.1.1.1"); GURL url6("http://[2606:2800:220:1:248:1893:25c8:1946]"); @@ -617,14 +663,16 @@ TEST(CanonicalCookieTest, CreateWithPartitioned) { EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); - // Invalid Partitioned attribute: Domain cookie. + // Partitioned attribute: Domain cookie. status = CookieInclusionStatus(); cookie = CanonicalCookie::Create( - url, "A=2; Partitioned; Path=/; Domain=example.com", creation_time, - server_time, partition_key, &status); - EXPECT_FALSE(cookie.get()); - EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( - {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); + url, "A=2; Partitioned; Path=/; Secure; Domain=example.com", + creation_time, server_time, partition_key, &status); + EXPECT_TRUE(cookie.get()); + LOG(ERROR) << status; + EXPECT_TRUE(status.IsInclude()); + EXPECT_TRUE(cookie->IsPartitioned()); + EXPECT_EQ(partition_key, cookie->PartitionKey()); // Invalid Partitioned attribute: SameParty cookie. status = CookieInclusionStatus(); @@ -672,6 +720,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithMaxAge) { EXPECT_TRUE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Seconds(60) + creation_time, cookie->ExpiryDate()); + EXPECT_TRUE(cookie->IsCanonical()); // Max-age with expires (max-age should take precedence). cookie = CanonicalCookie::Create( @@ -681,6 +730,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithMaxAge) { EXPECT_TRUE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Seconds(60) + creation_time, cookie->ExpiryDate()); + EXPECT_TRUE(cookie->IsCanonical()); // Max-age=0 should create an expired cookie with expiry equal to the earliest // representable time. @@ -691,6 +741,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithMaxAge) { EXPECT_TRUE(cookie->IsPersistent()); EXPECT_TRUE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate()); + EXPECT_TRUE(cookie->IsCanonical()); // Negative max-age should create an expired cookie with expiry equal to the // earliest representable time. @@ -701,6 +752,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithMaxAge) { EXPECT_TRUE(cookie->IsPersistent()); EXPECT_TRUE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate()); + EXPECT_TRUE(cookie->IsCanonical()); // Max-age with whitespace (should be trimmed out). cookie = CanonicalCookie::Create(url, "A=1; max-age = 60 ; Secure", @@ -710,6 +762,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithMaxAge) { EXPECT_TRUE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Seconds(60) + creation_time, cookie->ExpiryDate()); + EXPECT_TRUE(cookie->IsCanonical()); // Max-age with non-integer should be ignored. cookie = CanonicalCookie::Create(url, "A=1; max-age=abcd", creation_time, @@ -718,6 +771,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithMaxAge) { EXPECT_TRUE(cookie.get()); EXPECT_FALSE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); + EXPECT_TRUE(cookie->IsCanonical()); // Overflow max-age should be clipped. cookie = CanonicalCookie::Create(url, @@ -735,6 +789,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithMaxAge) { } else { EXPECT_EQ(base::Time::Max(), cookie->ExpiryDate()); } + EXPECT_TRUE(cookie->IsCanonical()); // Underflow max-age should be clipped. cookie = CanonicalCookie::Create(url, @@ -748,6 +803,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithMaxAge) { EXPECT_TRUE(cookie->IsPersistent()); EXPECT_TRUE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate()); + EXPECT_TRUE(cookie->IsCanonical()); } TEST_P(CanonicalCookieWithClampingTest, CreateWithExpires) { @@ -765,6 +821,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithExpires) { EXPECT_TRUE(cookie->IsExpired(creation_time)); EXPECT_TRUE((past_date - cookie->ExpiryDate()).magnitude() < base::Seconds(1)); + EXPECT_TRUE(cookie->IsCanonical()); // Expires in the future base::Time future_date = base::Time::Now() + base::Days(10); @@ -776,6 +833,7 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithExpires) { EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_TRUE((future_date - cookie->ExpiryDate()).magnitude() < base::Seconds(1)); + EXPECT_TRUE(cookie->IsCanonical()); // Expires in the far future future_date = base::Time::Now() + base::Days(800); @@ -793,22 +851,29 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithExpires) { EXPECT_TRUE((future_date - cookie->ExpiryDate()).magnitude() < base::Seconds(1)); } + EXPECT_TRUE(cookie->IsCanonical()); // Expires in the far future using CreateUnsafeCookieForTesting. cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "1", url.host(), url.path(), creation_time, base::Time::Max(), - base::Time(), true, false, CookieSameSite::UNSPECIFIED, + base::Time(), base::Time(), true, false, CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_HIGH, false, absl::nullopt /* cookie_partition_key */, CookieSourceScheme::kSecure, 443); EXPECT_TRUE(cookie.get()); EXPECT_TRUE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Time::Max(), cookie->ExpiryDate()); + EXPECT_EQ(base::Time(), cookie->LastUpdateDate()); + if (IsClampCookieExpiryTo400DaysEnabled()) { + EXPECT_FALSE(cookie->IsCanonical()); + } else { + EXPECT_TRUE(cookie->IsCanonical()); + } // Expires in the far future using FromStorage. cookie = CanonicalCookie::FromStorage( "A", "B", "www.foo.com", "/bar", creation_time, base::Time::Max(), - base::Time(), false /*secure*/, false /*httponly*/, + base::Time(), base::Time(), false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 443); @@ -816,6 +881,12 @@ TEST_P(CanonicalCookieWithClampingTest, CreateWithExpires) { EXPECT_TRUE(cookie->IsPersistent()); EXPECT_FALSE(cookie->IsExpired(creation_time)); EXPECT_EQ(base::Time::Max(), cookie->ExpiryDate()); + EXPECT_EQ(base::Time(), cookie->LastUpdateDate()); + if (IsClampCookieExpiryTo400DaysEnabled()) { + EXPECT_FALSE(cookie->IsCanonical()); + } else { + EXPECT_TRUE(cookie->IsCanonical()); + } } TEST(CanonicalCookieTest, EmptyExpiry) { @@ -852,6 +923,54 @@ TEST(CanonicalCookieTest, EmptyExpiry) { EXPECT_EQ(base::Time(), cookie->ExpiryDate()); } +TEST_P(CanonicalCookieWithClampingTest, CreateWithLastUpdate) { + GURL url("http://www.example.com/test/foo.html"); + base::Time creation_time = base::Time::Now() - base::Days(1); + base::Time last_update_time = base::Time::Now() - base::Hours(1); + absl::optional<base::Time> server_time = absl::nullopt; + + // Creating a cookie sets the last update date as now. + std::unique_ptr<CanonicalCookie> cookie = + CanonicalCookie::Create(url, "A=1", creation_time, server_time, + /*cookie_partition_key=*/absl::nullopt); + ASSERT_TRUE(cookie.get()); + EXPECT_TRUE((base::Time::Now() - cookie->LastUpdateDate()).magnitude() < + base::Seconds(1)); + + // Creating a sanitized cookie sets the last update date as now. + cookie = CanonicalCookie::CreateSanitizedCookie( + url, "A", "1", url.host(), url.path(), creation_time, base::Time(), + creation_time, /*secure=*/true, + /*http_only=*/false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_DEFAULT, /*same_party=*/false, + /*partition_key=*/absl::nullopt); + ASSERT_TRUE(cookie.get()); + EXPECT_TRUE((base::Time::Now() - cookie->LastUpdateDate()).magnitude() < + base::Seconds(1)); + + // Creating an unsafe cookie allows us to set the last update date. + cookie = CanonicalCookie::CreateUnsafeCookieForTesting( + "A", "1", url.host(), url.path(), creation_time, base::Time(), + base::Time(), last_update_time, /*secure=*/true, + /*httponly=*/false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_DEFAULT, /*same_party=*/false, + /*partition_key=*/absl::nullopt, CookieSourceScheme::kSecure, + /*source_port=*/443); + ASSERT_TRUE(cookie.get()); + EXPECT_EQ(last_update_time, cookie->LastUpdateDate()); + + // Loading a cookie from storage allows us to set the last update date. + cookie = CanonicalCookie::FromStorage( + "A", "1", url.host(), url.path(), creation_time, base::Time(), + base::Time(), last_update_time, /*secure=*/true, + /*httponly=*/false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_DEFAULT, /*same_party=*/false, + /*partition_key=*/absl::nullopt, CookieSourceScheme::kSecure, + /*source_port=*/443); + ASSERT_TRUE(cookie.get()); + EXPECT_EQ(last_update_time, cookie->LastUpdateDate()); +} + TEST(CanonicalCookieTest, IsEquivalent) { GURL url("https://www.example.com/"); std::string cookie_name = "A"; @@ -860,6 +979,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { std::string cookie_path = "/path"; base::Time creation_time = base::Time::Now(); base::Time expiration_time = creation_time + base::Days(2); + base::Time update_time = creation_time + base::Days(1); bool secure = false; bool httponly = false; CookieSameSite same_site = CookieSameSite::NO_RESTRICTION; @@ -868,7 +988,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // Test that a cookie is equivalent to itself. auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_TRUE(cookie->IsEquivalent(*cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*cookie)); @@ -876,7 +996,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // Test that two identical cookies are equivalent. auto other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); @@ -885,7 +1005,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // DON'T affect cookie equivalence. other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, "2", cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_HIGH, same_party); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -894,7 +1014,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { base::Time other_creation_time = creation_time + base::Minutes(2); other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, "2", cookie_domain, cookie_path, other_creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -902,7 +1022,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), true, httponly, same_site, + expiration_time, base::Time(), update_time, true, httponly, same_site, COOKIE_PRIORITY_LOW, same_party); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -910,7 +1030,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, true, same_site, + expiration_time, base::Time(), update_time, secure, true, same_site, COOKIE_PRIORITY_LOW, same_party); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -918,16 +1038,26 @@ TEST(CanonicalCookieTest, IsEquivalent) { other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, + expiration_time, base::Time(), update_time, secure, httponly, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_LOW, same_party); EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); + // Test the effect of a differing last_update_time on equivalency. + other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( + cookie_name, cookie_name, cookie_domain, cookie_path, creation_time, + expiration_time, base::Time(), base::Time(), secure, httponly, same_site, + COOKIE_PRIORITY_LOW, same_party); + EXPECT_TRUE(cookie->IsEquivalent(*other_cookie)); + EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); + EXPECT_TRUE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie)); + EXPECT_FALSE(cookie->HasEquivalentDataMembers(*other_cookie)); + // Cookies whose names mismatch are not equivalent. other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "B", cookie_value, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -938,7 +1068,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // rules of 'IsEquivalentForSecureCookieMatching'. other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, "www.example.com", cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_TRUE(cookie->IsDomainCookie()); EXPECT_FALSE(other_cookie->IsDomainCookie()); @@ -950,7 +1080,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // 'www.example.com', but they are equivalent for secure cookie matching. other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, ".example.com", cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -963,7 +1093,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // equivalent for secure cookie matching to |other_cookie| set on '/'. other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, cookie_domain, "/test", creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -971,8 +1101,8 @@ TEST(CanonicalCookieTest, IsEquivalent) { other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, cookie_domain, cookie_path + "/subpath", - creation_time, expiration_time, base::Time(), secure, httponly, same_site, - COOKIE_PRIORITY_MEDIUM, same_party); + creation_time, expiration_time, base::Time(), update_time, secure, + httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); // The path comparison is asymmetric EXPECT_FALSE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -980,7 +1110,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, cookie_domain, "/", creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); EXPECT_TRUE(cookie->IsEquivalentForSecureCookieMatching(*other_cookie)); @@ -989,7 +1119,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // Partitioned cookies are not equivalent to unpartitioned cookies. other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party, CookiePartitionKey::FromURLForTesting(GURL("https://foo.com"))); EXPECT_FALSE(cookie->IsEquivalent(*other_cookie)); @@ -998,7 +1128,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // Partitioned cookies are equal if they have the same partition key. auto paritioned_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party, CookiePartitionKey::FromURLForTesting(GURL("https://foo.com"))); EXPECT_TRUE(paritioned_cookie->IsEquivalent(*other_cookie)); @@ -1008,7 +1138,7 @@ TEST(CanonicalCookieTest, IsEquivalent) { // Partitioned cookies with different partition keys are not equal other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( cookie_name, cookie_value, cookie_domain, cookie_path, creation_time, - expiration_time, base::Time(), secure, httponly, same_site, + expiration_time, base::Time(), update_time, secure, httponly, same_site, COOKIE_PRIORITY_MEDIUM, same_party, CookiePartitionKey::FromURLForTesting(GURL("https://bar.com"))); EXPECT_FALSE(paritioned_cookie->IsEquivalent(*other_cookie)); @@ -1073,14 +1203,15 @@ TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) { for (auto test : kTests) { auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting( test.cookie.name, "value1", test.cookie.domain, test.cookie.path, - base::Time(), base::Time(), base::Time(), false /* secure */, - false /* httponly */, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_MEDIUM, - false /* sameparty */, test.cookie.cookie_partition_key); + base::Time(), base::Time(), base::Time(), base::Time(), + false /* secure */, false /* httponly */, CookieSameSite::LAX_MODE, + COOKIE_PRIORITY_MEDIUM, false /* sameparty */, + test.cookie.cookie_partition_key); auto secure_cookie = CanonicalCookie::CreateUnsafeCookieForTesting( test.secure_cookie.name, "value2", test.secure_cookie.domain, test.secure_cookie.path, base::Time(), base::Time(), base::Time(), - true /* secure */, false /* httponly */, CookieSameSite::LAX_MODE, - COOKIE_PRIORITY_MEDIUM, false /* sameparty */, + base::Time(), true /* secure */, false /* httponly */, + CookieSameSite::LAX_MODE, COOKIE_PRIORITY_MEDIUM, false /* sameparty */, test.secure_cookie.cookie_partition_key); EXPECT_EQ(test.equivalent, @@ -1194,25 +1325,25 @@ TEST(CanonicalCookieTest, GetEffectiveSameSite) { // Recent session cookie. cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "example.test", "/", recent_creation_time, base::Time(), - base::Time(), true /* secure */, false /* httponly */, test.same_site, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), true /* secure */, false /* httponly */, + test.same_site, COOKIE_PRIORITY_DEFAULT, false)); // Recent persistent cookie. cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "example.test", "/", recent_creation_time, expiry_time, - base::Time(), true /* secure */, false /* httponly */, test.same_site, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), true /* secure */, false /* httponly */, + test.same_site, COOKIE_PRIORITY_DEFAULT, false)); } if (!test.is_cookie_recent.has_value() || !(*test.is_cookie_recent)) { // Not-recent session cookie. cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "example.test", "/", not_recent_creation_time, base::Time(), - base::Time(), true /* secure */, false /* httponly */, test.same_site, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), true /* secure */, false /* httponly */, + test.same_site, COOKIE_PRIORITY_DEFAULT, false)); // Not-recent persistent cookie. cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "example.test", "/", not_recent_creation_time, expiry_time, - base::Time(), true /* secure */, false /* httponly */, test.same_site, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), true /* secure */, false /* httponly */, + test.same_site, COOKIE_PRIORITY_DEFAULT, false)); } std::vector<CookieAccessSemantics> access_semantics = { @@ -1930,7 +2061,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURL_SameSiteNone_Metrics) { const auto make_cookie = [now](CookieSameSite same_site, bool same_party) { return CanonicalCookie::CreateUnsafeCookieForTesting( "A", "1", "www.example.com", "/test", now, base::Time(), base::Time(), - true /* secure */, false /*httponly*/, same_site, + base::Time(), true /* secure */, false /*httponly*/, same_site, COOKIE_PRIORITY_DEFAULT, same_party); }; GURL url("https://www.example.com/test"); @@ -2153,7 +2284,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURL_RedirectDowngradeWarning) { std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "1", "www.example.test", "/test", base::Time::Now(), - base::Time(), base::Time(), /*secure=*/true, + base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, samesite, COOKIE_PRIORITY_DEFAULT, /*same_party=*/false); @@ -2178,8 +2309,9 @@ TEST(CanonicalCookieTest, IncludeForRequestURL_RedirectDowngradeWarning) { std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "1", "www.example.test", "/test", base::Time::Now(), - base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, - test.samesite, COOKIE_PRIORITY_DEFAULT, /*same_party=*/false); + base::Time(), base::Time(), base::Time(), /*secure=*/true, + /*httponly=*/false, test.samesite, COOKIE_PRIORITY_DEFAULT, + /*same_party=*/false); CookieOptions options; options.set_same_site_cookie_context( @@ -2230,7 +2362,7 @@ TEST(CanonicalCookieTest, MultipleExclusionReasons) { // would weed it out. auto cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting( "name", "value", "other-domain.com", "/bar", creation_time, base::Time(), - base::Time(), true /* secure */, true /* httponly */, + base::Time(), base::Time(), true /* secure */, true /* httponly */, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false); EXPECT_THAT( cookie1->IncludeForRequestURL( @@ -2487,228 +2619,242 @@ TEST(CanonicalCookieTest, IsCanonical) { // Base correct template. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Newline in name. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A\n", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Carriage return in name. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A\r", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Null character in name. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( std::string("A\0Z", 3), "B", "x.y", "/path", base::Time(), - base::Time(), base::Time(), false, false, + base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Name begins with whitespace. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( " A", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Name ends with whitespace. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A ", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Empty name. (Note this is against the spec but compatible with other // browsers.) EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Space in name EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A C", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Extra space suffixing name. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A ", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // '=' character in name. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A=", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Separator in name. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A;", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // '=' character in value. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B=", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Separator in value. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B;", "x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Separator in domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", ";x.y", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Garbage in domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "@:&", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Space in domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y ", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Empty domain. (This is against cookie spec, but needed for Chrome's // out-of-spec use of cookies for extensions; see http://crbug.com/730633. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Path does not start with a "/". EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Empty path. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // "localhost" as domain. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "localhost", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) + ->IsCanonical()); + + // non-ASCII domain. + EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( + "A", "B", "\xC3\xA9xample.com", "/path", base::Time(), + base::Time(), base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) + ->IsCanonical()); + + // punycode domain. + EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( + "A", "B", "xn--xample-9ua.com", "/path", base::Time(), + base::Time(), base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Localhost IPv4 address as domain. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "127.0.0.1", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Simple IPv4 address as domain. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "1.2.3.4", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // period-prefixed IPv4 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", ".1.3.2.4", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // period-prefixed truncated IPv4 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", ".3.2.4", "/path", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // truncated IPv4 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "3.2.4", "/path", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Non-canonical IPv4 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "01.2.03.4", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Non-canonical IPv4 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "16843009", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Non-canonical IPv4 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "0x1010101", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Null IPv6 address as domain. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "[::]", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Localhost IPv6 address as domain. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "[::1]", "/path", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Fully speced IPv6 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "[2001:0DB8:AC10:FE01:0000:0000:0000:0000]", - "/path", base::Time(), base::Time(), base::Time(), false, - false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, - false) + "/path", base::Time(), base::Time(), base::Time(), + base::Time(), false, false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Zero abbreviated IPv6 address as domain. Not canonical because of leading // zeros & uppercase hex letters. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "[2001:0DB8:AC10:FE01::]", "/path", base::Time(), - base::Time(), base::Time(), false, false, + base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); @@ -2716,123 +2862,125 @@ TEST(CanonicalCookieTest, IsCanonical) { // uppercase hex letters. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "[2001:DB8:AC10:FE01::]", "/path", base::Time(), - base::Time(), base::Time(), false, false, + base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Lowercased hex IPv6 address as domain. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "[2001:db8:ac10:fe01::]", "/path", base::Time(), - base::Time(), base::Time(), false, false, + base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Lowercased hex IPv6 address as domain for domain cookie. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", ".[2001:db8:ac10:fe01::]", "/path", base::Time(), - base::Time(), base::Time(), false, false, + base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Incomplete lowercased hex IPv6 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "[2001:db8:ac10:fe01:]", "/path", base::Time(), - base::Time(), base::Time(), false, false, + base::Time(), base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Missing square brackets in IPv6 address as domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "2606:2800:220:1:248:1893:25c8:1946", "/path", - base::Time(), base::Time(), base::Time(), false, false, - CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), base::Time(), base::Time(), + false, false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Properly formatted host cookie. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Insecure host cookie. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Host cookie with non-null path. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-A", "B", "x.y", "/path", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Host cookie with empty domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-A", "B", "", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Host cookie with period prefixed domain. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-A", "B", ".x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Properly formatted secure cookie. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Secure-A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // Insecure secure cookie. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Secure-A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); // SameParty attribute used correctly (with Secure and non-Strict SameSite). EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, true) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, true) ->IsCanonical()); EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::UNSPECIFIED, - COOKIE_PRIORITY_LOW, true) + base::Time(), base::Time(), true, false, + CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_LOW, true) ->IsCanonical()); EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::LAX_MODE, - COOKIE_PRIORITY_LOW, true) + base::Time(), base::Time(), true, false, + CookieSameSite::LAX_MODE, COOKIE_PRIORITY_LOW, true) ->IsCanonical()); // SameParty without Secure is not canonical. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), false, false, CookieSameSite::LAX_MODE, - COOKIE_PRIORITY_LOW, true) + base::Time(), base::Time(), false, false, + CookieSameSite::LAX_MODE, COOKIE_PRIORITY_LOW, true) ->IsCanonical()); // SameParty with SameSite=Strict is not canonical. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::STRICT_MODE, - COOKIE_PRIORITY_LOW, true) + base::Time(), base::Time(), true, false, + CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_LOW, true) ->IsCanonical()); // Partitioned attribute used correctly (__Host- prefix, no SameParty). EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), /*secure=*/true, /*httponly=*/false, - CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_LOW, + base::Time(), base::Time(), /*secure=*/true, + /*httponly=*/false, CookieSameSite::UNSPECIFIED, + COOKIE_PRIORITY_LOW, /*same_party=*/false, CookiePartitionKey::FromURLForTesting( GURL("https://toplevelsite.com"))) @@ -2842,8 +2990,9 @@ TEST(CanonicalCookieTest, IsCanonical) { // Secure, Path=/, and no Domain. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), /*secure=*/true, /*httponly=*/false, - CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_LOW, + base::Time(), base::Time(), /*secure=*/true, + /*httponly=*/false, CookieSameSite::UNSPECIFIED, + COOKIE_PRIORITY_LOW, /*same_party=*/false, CookiePartitionKey::FromURLForTesting( GURL("https://toplevelsite.com"))) @@ -2852,8 +3001,9 @@ TEST(CanonicalCookieTest, IsCanonical) { // Partitioned attribute invalid, not Secure. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), /*secure=*/false, /*httponly=*/false, - CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_LOW, + base::Time(), base::Time(), /*secure=*/false, + /*httponly=*/false, CookieSameSite::UNSPECIFIED, + COOKIE_PRIORITY_LOW, /*same_party=*/false, CookiePartitionKey::FromURLForTesting( GURL("https://toplevelsite.com"))) @@ -2862,8 +3012,9 @@ TEST(CanonicalCookieTest, IsCanonical) { // Partitioned attribute invalid, no Path. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "", base::Time(), base::Time(), - base::Time(), /*secure=*/true, /*httponly=*/false, - CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_LOW, + base::Time(), base::Time(), /*secure=*/true, + /*httponly=*/false, CookieSameSite::UNSPECIFIED, + COOKIE_PRIORITY_LOW, /*same_party=*/false, CookiePartitionKey::FromURLForTesting( GURL("https://toplevelsite.com"))) @@ -2872,28 +3023,31 @@ TEST(CanonicalCookieTest, IsCanonical) { // Partitioned attribute invalid, invalid Path. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "x.y", "/foobar", base::Time(), base::Time(), - base::Time(), /*secure=*/true, /*httponly=*/false, - CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_LOW, + base::Time(), base::Time(), /*secure=*/true, + /*httponly=*/false, CookieSameSite::UNSPECIFIED, + COOKIE_PRIORITY_LOW, /*same_party=*/false, CookiePartitionKey::FromURLForTesting( GURL("https://toplevelsite.com"))) ->IsCanonical()); - // Partitioned attribute invalid, Domain attribute also included. - EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( - "A", "B", ".x.y", "/", base::Time(), base::Time(), - base::Time(), /*secure=*/true, /*httponly=*/false, - CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_LOW, - /*same_party=*/false, - CookiePartitionKey::FromURLForTesting( - GURL("https://toplevelsite.com"))) - ->IsCanonical()); + // Partitioned attribute is valid when Domain attribute also included. + EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( + "A", "B", ".x.y", "/", base::Time(), base::Time(), + base::Time(), base::Time(), /*secure=*/true, + /*httponly=*/false, CookieSameSite::UNSPECIFIED, + COOKIE_PRIORITY_LOW, + /*same_party=*/false, + CookiePartitionKey::FromURLForTesting( + GURL("https://toplevelsite.com"))) + ->IsCanonical()); // Partitioned attribute invalid, SameParty attribute also included. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-A", "B", "x.y", "/", base::Time(), base::Time(), - base::Time(), /*secure=*/true, /*httponly=*/false, - CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_LOW, + base::Time(), base::Time(), /*secure=*/true, + /*httponly=*/false, CookieSameSite::UNSPECIFIED, + COOKIE_PRIORITY_LOW, /*same_party=*/true, CookiePartitionKey::FromURLForTesting( GURL("https://toplevelsite.com"))) @@ -2902,33 +3056,34 @@ TEST(CanonicalCookieTest, IsCanonical) { // Hidden cookie prefixes. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "", "__Secure-a=b", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "", "__Host-a=b", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "a", "__Secure-a=b", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( "a", "__Host-a=b", "x.y", "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_LOW, false) + base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false) ->IsCanonical()); } TEST(CanonicalCookieTest, TestSetCreationDate) { auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting( - "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), false, - false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW, false); + "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(), + base::Time(), false, false, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_LOW, false); EXPECT_TRUE(cookie->CreationDate().is_null()); base::Time now(base::Time::Now()); @@ -3684,9 +3839,9 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) { &status)); EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); - // Invalid: Domain attribute present. + // Domain attribute present is still valid. status = CookieInclusionStatus(); - EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie( + EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie( GURL("https://www.foo.com"), "A", "B", ".foo.com", "/", two_hours_ago, one_hour_from_now, one_hour_ago, /*secure=*/true, /*http_only=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -3694,8 +3849,7 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) { absl::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting( GURL("https://toplevelsite.com"))), &status)); - EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( - {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); + EXPECT_TRUE(status.IsInclude()); // Invalid: SameParty attribute present. status = CookieInclusionStatus(); EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie( @@ -3971,7 +4125,7 @@ TEST(CanonicalCookieTest, FromStorage) { std::unique_ptr<CanonicalCookie> cc = CanonicalCookie::FromStorage( "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now, - one_hour_ago, false /*secure*/, false /*httponly*/, + one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 87); @@ -3983,6 +4137,7 @@ TEST(CanonicalCookieTest, FromStorage) { EXPECT_EQ(two_hours_ago, cc->CreationDate()); EXPECT_EQ(one_hour_ago, cc->LastAccessDate()); EXPECT_EQ(one_hour_from_now, cc->ExpiryDate()); + EXPECT_EQ(one_hour_ago, cc->LastUpdateDate()); EXPECT_FALSE(cc->IsSecure()); EXPECT_FALSE(cc->IsHttpOnly()); EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cc->SameSite()); @@ -3996,7 +4151,7 @@ TEST(CanonicalCookieTest, FromStorage) { // contains a newline character. EXPECT_FALSE(CanonicalCookie::FromStorage( "A\n", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now, - one_hour_ago, false /*secure*/, false /*httponly*/, + one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 80)); @@ -4005,7 +4160,7 @@ TEST(CanonicalCookieTest, FromStorage) { // FromStorage() should result in a PORT_INVALID. std::unique_ptr<CanonicalCookie> cc2 = CanonicalCookie::FromStorage( "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now, - one_hour_ago, false /*secure*/, false /*httponly*/, + one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 80000); @@ -4015,7 +4170,7 @@ TEST(CanonicalCookieTest, FromStorage) { // Test port edge cases: unspecified. std::unique_ptr<CanonicalCookie> cc3 = CanonicalCookie::FromStorage( "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now, - one_hour_ago, false /*secure*/, false /*httponly*/, + one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, url::PORT_UNSPECIFIED); @@ -4024,7 +4179,7 @@ TEST(CanonicalCookieTest, FromStorage) { // Test port edge cases: invalid. std::unique_ptr<CanonicalCookie> cc4 = CanonicalCookie::FromStorage( "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now, - one_hour_ago, false /*secure*/, false /*httponly*/, + one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, url::PORT_INVALID); @@ -4038,11 +4193,11 @@ TEST(CanonicalCookieTest, IsSetPermittedInContext) { auto cookie_scriptable = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); auto cookie_httponly = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, true /*httponly*/, + base::Time(), base::Time(), true /*secure*/, true /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); CookieOptions context_script; @@ -4143,7 +4298,7 @@ TEST(CanonicalCookieTest, IsSetPermittedInContext) { auto cookie_same_site_unrestricted = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); EXPECT_THAT( @@ -4248,7 +4403,7 @@ TEST(CanonicalCookieTest, IsSetPermittedInContext) { { auto cookie_same_site_lax = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false); EXPECT_THAT( @@ -4373,7 +4528,7 @@ TEST(CanonicalCookieTest, IsSetPermittedInContext) { auto cookie_same_site_strict = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false); // TODO(morlovich): Do compatibility testing on whether set of strict in lax @@ -4537,7 +4692,7 @@ TEST(CanonicalCookieTest, IsSetPermittedInContext) { auto cookie_same_site_unspecified = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, false); EXPECT_THAT( @@ -4656,7 +4811,7 @@ TEST(CanonicalCookieTest, IsSetPermittedEffectiveSameSite) { // CanonicalCookie with CookieSameSite::NO_RESTRICTION. auto cookie_no_restriction = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); EXPECT_THAT( @@ -4673,7 +4828,7 @@ TEST(CanonicalCookieTest, IsSetPermittedEffectiveSameSite) { // CanonicalCookie with CookieSameSite::LAX_MODE. auto cookie_lax = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false); EXPECT_THAT( @@ -4690,7 +4845,7 @@ TEST(CanonicalCookieTest, IsSetPermittedEffectiveSameSite) { // CanonicalCookie with CookieSameSite::STRICT_MODE. auto cookie_strict = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false); EXPECT_THAT( @@ -4708,11 +4863,11 @@ TEST(CanonicalCookieTest, IsSetPermittedEffectiveSameSite) { base::Time creation_time = base::Time::Now() - (kLaxAllowUnsafeMaxAge * 4); auto cookie_old_unspecified = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", creation_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, false); auto cookie_unspecified = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /*secure*/, false /*httponly*/, + base::Time(), base::Time(), true /*secure*/, false /*httponly*/, CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, false); EXPECT_THAT( @@ -4776,7 +4931,7 @@ TEST(CanonicalCookieTest, IsSetPermitted_AllowedToAccessSecureCookies) { continue; auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), secure, false /*httponly*/, same_site, + base::Time(), base::Time(), secure, false /*httponly*/, same_site, COOKIE_PRIORITY_DEFAULT, same_party); for (bool delegate_treats_url_as_trustworthy : {false, true}) { @@ -4839,7 +4994,7 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameSiteNone_Metrics) { const auto make_cookie = [now](CookieSameSite same_site, bool same_party) { return CanonicalCookie::CreateUnsafeCookieForTesting( "A", "1", "www.example.com", "/test", now, base::Time(), base::Time(), - true /* secure */, false /*httponly*/, same_site, + base::Time(), true /* secure */, false /*httponly*/, same_site, COOKIE_PRIORITY_DEFAULT, same_party); }; GURL url("https://www.example.com/test"); @@ -4993,7 +5148,7 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameParty) { bool delegate_treats_url_as_trustworthy = false; auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /* secure */, false /*httponly*/, + base::Time(), base::Time(), true /* secure */, false /*httponly*/, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, true /* same_party */); @@ -5020,8 +5175,8 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameParty) { }) { auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "2", "www.example.com", "/test", current_time, base::Time(), - base::Time(), true /* secure */, false /*httponly*/, same_site, - COOKIE_PRIORITY_DEFAULT, true /* same_party */); + base::Time(), base::Time(), true /* secure */, false /*httponly*/, + same_site, COOKIE_PRIORITY_DEFAULT, true /* same_party */); for (bool delegate_treats_url_as_trustworthy : {false, true}) { for (CookieAccessSemantics access_semantics : { @@ -5082,7 +5237,7 @@ TEST(CanonicalCookieTest, IsSetPermittedInContext_RedirectDowngradeWarning) { std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "1", "www.example.test", "/test", base::Time::Now(), - base::Time(), base::Time(), /*secure=*/true, + base::Time(), base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, samesite, COOKIE_PRIORITY_DEFAULT, /*same_party=*/false); @@ -5108,8 +5263,9 @@ TEST(CanonicalCookieTest, IsSetPermittedInContext_RedirectDowngradeWarning) { std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "A", "1", "www.example.test", "/test", base::Time::Now(), - base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false, - test.samesite, COOKIE_PRIORITY_DEFAULT, /*same_party=*/false); + base::Time(), base::Time(), base::Time(), /*secure=*/true, + /*httponly=*/false, test.samesite, COOKIE_PRIORITY_DEFAULT, + /*same_party=*/false); Context::ContextMetadata lax_cross_downgrade_metadata; lax_cross_downgrade_metadata.cross_site_redirect_downgrade = @@ -5166,7 +5322,7 @@ TEST(CanonicalCookieTest, TestIsCanonicalWithInvalidSizeHistograms) { // Test a cookie that is canonical and valid size EXPECT_TRUE(CanonicalCookie::FromStorage( "A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now, - one_hour_ago, false /*secure*/, false /*httponly*/, + one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 87)); @@ -5180,13 +5336,13 @@ TEST(CanonicalCookieTest, TestIsCanonicalWithInvalidSizeHistograms) { const std::string kCookieBig(4096, 'a'); EXPECT_TRUE(CanonicalCookie::FromStorage( kCookieBig, "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now, - one_hour_ago, false /*secure*/, false /*httponly*/, + one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 87)); EXPECT_TRUE(CanonicalCookie::FromStorage( "A", kCookieBig, "www.foo.com", "/bar", two_hours_ago, one_hour_from_now, - one_hour_ago, false /*secure*/, false /*httponly*/, + one_hour_ago, one_hour_ago, false /*secure*/, false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /*same_party*/, absl::nullopt /*partition_key*/, CookieSourceScheme::kSecure, 87)); diff --git a/chromium/net/cookies/cookie_deletion_info.h b/chromium/net/cookies/cookie_deletion_info.h index 5158f45211c..c066f13f8af 100644 --- a/chromium/net/cookies/cookie_deletion_info.h +++ b/chromium/net/cookies/cookie_deletion_info.h @@ -141,9 +141,9 @@ struct NET_EXPORT CookieDeletionInfo { // Used only for testing purposes. absl::optional<std::string> value_for_testing; - // Cookie partition keychain. Partitioned cookies are not deleted if their - // partition key is not in the keychain. By default, it clears cookies in all - // partitions. + // Cookie partition collection. Partitioned cookies are not deleted if their + // partition key is not in the collection. By default, it clears cookies in + // all partitions. CookiePartitionKeyCollection cookie_partition_key_collection = CookiePartitionKeyCollection::ContainsAll(); }; diff --git a/chromium/net/cookies/cookie_deletion_info_unittest.cc b/chromium/net/cookies/cookie_deletion_info_unittest.cc index f316103f891..a21021e7cf5 100644 --- a/chromium/net/cookies/cookie_deletion_info_unittest.cc +++ b/chromium/net/cookies/cookie_deletion_info_unittest.cc @@ -88,6 +88,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchSessionControl) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -98,6 +99,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchSessionControl) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -149,6 +151,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchHost) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -160,6 +163,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchHost) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -224,6 +228,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchName) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -234,6 +239,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchName) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -260,6 +266,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchValue) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -270,6 +277,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchValue) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -296,6 +304,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchUrl) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, @@ -349,6 +358,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoDomainMatchesDomain) { /*creation=*/base::Time::FromDoubleT(kTestMinEpoch + 1), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::FromDoubleT(kTestMinEpoch + 1), + /*last_update=*/base::Time::Now(), /*secure=*/true, /*httponly=*/false, /*same_site=*/CookieSameSite::NO_RESTRICTION, @@ -417,6 +427,7 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchesDomainList) { /*creation=*/base::Time::Now(), /*expiration=*/base::Time::Max(), /*last_access=*/base::Time::Now(), + /*last_update=*/base::Time::Now(), /*secure=*/false, /*httponly=*/false, /*same_site=*/CookieSameSite::NO_RESTRICTION, diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc index 73172c5c884..644e5fc1371 100644 --- a/chromium/net/cookies/cookie_monster.cc +++ b/chromium/net/cookies/cookie_monster.cc @@ -364,18 +364,11 @@ CookieMonster::CookieMonster(scoped_refptr<PersistentCookieStore> store, base::TimeDelta last_access_threshold, NetLog* net_log, bool first_party_sets_enabled) - : num_keys_(0u), - num_partitioned_cookies_(0u), - change_dispatcher_(this, first_party_sets_enabled), - initialized_(false), - started_fetching_all_cookies_(false), - finished_fetching_all_cookies_(false), - seen_global_task_(false), + : change_dispatcher_(this, first_party_sets_enabled), net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::COOKIE_STORE)), store_(std::move(store)), last_access_threshold_(last_access_threshold), last_statistic_record_time_(base::Time::Now()), - persist_session_cookies_(false), first_party_sets_enabled_(first_party_sets_enabled) { cookieable_schemes_.insert( cookieable_schemes_.begin(), kDefaultCookieableSchemes, @@ -2412,9 +2405,18 @@ void CookieMonster::OnConvertPartitionedCookiesToUnpartitioned( // We only want cookies whose domain is a match for the entire URL host. // This should exclude cookies set on subdomains. std::vector<CanonicalCookie*> cookie_ptrs; + CookieOptions options = CookieOptions::MakeAllInclusive(); + bool delegate_treats_url_as_trustworthy = + cookie_access_delegate() && + cookie_access_delegate()->ShouldTreatUrlAsTrustworthy(url); + CookieAccessParams accesss_params{ + net::CookieAccessSemantics::UNKNOWN, delegate_treats_url_as_trustworthy, + CookieSamePartyStatus::kNoSamePartyEnforcement}; for (auto* cookie : cookie_ptrs_for_site) { - if (cookie->Domain() == url.host()) + if (cookie->IncludeForRequestURL(url, options, accesss_params) + .status.IsInclude()) { cookie_ptrs.push_back(cookie); + } } std::map<std::tuple<std::string, std::string, std::string>, @@ -2445,9 +2447,19 @@ void CookieMonster::OnConvertPartitionedCookiesToUnpartitioned( cookie_to_convert = *kv_pair.second[0]; } else { for (const auto* cookie : kv_pair.second) { - // If the site only has partitioned cookies, we convert the most - // recently accessed cookie to unpartitioned and delete the rest. + // If the site only has partitioned cookies, we first check if there is + // a cookie whose partition key is same-site with the cookie's domain. + // + // If there are no partitioned cookies whose partition key is same-site + // with the cookie's domain, we convert the most recently accessed + // cookie to unpartitioned and delete the rest. if (cookie->IsPartitioned() && !cookie->PartitionKey()->nonce()) { + if (cookie->PartitionKey()->site() == + SchemefulSite(GURL("https://" + cookie->DomainWithoutDot()))) { + should_convert_cookie = true; + cookie_to_convert = *cookie; + break; + } if (!should_convert_cookie || cookie->LastAccessDate() > cookie_to_convert.LastAccessDate()) { should_convert_cookie = true; @@ -2480,13 +2492,14 @@ void CookieMonster::OnConvertPartitionedCookiesToUnpartitioned( CanonicalCookie* cc = cur_cookie_it->second.get(); ++cookie_it; - if (cc->Domain() != url.host()) + if (!cc->IncludeForRequestURL(url, options, accesss_params) + .status.IsInclude() || + cc->PartitionKey()->nonce()) { continue; - - if (!cc->PartitionKey()->nonce()) { - InternalDeletePartitionedCookie(cur_partition_it, cur_cookie_it, true, - DELETE_COOKIE_EXPLICIT); } + + InternalDeletePartitionedCookie(cur_partition_it, cur_cookie_it, true, + DELETE_COOKIE_EXPLICIT); } } } @@ -2497,8 +2510,8 @@ void CookieMonster::ConvertPartitionedCookie(const net::CanonicalCookie& cookie, auto new_cookie = net::CanonicalCookie::FromStorage( cookie.Name(), cookie.Value(), cookie.Domain(), cookie.Path(), cookie.CreationDate(), cookie.ExpiryDate(), base::Time::Now(), - cookie.IsSecure(), cookie.IsHttpOnly(), cookie.SameSite(), - cookie.Priority(), cookie.IsSameParty(), absl::nullopt, + cookie.LastUpdateDate(), cookie.IsSecure(), cookie.IsHttpOnly(), + cookie.SameSite(), cookie.Priority(), cookie.IsSameParty(), absl::nullopt, cookie.SourceScheme(), cookie.SourcePort()); DCHECK(new_cookie); diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h index 659a346d80d..d2cfebf4900 100644 --- a/chromium/net/cookies/cookie_monster.h +++ b/chromium/net/cookies/cookie_monster.h @@ -730,7 +730,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // The number of distinct keys (eTLD+1's) currently present in the |cookies_| // multimap. This is histogrammed periodically. - size_t num_keys_; + size_t num_keys_ = 0u; CookieMap cookies_; @@ -738,17 +738,17 @@ class NET_EXPORT CookieMonster : public CookieStore { // Number of distinct partitioned cookies globally. This is used to enforce a // global maximum on the number of partitioned cookies. - size_t num_partitioned_cookies_; + size_t num_partitioned_cookies_ = 0u; CookieMonsterChangeDispatcher change_dispatcher_; // Indicates whether the cookie store has been initialized. - bool initialized_; + bool initialized_ = false; // Indicates whether the cookie store has started fetching all cookies. - bool started_fetching_all_cookies_; + bool started_fetching_all_cookies_ = false; // Indicates whether the cookie store has finished fetching all cookies. - bool finished_fetching_all_cookies_; + bool finished_fetching_all_cookies_ = false; // List of domain keys that have been loaded from the DB. std::set<std::string> keys_loaded_; @@ -768,7 +768,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // view of the cookie store. This is 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_; + bool seen_global_task_ = false; NetLogWithSource net_log_; @@ -793,7 +793,7 @@ class NET_EXPORT CookieMonster : public CookieStore { base::Time last_statistic_record_time_; - bool persist_session_cookies_; + bool persist_session_cookies_ = false; bool first_party_sets_enabled_; diff --git a/chromium/net/cookies/cookie_monster_change_dispatcher.cc b/chromium/net/cookies/cookie_monster_change_dispatcher.cc index d9e41f20239..cf928360284 100644 --- a/chromium/net/cookies/cookie_monster_change_dispatcher.cc +++ b/chromium/net/cookies/cookie_monster_change_dispatcher.cc @@ -183,7 +183,7 @@ CookieMonsterChangeDispatcher::AddCallbackForAllChanges( std::unique_ptr<Subscription> subscription = std::make_unique<Subscription>( weak_ptr_factory_.GetWeakPtr(), std::string(kGlobalDomainKey), - std::string(kGlobalNameKey), GURL(""), CookiePartitionKey::Todo(), + std::string(kGlobalNameKey), GURL(""), absl::nullopt, first_party_sets_enabled_, std::move(callback)); LinkSubscription(subscription.get()); diff --git a/chromium/net/cookies/cookie_monster_netlog_params.cc b/chromium/net/cookies/cookie_monster_netlog_params.cc index fad5f472ee6..8215b9c0456 100644 --- a/chromium/net/cookies/cookie_monster_netlog_params.cc +++ b/chromium/net/cookies/cookie_monster_netlog_params.cc @@ -10,9 +10,9 @@ namespace net { base::Value NetLogCookieMonsterConstructorParams(bool persistent_store) { - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetBoolKey("persistent_store", persistent_store); - return dict; + base::Value::Dict dict; + dict.Set("persistent_store", persistent_store); + return base::Value(std::move(dict)); } base::Value NetLogCookieMonsterCookieAdded(const CanonicalCookie* cookie, @@ -21,19 +21,19 @@ base::Value NetLogCookieMonsterCookieAdded(const CanonicalCookie* cookie, if (!NetLogCaptureIncludesSensitive(capture_mode)) return base::Value(); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("name", cookie->Name()); - dict.SetStringKey("value", cookie->Value()); - dict.SetStringKey("domain", cookie->Domain()); - dict.SetStringKey("path", cookie->Path()); - dict.SetBoolKey("httponly", cookie->IsHttpOnly()); - dict.SetBoolKey("secure", cookie->IsSecure()); - dict.SetStringKey("priority", CookiePriorityToString(cookie->Priority())); - dict.SetStringKey("same_site", CookieSameSiteToString(cookie->SameSite())); - dict.SetBoolKey("is_persistent", cookie->IsPersistent()); - dict.SetBoolKey("sync_requested", sync_requested); - dict.SetBoolKey("same_party", cookie->IsSameParty()); - return dict; + base::Value::Dict dict; + dict.Set("name", cookie->Name()); + dict.Set("value", cookie->Value()); + dict.Set("domain", cookie->Domain()); + dict.Set("path", cookie->Path()); + dict.Set("httponly", cookie->IsHttpOnly()); + dict.Set("secure", cookie->IsSecure()); + dict.Set("priority", CookiePriorityToString(cookie->Priority())); + dict.Set("same_site", CookieSameSiteToString(cookie->SameSite())); + dict.Set("is_persistent", cookie->IsPersistent()); + dict.Set("sync_requested", sync_requested); + dict.Set("same_party", cookie->IsSameParty()); + return base::Value(std::move(dict)); } base::Value NetLogCookieMonsterCookieDeleted(const CanonicalCookie* cookie, @@ -43,15 +43,15 @@ base::Value NetLogCookieMonsterCookieDeleted(const CanonicalCookie* cookie, if (!NetLogCaptureIncludesSensitive(capture_mode)) return base::Value(); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("name", cookie->Name()); - dict.SetStringKey("value", cookie->Value()); - dict.SetStringKey("domain", cookie->Domain()); - dict.SetStringKey("path", cookie->Path()); - dict.SetBoolKey("is_persistent", cookie->IsPersistent()); - dict.SetStringKey("deletion_cause", CookieChangeCauseToString(cause)); - dict.SetBoolKey("sync_requested", sync_requested); - return dict; + base::Value::Dict dict; + dict.Set("name", cookie->Name()); + dict.Set("value", cookie->Value()); + dict.Set("domain", cookie->Domain()); + dict.Set("path", cookie->Path()); + dict.Set("is_persistent", cookie->IsPersistent()); + dict.Set("deletion_cause", CookieChangeCauseToString(cause)); + dict.Set("sync_requested", sync_requested); + return base::Value(std::move(dict)); } base::Value NetLogCookieMonsterCookieRejectedSecure( @@ -60,14 +60,14 @@ base::Value NetLogCookieMonsterCookieRejectedSecure( NetLogCaptureMode capture_mode) { if (!NetLogCaptureIncludesSensitive(capture_mode)) return base::Value(); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("name", old_cookie->Name()); - dict.SetStringKey("domain", old_cookie->Domain()); - dict.SetStringKey("oldpath", old_cookie->Path()); - dict.SetStringKey("newpath", new_cookie->Path()); - dict.SetStringKey("oldvalue", old_cookie->Value()); - dict.SetStringKey("newvalue", new_cookie->Value()); - return dict; + base::Value::Dict dict; + dict.Set("name", old_cookie->Name()); + dict.Set("domain", old_cookie->Domain()); + dict.Set("oldpath", old_cookie->Path()); + dict.Set("newpath", new_cookie->Path()); + dict.Set("oldvalue", old_cookie->Value()); + dict.Set("newvalue", new_cookie->Value()); + return base::Value(std::move(dict)); } base::Value NetLogCookieMonsterCookieRejectedHttponly( @@ -76,13 +76,13 @@ base::Value NetLogCookieMonsterCookieRejectedHttponly( NetLogCaptureMode capture_mode) { if (!NetLogCaptureIncludesSensitive(capture_mode)) return base::Value(); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("name", old_cookie->Name()); - dict.SetStringKey("domain", old_cookie->Domain()); - dict.SetStringKey("path", old_cookie->Path()); - dict.SetStringKey("oldvalue", old_cookie->Value()); - dict.SetStringKey("newvalue", new_cookie->Value()); - return dict; + base::Value::Dict dict; + dict.Set("name", old_cookie->Name()); + dict.Set("domain", old_cookie->Domain()); + dict.Set("path", old_cookie->Path()); + dict.Set("oldvalue", old_cookie->Value()); + dict.Set("newvalue", new_cookie->Value()); + return base::Value(std::move(dict)); } base::Value NetLogCookieMonsterCookiePreservedSkippedSecure( @@ -92,15 +92,15 @@ base::Value NetLogCookieMonsterCookiePreservedSkippedSecure( NetLogCaptureMode capture_mode) { if (!NetLogCaptureIncludesSensitive(capture_mode)) return base::Value(); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetStringKey("name", preserved->Name()); - dict.SetStringKey("domain", preserved->Domain()); - dict.SetStringKey("path", preserved->Path()); - dict.SetStringKey("securecookiedomain", skipped_secure->Domain()); - dict.SetStringKey("securecookiepath", skipped_secure->Path()); - dict.SetStringKey("preservedvalue", preserved->Value()); - dict.SetStringKey("discardedvalue", new_cookie->Value()); - return dict; + base::Value::Dict dict; + dict.Set("name", preserved->Name()); + dict.Set("domain", preserved->Domain()); + dict.Set("path", preserved->Path()); + dict.Set("securecookiedomain", skipped_secure->Domain()); + dict.Set("securecookiepath", skipped_secure->Path()); + dict.Set("preservedvalue", preserved->Value()); + dict.Set("discardedvalue", new_cookie->Value()); + return base::Value(std::move(dict)); } } // namespace net diff --git a/chromium/net/cookies/cookie_monster_perftest.cc b/chromium/net/cookies/cookie_monster_perftest.cc index 85558110f21..12de7b53e46 100644 --- a/chromium/net/cookies/cookie_monster_perftest.cc +++ b/chromium/net/cookies/cookie_monster_perftest.cc @@ -72,7 +72,7 @@ class CookieMonsterTest : public testing::Test { class CookieTestCallback { public: - CookieTestCallback() : has_run_(false) {} + CookieTestCallback() = default; protected: void WaitForCallback() { @@ -88,7 +88,7 @@ class CookieTestCallback { void Run() { has_run_ = true; } - bool has_run_; + bool has_run_ = false; }; class SetCookieCallback : public CookieTestCallback { diff --git a/chromium/net/cookies/cookie_monster_store_test.cc b/chromium/net/cookies/cookie_monster_store_test.cc index 4170ea3a381..1bc8e950827 100644 --- a/chromium/net/cookies/cookie_monster_store_test.cc +++ b/chromium/net/cookies/cookie_monster_store_test.cc @@ -30,8 +30,7 @@ CookieStoreCommand::CookieStoreCommand(Type type, const CanonicalCookie& cookie) CookieStoreCommand::CookieStoreCommand(CookieStoreCommand&& other) = default; CookieStoreCommand::~CookieStoreCommand() = default; -MockPersistentCookieStore::MockPersistentCookieStore() - : store_load_commands_(false), load_return_value_(true), loaded_(false) {} +MockPersistentCookieStore::MockPersistentCookieStore() = default; void MockPersistentCookieStore::SetLoadExpectation( bool return_value, @@ -121,8 +120,8 @@ std::unique_ptr<CanonicalCookie> BuildCanonicalCookie( return CanonicalCookie::CreateUnsafeCookieForTesting( pc.Name(), pc.Value(), "." + url.host(), cookie_path, creation_time, - cookie_expires, base::Time(), pc.IsSecure(), pc.IsHttpOnly(), - pc.SameSite(), pc.Priority(), pc.IsSameParty()); + cookie_expires, base::Time(), base::Time(), pc.IsSecure(), + pc.IsHttpOnly(), pc.SameSite(), pc.Priority(), pc.IsSameParty()); } void AddCookieToList(const GURL& url, @@ -135,9 +134,7 @@ void AddCookieToList(const GURL& url, out_list->push_back(std::move(cookie)); } -MockSimplePersistentCookieStore::MockSimplePersistentCookieStore() - : loaded_(false) { -} +MockSimplePersistentCookieStore::MockSimplePersistentCookieStore() = default; void MockSimplePersistentCookieStore::Load( LoadedCallback loaded_callback, @@ -205,7 +202,7 @@ std::unique_ptr<CookieMonster> CreateMonsterFromStoreForGC( int num_old_non_secure_cookies, int days_old) { base::Time current(base::Time::Now()); - base::Time past_creation(base::Time::Now() - base::Days(1000)); + base::Time past_creation(base::Time::Now() - base::Days(100)); scoped_refptr<MockSimplePersistentCookieStore> store( new MockSimplePersistentCookieStore); int total_cookies = num_secure_cookies + num_non_secure_cookies; @@ -234,8 +231,9 @@ std::unique_ptr<CookieMonster> CreateMonsterFromStoreForGC( std::unique_ptr<CanonicalCookie> cc = CanonicalCookie::CreateUnsafeCookieForTesting( "a", "1", base::StringPrintf("h%05d.izzle", i), "/path", - creation_time, expiration_time, base::Time(), secure, false, - CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); + creation_time, expiration_time, base::Time(), base::Time(), secure, + false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, + false); cc->SetLastAccessDate(last_access_time); store->AddCookie(*cc); } diff --git a/chromium/net/cookies/cookie_monster_store_test.h b/chromium/net/cookies/cookie_monster_store_test.h index 8f3b96abcfa..6250ebba5ea 100644 --- a/chromium/net/cookies/cookie_monster_store_test.h +++ b/chromium/net/cookies/cookie_monster_store_test.h @@ -119,14 +119,14 @@ class MockPersistentCookieStore : public CookieMonster::PersistentCookieStore { private: CommandList commands_; - bool store_load_commands_; + bool store_load_commands_ = false; // Deferred result to use when Load() is called. - bool load_return_value_; + bool load_return_value_ = true; std::vector<std::unique_ptr<CanonicalCookie>> load_result_; // Indicates if the store has been fully loaded to avoid returning duplicate // cookies. - bool loaded_; + bool loaded_ = false; }; // Helper to build a single CanonicalCookie. @@ -177,7 +177,7 @@ class MockSimplePersistentCookieStore // Indicates if the store has been fully loaded to avoid return duplicate // cookies in subsequent load requests - bool loaded_; + bool loaded_ = false; }; // Helper function for creating a CookieMonster backed by a diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc index 88521a44187..f143924451e 100644 --- a/chromium/net/cookies/cookie_monster_unittest.cc +++ b/chromium/net/cookies/cookie_monster_unittest.cc @@ -32,9 +32,11 @@ #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" +#include "base/test/scoped_feature_list.h" #include "base/threading/thread.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "net/base/features.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/canonical_cookie_test_helpers.h" #include "net/cookies/cookie_change_dispatcher.h" @@ -81,6 +83,26 @@ MATCHER_P2(MatchesCookieNameDomain, name, domain, "") { arg, result_listener); } +MATCHER_P4(MatchesCookieNameValueCreationExpiry, + name, + value, + creation, + expiry, + "") { + return testing::ExplainMatchResult( + testing::AllOf( + testing::Property(&net::CanonicalCookie::Name, name), + testing::Property(&net::CanonicalCookie::Value, value), + testing::Property(&net::CanonicalCookie::CreationDate, creation), + // We need a margin of error when testing the ExpiryDate as, if + // clamped, it is set relative to the current time. + testing::Property(&net::CanonicalCookie::ExpiryDate, + testing::Gt(expiry - base::Minutes(1))), + testing::Property(&net::CanonicalCookie::ExpiryDate, + testing::Lt(expiry + base::Minutes(1)))), + arg, result_listener); +} + const char kTopLevelDomainPlus1[] = "http://www.harvard.edu"; const char kTopLevelDomainPlus2[] = "http://www.math.harvard.edu"; const char kTopLevelDomainPlus2Secure[] = "https://www.math.harvard.edu"; @@ -248,89 +270,89 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { // Domain cookies cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "dom_1", "A", ".harvard.edu", "/", now, base::Time(), base::Time(), - false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, - false)); + base::Time(), false, false, CookieSameSite::LAX_MODE, + COOKIE_PRIORITY_DEFAULT, false)); cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "dom_2", "B", ".math.harvard.edu", "/", now, base::Time(), base::Time(), - false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, - false)); + base::Time(), false, false, CookieSameSite::LAX_MODE, + COOKIE_PRIORITY_DEFAULT, false)); cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "dom_3", "C", ".bourbaki.math.harvard.edu", "/", now, base::Time(), - base::Time(), false, false, CookieSameSite::LAX_MODE, + base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); // Host cookies cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "host_1", "A", url_top_level_domain_plus_1, "/", now, base::Time(), - base::Time(), false, false, CookieSameSite::LAX_MODE, + base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "host_2", "B", url_top_level_domain_plus_2, "/", now, base::Time(), - base::Time(), false, false, CookieSameSite::LAX_MODE, + base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "host_3", "C", url_top_level_domain_plus_3, "/", now, base::Time(), - base::Time(), false, false, CookieSameSite::LAX_MODE, + base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); // http_only cookie cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "httpo_check", "A", url_top_level_domain_plus_2, "/", now, base::Time(), - base::Time(), false, true, CookieSameSite::LAX_MODE, + base::Time(), base::Time(), false, true, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); // same-site cookie cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "same_site_check", "A", url_top_level_domain_plus_2, "/", now, - base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), base::Time(), false, false, + CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false)); // same-party cookie cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "same_party_check", "A", url_top_level_domain_plus_2, "/", now, - base::Time(), base::Time(), true /* secure */, false, + base::Time(), base::Time(), base::Time(), true /* secure */, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, true /* same_party */)); // Secure cookies cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "sec_dom", "A", ".math.harvard.edu", "/", now, base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, + base::Time(), base::Time(), true, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false)); cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "sec_host", "B", url_top_level_domain_plus_2, "/", now, base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, + base::Time(), base::Time(), true, false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false)); // Domain path cookies cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "dom_path_1", "A", ".math.harvard.edu", "/dir1", now, base::Time(), - base::Time(), false, false, CookieSameSite::LAX_MODE, + base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "dom_path_2", "B", ".math.harvard.edu", "/dir1/dir2", now, base::Time(), - base::Time(), false, false, CookieSameSite::LAX_MODE, + base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); // Host path cookies cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "host_path_1", "A", url_top_level_domain_plus_2, "/dir1", now, - base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), base::Time(), false, false, + CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "host_path_2", "B", url_top_level_domain_plus_2, "/dir1/dir2", now, - base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), base::Time(), false, false, + CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false)); // Partitioned cookies cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-pc_1", "A", url_top_level_domain_secure, "/", now, base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, + base::Time(), base::Time(), true, false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, false, CookiePartitionKey::FromURLForTesting(GURL(kTopLevelDomainPlus1)))); cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-pc_2", "B", url_top_level_domain_secure, "/", now, base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, + base::Time(), base::Time(), true, false, CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, false, CookiePartitionKey::FromURLForTesting(GURL(kTopLevelDomainPlus1)))); @@ -942,10 +964,11 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { for (int i = 0; i < num_cookies; i++) { std::unique_ptr<CanonicalCookie> cc( CanonicalCookie::CreateUnsafeCookieForTesting( - "a", "1", base::StringPrintf("h%05d.izzle", i), "/" /* path */, - creation_time, base::Time() /* expiration_time */, - creation_time /* last_access */, true /* secure */, - false /* http_only */, CookieSameSite::NO_RESTRICTION, + "a", "1", base::StringPrintf("h%05d.izzle", i), /*path=*/"/", + creation_time, /*=expiration_time=*/base::Time(), + /*last_access=*/creation_time, /*last_update=*/creation_time, + /*secure=*/true, + /*httponly=*/false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /* same_party */)); GURL source_url = cookie_util::SimulatedCookieSource(*cc, "https"); cm->SetCanonicalCookieAsync(std::move(cc), source_url, @@ -962,6 +985,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { it->CreationDate() == cookie.CreationDate() && it->ExpiryDate() == cookie.ExpiryDate() && it->LastAccessDate() == cookie.LastAccessDate() && + it->LastUpdateDate() == cookie.LastUpdateDate() && it->IsSecure() == cookie.IsSecure() && it->IsHttpOnly() == cookie.IsHttpOnly() && it->Priority() == cookie.Priority()) { @@ -1061,7 +1085,7 @@ class DeferredCookieTaskTest : public CookieMonsterTest { TEST_F(DeferredCookieTaskTest, DeferredGetCookieList) { DeclareLoadedCookie(http_www_foo_.url(), - "X=1; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=1; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(3)); GetCookieListCallback call1; @@ -1124,12 +1148,12 @@ TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) { CookieList list; list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "." + http_www_foo_.domain(), "/", base::Time::Now(), - base::Time(), base::Time(), false, true, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), base::Time(), false, true, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false)); list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "C", "D", "." + http_www_foo_.domain(), "/", base::Time::Now(), - base::Time(), base::Time(), false, true, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), base::Time(), false, true, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false)); ResultSavingCookieCallback<CookieAccessResult> call1; cookie_monster_->SetAllCookiesAsync(list, call1.MakeCallback()); @@ -1151,7 +1175,7 @@ TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) { TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) { DeclareLoadedCookie(http_www_foo_.url(), - "X=1; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=1; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(3)); GetAllCookiesCallback call1; @@ -1173,7 +1197,7 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) { TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) { DeclareLoadedCookie(http_www_foo_.url(), - "X=1; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=1; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(3)); GetCookieListCallback call1; @@ -1199,7 +1223,7 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) { TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) { DeclareLoadedCookie(http_www_foo_.url(), - "X=1; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=1; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(3)); GetCookieListCallback call1; @@ -1225,7 +1249,7 @@ TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) { TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) { DeclareLoadedCookie(http_www_foo_.url(), - "X=1; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=1; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(3)); ResultSavingCookieCallback<uint32_t> call1; @@ -1362,7 +1386,7 @@ TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) { TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) { cookie_monster_->SetPersistSessionCookies(true); DeclareLoadedCookie(http_www_foo_.url(), - "X=1; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=1; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(3)); bool get_cookie_list_callback_was_run = false; @@ -1437,9 +1461,8 @@ TEST_F(CookieMonsterTest, TestCookieDeleteAll) { EXPECT_EQ(0u, store->commands().size()); // Create a persistent cookie. - EXPECT_TRUE(SetCookie( - cm.get(), http_www_foo_.url(), - std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-62 22:50:13 GMT")); + EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), + kValidCookieLine + FutureCookieExpirationString())); ASSERT_EQ(1u, store->commands().size()); EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type); @@ -2154,14 +2177,18 @@ TEST_F(CookieMonsterTest, InheritCreationDate) { CookieList cookies = GetAllCookies(cm.get()); ASSERT_EQ(1u, cookies.size()); EXPECT_EQ(the_not_so_distant_past, cookies[0].CreationDate()); + base::Time last_update = cookies[0].LastUpdateDate(); // Overwrite the cookie with the same value, and verify that the creation date - // is inherited. + // is inherited. The update date isn't inherited though. EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "Name=Value; path=/")); cookies = GetAllCookies(cm.get()); ASSERT_EQ(1u, cookies.size()); EXPECT_EQ(the_not_so_distant_past, cookies[0].CreationDate()); + // If this is flakey you many need to manually set the last update time. + EXPECT_LT(last_update, cookies[0].LastUpdateDate()); + last_update = cookies[0].LastUpdateDate(); // New value => new creation date. EXPECT_TRUE( @@ -2170,6 +2197,8 @@ TEST_F(CookieMonsterTest, InheritCreationDate) { cookies = GetAllCookies(cm.get()); ASSERT_EQ(1u, cookies.size()); EXPECT_NE(the_not_so_distant_past, cookies[0].CreationDate()); + // If this is flakey you many need to manually set the last update time. + EXPECT_LT(last_update, cookies[0].LastUpdateDate()); } // Check that GetAllCookiesForURL() does not return expired cookies and deletes @@ -2239,37 +2268,37 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) { // the import. AddCookieToList(GURL("http://www.foo.com"), - "X=1; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=1; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(3), &initial_cookies); AddCookieToList(GURL("http://www.foo.com"), - "X=2; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=2; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(1), &initial_cookies); // ===> This one is the WINNER (biggest creation time). <==== AddCookieToList(GURL("http://www.foo.com"), - "X=3; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=3; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(4), &initial_cookies); AddCookieToList(GURL("http://www.foo.com"), - "X=4; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", - Time::Now(), &initial_cookies); + "X=4; path=/" + FutureCookieExpirationString(), Time::Now(), + &initial_cookies); // Insert 2 cookies with name "X" on path "/2", with varying creation // dates. We expect only the most recent one to be preserved the import. // ===> This one is the WINNER (biggest creation time). <==== AddCookieToList(GURL("http://www.foo.com"), - "X=a1; path=/2; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=a1; path=/2" + FutureCookieExpirationString(), Time::Now() + base::Days(9), &initial_cookies); AddCookieToList(GURL("http://www.foo.com"), - "X=a2; path=/2; expires=Mon, 18-Apr-62 22:50:14 GMT", + "X=a2; path=/2" + FutureCookieExpirationString(), Time::Now() + base::Days(2), &initial_cookies); // Insert 1 cookie with name "Y" on path "/". AddCookieToList(GURL("http://www.foo.com"), - "Y=a; path=/; expires=Mon, 18-Apr-62 22:50:14 GMT", + "Y=a; path=/" + FutureCookieExpirationString(), Time::Now() + base::Days(10), &initial_cookies); // Inject our initial cookies into the mock PersistentCookieStore. @@ -2529,9 +2558,9 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) { cmout.get(), CanonicalCookie::CreateUnsafeCookieForTesting( cookie.name, cookie.value, cookie.domain, cookie.path, - base::Time(), cookie.expiration_time, base::Time(), cookie.secure, - cookie.http_only, cookie.same_site, cookie.priority, - cookie.same_party), + base::Time(), cookie.expiration_time, base::Time(), base::Time(), + cookie.secure, cookie.http_only, cookie.same_site, + cookie.priority, cookie.same_party), cookie.url, true /*modify_httponly*/)); } @@ -2999,20 +3028,21 @@ TEST_F(CookieMonsterTest, SetAllCookies) { CookieList list; list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", "." + http_www_foo_.url().host(), "/", base::Time::Now(), - base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false)); list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "C", "D", "." + http_www_foo_.url().host(), "/bar", base::Time::Now(), - base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false)); list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "W", "X", "." + http_www_foo_.url().host(), "/", base::Time::Now(), - base::Time(), base::Time(), false, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false)); + base::Time(), base::Time(), base::Time(), false, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false)); list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( "__Host-Y", "Z", https_www_foo_.url().host(), "/", base::Time::Now(), - base::Time(), base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - CookiePriority::COOKIE_PRIORITY_DEFAULT, false, + base::Time(), base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, + false, CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com")))); // SetAllCookies must not flush. @@ -3101,8 +3131,8 @@ TEST_F(CookieMonsterTest, HistogramCheck) { expired_histogram->SnapshotSamples()); auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting( "a", "b", "a.url", "/", base::Time(), - base::Time::Now() + base::Minutes(59), base::Time(), true, false, - CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); + base::Time::Now() + base::Minutes(59), base::Time(), base::Time(), true, + false, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false); GURL source_url = cookie_util::SimulatedCookieSource(*cookie, "https"); ASSERT_TRUE(SetCanonicalCookie(cm.get(), std::move(cookie), source_url, true /*modify_httponly*/)); @@ -3176,7 +3206,7 @@ TEST_F(CookieMonsterTest, PersisentCookieStorageTest) { // Add a cookie. EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), - "A=B; expires=Mon, 18-Apr-62 22:50:13 GMT")); + "A=B" + FutureCookieExpirationString())); this->MatchCookieLines("A=B", GetCookies(cm.get(), http_www_foo_.url())); ASSERT_EQ(1u, store->commands().size()); EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type); @@ -3189,13 +3219,13 @@ TEST_F(CookieMonsterTest, PersisentCookieStorageTest) { // Add a cookie. EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), - "A=B; expires=Mon, 18-Apr-62 22:50:13 GMT")); + "A=B" + FutureCookieExpirationString())); this->MatchCookieLines("A=B", GetCookies(cm.get(), http_www_foo_.url())); ASSERT_EQ(3u, store->commands().size()); EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type); // Overwrite it. EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), - "A=Foo; expires=Mon, 18-Apr-62 22:50:14 GMT")); + "A=Foo" + FutureCookieExpirationString())); this->MatchCookieLines("A=Foo", GetCookies(cm.get(), http_www_foo_.url())); ASSERT_EQ(5u, store->commands().size()); EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type); @@ -3234,9 +3264,10 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { "baz", "\x05" "boo", - "." + domain, path, now2, later, base::Time(), true /* secure */, - false /* httponly */, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false /* sameparty */); + "." + domain, path, now2, later, base::Time(), base::Time(), + true /* secure */, false /* httponly */, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, + false /* sameparty */); initial_cookies.push_back(std::move(cc)); std::unique_ptr<CanonicalCookie> cc2 = @@ -3244,9 +3275,10 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { "baz", "\x7F" "boo", - "." + domain, path, now3, later, base::Time(), true /* secure */, - false /* httponly */, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false /* sameparty */); + "." + domain, path, now3, later, base::Time(), base::Time(), + true /* secure */, false /* httponly */, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, + false /* sameparty */); initial_cookies.push_back(std::move(cc2)); // Partitioned cookies with control characters should not be loaded. @@ -3257,9 +3289,10 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { "__Host-baz", "\x7F" "boo", - domain, "/", now3, later, base::Time(), true /* secure */, - false /* httponly */, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false /* sameparty */, cookie_partition_key); + domain, "/", now3, later, base::Time(), base::Time(), + true /* secure */, false /* httponly */, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, + false /* sameparty */, cookie_partition_key); initial_cookies.push_back(std::move(cc3)); AddCookieToList(url, "hello=world; path=" + path, now4, &initial_cookies); @@ -5474,6 +5507,327 @@ TEST_F(CookieMonsterTest, ConvertPartitionedCookiesToUnpartitioned) { EXPECT_EQ(cookies.size(), 1u); EXPECT_EQ(cookies[0].Name(), "__Host-F"); EXPECT_TRUE(cookies[0].IsPartitioned()); + + // Set three partitioned cookies: + // - The first has a partition key that is same-site with the cookie URL. + // + // - The second cookie has a partition key that is cross-site with the cookie + // URL because it has a different host. + // + // - The third cookie has a partition key that is cross-site with the cookie + // URL because it has a different scheme. + // + // The first cookie should be kept, even though it is not the most recently + // used. This is because we should cookies whose partition key is same-site + // with their URL. + EXPECT_TRUE(CreateAndSetCookie( + cm.get(), https_www_foo_.url(), + "__Host-G=0; Secure; Path=/; SameSite=None; Partitioned", options, + absl::nullopt, absl::nullopt, + CookiePartitionKey::FromURLForTesting(https_www_foo_.url()))); + EXPECT_TRUE(CreateAndSetCookie( + cm.get(), https_www_foo_.url(), + "__Host-G=1; Secure; Path=/; SameSite=None; Partitioned", options, + absl::nullopt, absl::nullopt, + CookiePartitionKey::FromURLForTesting(GURL("https://2.com")))); + EXPECT_TRUE(CreateAndSetCookie( + cm.get(), https_www_foo_.url(), + "__Host-G=2; Secure; Path=/; SameSite=None; Partitioned", options, + absl::nullopt, absl::nullopt, + CookiePartitionKey::FromURLForTesting((http_www_foo_.url())))); + + cm->ConvertPartitionedCookiesToUnpartitioned(https_www_foo_.url()); + + cookies = GetAllCookiesForURL(cm.get(), https_www_foo_.url(), + CookiePartitionKeyCollection::ContainsAll()); + EXPECT_EQ(cookies.size(), 6u); + EXPECT_EQ(cookies[5].Name(), "__Host-G"); + EXPECT_EQ(cookies[5].Value(), "0"); + EXPECT_FALSE(cookies[5].IsPartitioned()); + + // Test that a Domain cookie is converted if one of its subdomains converts + // their cookies. + EXPECT_TRUE(CreateAndSetCookie( + cm.get(), https_www_foo_.url(), + "H=0; Secure; Path=/; SameSite=None; Partitioned; Domain=foo.com", + options, absl::nullopt, absl::nullopt, + CookiePartitionKey::FromURLForTesting(GURL("https://example.com")))); + // Include a hostname bound cookie as well to test interaction. + EXPECT_TRUE(CreateAndSetCookie( + cm.get(), https_www_foo_.url(), + "H=1; Secure; Path=/; SameSite=None; Partitioned", options, absl::nullopt, + absl::nullopt, + CookiePartitionKey::FromURLForTesting(GURL("https://example.com")))); + + cm->ConvertPartitionedCookiesToUnpartitioned(https_www_foo_.url()); + + cookies = GetAllCookiesForURL(cm.get(), https_www_foo_.url(), + CookiePartitionKeyCollection::ContainsAll()); + EXPECT_EQ(cookies.size(), 8u); + EXPECT_EQ(cookies[6].Name(), "H"); + EXPECT_EQ(cookies[6].Value(), "0"); + EXPECT_FALSE(cookies[6].IsPartitioned()); + EXPECT_EQ(cookies[7].Name(), "H"); + EXPECT_EQ(cookies[7].Value(), "1"); + EXPECT_FALSE(cookies[7].IsPartitioned()); +} + +// Tests which use this class verify the expiry date clamping behavior when +// kClampCookieExpiryTo400Days is enabled. This caps expiry dates on new/updated +// cookies to max of 400 days, but does not affect previously stored cookies. +class CookieMonsterWithClampingTest : public CookieMonsterTest, + public testing::WithParamInterface<bool> { + public: + CookieMonsterWithClampingTest() { + scoped_feature_list_.InitWithFeatureState( + features::kClampCookieExpiryTo400Days, + IsClampCookieExpiryTo400DaysEnabled()); + } + bool IsClampCookieExpiryTo400DaysEnabled() { return GetParam(); } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +INSTANTIATE_TEST_SUITE_P(/* no label */, + CookieMonsterWithClampingTest, + testing::Bool()); + +// This test sets a cookie (only checked using IsCanonicalForFromStorage) +// that's 300 days old and expires in 800 days. It checks that this cookie was +// stored, and then update it. It checks that the updated cookie has the +// creation and expiry dates expected given whether or not clamping is on. +TEST_P(CookieMonsterWithClampingTest, + FromStorageCookieCreated300DaysAgoThenUpdatedNow) { + scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto cookie_monster = std::make_unique<CookieMonster>( + store.get(), net::NetLog::Get(), kFirstPartySetsDefault); + cookie_monster->SetPersistSessionCookies(true); + EXPECT_TRUE(GetAllCookies(cookie_monster.get()).empty()); + + // Bypass IsCanonical and store a 300 day old cookie to bypass clamping. + base::Time original_creation = base::Time::Now() - base::Days(300); + base::Time original_expiry = original_creation + base::Days(800); + CookieList list; + list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( + "A", "B", "." + https_www_foo_.url().host(), "/", original_creation, + original_expiry, base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true)); + EXPECT_TRUE(SetAllCookies(cookie_monster.get(), list)); + + // Verify the cookie exists and was not clamped, even if clamping is on. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, original_expiry))); + + // Update the cookie without bypassing clamping. + base::Time new_creation = base::Time::Now(); + base::Time new_expiry = new_creation + base::Days(800); + EXPECT_TRUE(SetCanonicalCookie( + cookie_monster.get(), + CanonicalCookie::CreateSanitizedCookie( + https_www_foo_.url(), "A", "B", https_www_foo_.url().host(), "/", + new_creation, new_expiry, base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true, + absl::nullopt), + https_www_foo_.url(), false)); + + if (IsClampCookieExpiryTo400DaysEnabled()) { + // The clamped update should retain the original creation date, but have + // a clamped expiry date. + EXPECT_THAT( + GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, new_creation + base::Days(400)))); + } else { + // The unclamped update should retain the original creation date and have + // an unclamped expiry date. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, new_expiry))); + } +} + +// This test sets a cookie (only checked using IsCanonicalForFromStorage) +// that's 500 days old and expires in 800 days. It checks that this cookie was +// stored, and then update it. It checks that the updated cookie has the +// creation and expiry dates expected given whether or not clamping is on. +TEST_P(CookieMonsterWithClampingTest, + FromStorageCookieCreated500DaysAgoThenUpdatedNow) { + scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto cookie_monster = std::make_unique<CookieMonster>( + store.get(), net::NetLog::Get(), kFirstPartySetsDefault); + cookie_monster->SetPersistSessionCookies(true); + EXPECT_TRUE(GetAllCookies(cookie_monster.get()).empty()); + + // Bypass IsCanonical and store a 500 day old cookie to bypass clamping. + base::Time original_creation = base::Time::Now() - base::Days(500); + base::Time original_expiry = original_creation + base::Days(800); + CookieList list; + list.push_back(*CanonicalCookie::CreateUnsafeCookieForTesting( + "A", "B", "." + https_www_foo_.url().host(), "/", original_creation, + original_expiry, base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true)); + EXPECT_TRUE(SetAllCookies(cookie_monster.get(), list)); + + // Verify the cookie exists and was not clamped, even if clamping is on. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, original_expiry))); + + // Update the cookie without bypassing clamping. + base::Time new_creation = base::Time::Now(); + base::Time new_expiry = new_creation + base::Days(800); + EXPECT_TRUE(SetCanonicalCookie( + cookie_monster.get(), + CanonicalCookie::CreateSanitizedCookie( + https_www_foo_.url(), "A", "B", https_www_foo_.url().host(), "/", + new_creation, new_expiry, base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true, + absl::nullopt), + https_www_foo_.url(), false)); + + if (IsClampCookieExpiryTo400DaysEnabled()) { + // The clamped update should retain the original creation date, but have + // a clamped expiry date. + EXPECT_THAT( + GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, new_creation + base::Days(400)))); + } else { + // The unclamped update should retain the original creation date and have + // an unclamped expiry date. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, new_expiry))); + } +} + +// This test sets a cookie (checked using IsCanonical) that's 300 days old and +// expires in 800 days. It checks that this cookie was stored, and then update +// it. It checks that the updated cookie has the creation and expiry dates +// expected given whether or not clamping is on. +TEST_P(CookieMonsterWithClampingTest, + SanitizedCookieCreated300DaysAgoThenUpdatedNow) { + scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto cookie_monster = std::make_unique<CookieMonster>( + store.get(), net::NetLog::Get(), kFirstPartySetsDefault); + cookie_monster->SetPersistSessionCookies(true); + EXPECT_TRUE(GetAllCookies(cookie_monster.get()).empty()); + + // Store a 300 day old cookie without bypassing clamping. + base::Time original_creation = base::Time::Now() - base::Days(300); + base::Time original_expiry = original_creation + base::Days(800); + EXPECT_TRUE(SetCanonicalCookie( + cookie_monster.get(), + CanonicalCookie::CreateSanitizedCookie( + https_www_foo_.url(), "A", "B", https_www_foo_.url().host(), "/", + original_creation, original_expiry, base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true, + absl::nullopt), + https_www_foo_.url(), false)); + + if (IsClampCookieExpiryTo400DaysEnabled()) { + // The clamped set should have a clamped expiry date. + EXPECT_THAT( + GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, original_creation + base::Days(400)))); + } else { + // The unclamped set should have an unclamped expiry date. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, original_expiry))); + } + + // Update the cookie without bypassing clamping. + base::Time new_creation = base::Time::Now(); + base::Time new_expiry = new_creation + base::Days(800); + EXPECT_TRUE(SetCanonicalCookie( + cookie_monster.get(), + CanonicalCookie::CreateSanitizedCookie( + https_www_foo_.url(), "A", "B", https_www_foo_.url().host(), "/", + new_creation, new_expiry, base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true, + absl::nullopt), + https_www_foo_.url(), false)); + + if (IsClampCookieExpiryTo400DaysEnabled()) { + // The clamped update should retain the original creation date, but have + // a clamped expiry date. + EXPECT_THAT( + GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, new_creation + base::Days(400)))); + } else { + // The unclamped update should retain the original creation date and have + // an unclamped expiry date. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, new_expiry))); + } +} + +// This test sets a cookie (checked using IsCanonical) that's 500 days old and +// expires in 800 days. It checks that this cookie was stored, and then update +// it. It checks that the updated cookie has the creation and expiry dates +// expected given whether or not clamping is on. +TEST_P(CookieMonsterWithClampingTest, + SanitizedCookieCreated500DaysAgoThenUpdatedNow) { + scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto cookie_monster = std::make_unique<CookieMonster>( + store.get(), net::NetLog::Get(), kFirstPartySetsDefault); + cookie_monster->SetPersistSessionCookies(true); + EXPECT_TRUE(GetAllCookies(cookie_monster.get()).empty()); + + // Store a 500 day old cookie without bypassing clamping. + base::Time original_creation = base::Time::Now() - base::Days(500); + base::Time original_expiry = original_creation + base::Days(800); + EXPECT_TRUE(SetCanonicalCookie( + cookie_monster.get(), + CanonicalCookie::CreateSanitizedCookie( + https_www_foo_.url(), "A", "B", https_www_foo_.url().host(), "/", + original_creation, original_expiry, base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true, + absl::nullopt), + https_www_foo_.url(), false)); + + if (IsClampCookieExpiryTo400DaysEnabled()) { + // The clamped set should result in no stored cookie. + EXPECT_TRUE(GetAllCookies(cookie_monster.get()).empty()); + } else { + // The unclamped set should have an unclamped expiry date. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, original_expiry))); + } + + // Update the cookie without bypassing clamping. + base::Time new_creation = base::Time::Now(); + base::Time new_expiry = new_creation + base::Days(800); + EXPECT_TRUE(SetCanonicalCookie( + cookie_monster.get(), + CanonicalCookie::CreateSanitizedCookie( + https_www_foo_.url(), "A", "B", https_www_foo_.url().host(), "/", + new_creation, new_expiry, base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, true, + absl::nullopt), + https_www_foo_.url(), false)); + + // The clamped one has the new creation date as the old cookie was expired. + if (IsClampCookieExpiryTo400DaysEnabled()) { + // The clamped update was really a set as the old cookie expired, so it has + // the new creation date and a clamped expiry date. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", new_creation, new_creation + base::Days(400)))); + } else { + // The unclamped update should retain the original creation date and have + // an unclamped expiry date. + EXPECT_THAT(GetAllCookies(cookie_monster.get()), + ElementsAre(MatchesCookieNameValueCreationExpiry( + "A", "B", original_creation, new_expiry))); + } } } // namespace net diff --git a/chromium/net/cookies/cookie_partition_key.h b/chromium/net/cookies/cookie_partition_key.h index 60ff48bc342..4b920323ae2 100644 --- a/chromium/net/cookies/cookie_partition_key.h +++ b/chromium/net/cookies/cookie_partition_key.h @@ -92,10 +92,6 @@ class NET_EXPORT CookiePartitionKey { return absl::make_optional(CookiePartitionKey(true)); } - // Temporary method, used to mark the places where we need to supply the - // cookie partition key to CanonicalCookie::Create. - static absl::optional<CookiePartitionKey> Todo() { return absl::nullopt; } - const SchemefulSite& site() const { return site_; } bool from_script() const { return from_script_; } diff --git a/chromium/net/cookies/cookie_store_test_callbacks.cc b/chromium/net/cookies/cookie_store_test_callbacks.cc index af88e4da3ec..1a8465a2980 100644 --- a/chromium/net/cookies/cookie_store_test_callbacks.cc +++ b/chromium/net/cookies/cookie_store_test_callbacks.cc @@ -14,12 +14,11 @@ namespace net { CookieCallback::CookieCallback(base::Thread* run_in_thread) - : run_in_thread_(run_in_thread), was_run_(false) {} + : run_in_thread_(run_in_thread) {} CookieCallback::CookieCallback() : run_in_thread_(nullptr), - run_in_task_runner_(base::ThreadTaskRunnerHandle::Get()), - was_run_(false) {} + run_in_task_runner_(base::ThreadTaskRunnerHandle::Get()) {} CookieCallback::~CookieCallback() = default; diff --git a/chromium/net/cookies/cookie_store_test_callbacks.h b/chromium/net/cookies/cookie_store_test_callbacks.h index e1dcf6b198d..ee319423e68 100644 --- a/chromium/net/cookies/cookie_store_test_callbacks.h +++ b/chromium/net/cookies/cookie_store_test_callbacks.h @@ -54,7 +54,7 @@ class CookieCallback { raw_ptr<base::Thread> run_in_thread_; scoped_refptr<base::SingleThreadTaskRunner> run_in_task_runner_; base::RunLoop loop_to_quit_; - bool was_run_; + bool was_run_ = false; }; // Callback implementations for the asynchronous CookieStore methods. diff --git a/chromium/net/cookies/cookie_store_test_helpers.cc b/chromium/net/cookies/cookie_store_test_helpers.cc index b9d345ac9b8..31c95384063 100644 --- a/chromium/net/cookies/cookie_store_test_helpers.cc +++ b/chromium/net/cookies/cookie_store_test_helpers.cc @@ -4,6 +4,7 @@ #include "net/cookies/cookie_store_test_helpers.h" +#include <string> #include <utility> #include "base/bind.h" @@ -11,6 +12,7 @@ #include "base/strings/string_util.h" #include "base/task/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" @@ -73,7 +75,6 @@ DelayedCookieMonster::DelayedCookieMonster() : cookie_monster_(new CookieMonster(nullptr /* store */, nullptr /* netlog */, false /* first_party_sets_enabled */)), - did_run_(false), result_(CookieAccessResult(CookieInclusionStatus( CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE))) {} @@ -214,7 +215,7 @@ std::string CookieURLHelper::Format(const std::string& format_string) const { // // FlushablePersistentStore // -FlushablePersistentStore::FlushablePersistentStore() : flush_count_(0) {} +FlushablePersistentStore::FlushablePersistentStore() = default; void FlushablePersistentStore::Load(LoadedCallback loaded_callback, const NetLogWithSource& /* net_log */) { @@ -257,7 +258,7 @@ FlushablePersistentStore::~FlushablePersistentStore() = default; // // CallbackCounter // -CallbackCounter::CallbackCounter() : callback_count_(0) {} +CallbackCounter::CallbackCounter() = default; void CallbackCounter::Callback() { base::AutoLock lock(callback_count_lock_); @@ -271,4 +272,9 @@ int CallbackCounter::callback_count() { CallbackCounter::~CallbackCounter() = default; +std::string FutureCookieExpirationString() { + return "; expires=" + + base::TimeFormatHTTP(base::Time::Now() + base::Days(365)); +} + } // namespace net diff --git a/chromium/net/cookies/cookie_store_test_helpers.h b/chromium/net/cookies/cookie_store_test_helpers.h index f549b7c7a8a..03ecacf626c 100644 --- a/chromium/net/cookies/cookie_store_test_helpers.h +++ b/chromium/net/cookies/cookie_store_test_helpers.h @@ -119,7 +119,7 @@ class DelayedCookieMonster : public CookieStore { std::unique_ptr<CookieMonster> cookie_monster_; DelayedCookieMonsterChangeDispatcher change_dispatcher_; - bool did_run_; + bool did_run_ = false; CookieAccessResult result_; std::string cookie_; std::string cookie_line_; @@ -169,7 +169,7 @@ class FlushablePersistentStore : public CookieMonster::PersistentCookieStore { private: ~FlushablePersistentStore() override; - int flush_count_; + int flush_count_ = 0; base::Lock flush_count_lock_; // Protects |flush_count_|. }; @@ -184,10 +184,15 @@ class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> { friend class base::RefCountedThreadSafe<CallbackCounter>; ~CallbackCounter(); - int callback_count_; + int callback_count_ = 0; base::Lock callback_count_lock_; // Protects |callback_count_|. }; +// Returns a cookie expiration string in the form of "; expires=<date>", where +// date is an RFC 7231 date a year in the future, which can be appended to +// cookie lines. +std::string FutureCookieExpirationString(); + } // namespace net #endif // NET_COOKIES_COOKIE_STORE_TEST_HELPERS_H_ diff --git a/chromium/net/cookies/cookie_store_unittest.h b/chromium/net/cookies/cookie_store_unittest.h index b1738b69be3..f131f4f10cd 100644 --- a/chromium/net/cookies/cookie_store_unittest.h +++ b/chromium/net/cookies/cookie_store_unittest.h @@ -605,28 +605,28 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { cs, CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", foo_foo_host, "/foo", one_hour_ago, one_hour_from_now, - base::Time(), false /* secure */, false /* httponly */, + base::Time(), base::Time(), false /* secure */, false /* httponly */, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false), this->www_foo_foo_.url(), true)); EXPECT_TRUE(this->SetCanonicalCookie( cs, CanonicalCookie::CreateUnsafeCookieForTesting( "C", "D", "." + foo_bar_domain, "/bar", two_hours_ago, base::Time(), - one_hour_ago, false, true, CookieSameSite::LAX_MODE, + one_hour_ago, one_hour_ago, false, true, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false), this->www_foo_bar_.url(), true)); // A secure source is required for setting secure cookies. - EXPECT_TRUE( - this->SetCanonicalCookieReturnAccessResult( - cs, - CanonicalCookie::CreateUnsafeCookieForTesting( - "E", "F", http_foo_host, "/", base::Time(), base::Time(), - base::Time(), true, false, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false), - this->http_www_foo_.url(), true) - .status.HasExclusionReason( - CookieInclusionStatus::EXCLUDE_SECURE_ONLY)); + EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult( + cs, + CanonicalCookie::CreateUnsafeCookieForTesting( + "E", "F", http_foo_host, "/", base::Time(), + base::Time(), base::Time(), base::Time(), true, false, + CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_DEFAULT, false), + this->http_www_foo_.url(), true) + .status.HasExclusionReason( + CookieInclusionStatus::EXCLUDE_SECURE_ONLY)); // A Secure cookie can be created from an insecure URL, but is rejected upon // setting. @@ -648,21 +648,22 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { cs, CanonicalCookie::CreateUnsafeCookieForTesting( "E", "F", https_foo_host, "/", base::Time(), base::Time(), - base::Time(), true /* secure */, false /* httponly */, + base::Time(), base::Time(), true /* secure */, false /* httponly */, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false /* same_party */), this->https_www_foo_.url(), true /* modify_http_only */)); - EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult( - cs, - CanonicalCookie::CreateUnsafeCookieForTesting( - "E", "F", http_foo_host, "/", base::Time(), - base::Time(), base::Time(), true /* secure */, - false /* httponly */, CookieSameSite::NO_RESTRICTION, - COOKIE_PRIORITY_DEFAULT, false /* same_party */), - this->http_www_foo_.url(), true /* modify_http_only */) - .status.HasExclusionReason( - CookieInclusionStatus::EXCLUDE_SECURE_ONLY)); + EXPECT_TRUE( + this->SetCanonicalCookieReturnAccessResult( + cs, + CanonicalCookie::CreateUnsafeCookieForTesting( + "E", "F", http_foo_host, "/", base::Time(), base::Time(), + base::Time(), base::Time(), true /* secure */, + false /* httponly */, CookieSameSite::NO_RESTRICTION, + COOKIE_PRIORITY_DEFAULT, false /* same_party */), + this->http_www_foo_.url(), true /* modify_http_only */) + .status.HasExclusionReason( + CookieInclusionStatus::EXCLUDE_SECURE_ONLY)); if (TypeParam::supports_http_only) { // Permission to modify http only cookies is required to set an @@ -671,9 +672,10 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { cs, CanonicalCookie::CreateUnsafeCookieForTesting( "G", "H", http_foo_host, "/unique", base::Time(), - base::Time(), base::Time(), false /* secure */, - true /* httponly */, CookieSameSite::LAX_MODE, - COOKIE_PRIORITY_DEFAULT, false /* same_party */), + base::Time(), base::Time(), base::Time(), + false /* secure */, true /* httponly */, + CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, + false /* same_party */), this->http_www_foo_.url(), false /* modify_http_only */) .status.HasExclusionReason( CookieInclusionStatus::EXCLUDE_HTTP_ONLY)); @@ -699,7 +701,7 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { cs, CanonicalCookie::CreateUnsafeCookieForTesting( "G", "H", http_foo_host, "/unique", base::Time(), base::Time(), - base::Time(), false /* secure */, true /* httponly */, + base::Time(), base::Time(), false /* secure */, true /* httponly */, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false /* same_party */), this->http_www_foo_.url(), true /* modify_http_only */)); @@ -708,9 +710,10 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { cs, CanonicalCookie::CreateUnsafeCookieForTesting( "G", "H", http_foo_host, "/unique", base::Time(), - base::Time(), base::Time(), false /* secure */, - true /* httponly */, CookieSameSite::LAX_MODE, - COOKIE_PRIORITY_DEFAULT, false /* same_party */), + base::Time(), base::Time(), base::Time(), + false /* secure */, true /* httponly */, + CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, + false /* same_party */), this->http_www_foo_.url(), false /* modify_http_only */) .status.HasExclusionReason( CookieInclusionStatus::EXCLUDE_HTTP_ONLY)); @@ -720,7 +723,7 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { cs, CanonicalCookie::CreateUnsafeCookieForTesting( "G", "H", http_foo_host, "/unique", base::Time(), base::Time(), - base::Time(), false /* secure */, true /* httponly */, + base::Time(), base::Time(), false /* secure */, true /* httponly */, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false /* same_party */), this->http_www_foo_.url(), true /* modify_http_only */)); @@ -799,28 +802,28 @@ TYPED_TEST_P(CookieStoreTest, SecureEnforcement) { cs, CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", http_domain, "/", base::Time::Now(), base::Time(), - base::Time(), true, false, CookieSameSite::STRICT_MODE, + base::Time(), base::Time(), true, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false /* same_party */), http_url, true /*modify_httponly*/)); EXPECT_TRUE(this->SetCanonicalCookie( cs, CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", http_domain, "/", base::Time::Now(), base::Time(), - base::Time(), true, false, CookieSameSite::STRICT_MODE, + base::Time(), base::Time(), true, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false /* same_party */), https_url, true /*modify_httponly*/)); EXPECT_TRUE(this->SetCanonicalCookie( cs, CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", http_domain, "/", base::Time::Now(), base::Time(), - base::Time(), false, false, CookieSameSite::STRICT_MODE, + base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false /* same_party */), https_url, true /*modify_httponly*/)); EXPECT_TRUE(this->SetCanonicalCookie( cs, CanonicalCookie::CreateUnsafeCookieForTesting( "A", "B", http_domain, "/", base::Time::Now(), base::Time(), - base::Time(), false, false, CookieSameSite::STRICT_MODE, + base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false /* same_party */), http_url, true /*modify_httponly*/)); } @@ -1391,9 +1394,9 @@ TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) { this->GetCookies(cs, this->http_www_foo_.url())); // Create a persistent cookie. - EXPECT_TRUE(this->SetCookie( - cs, this->http_www_foo_.url(), - std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-62 22:50:13 GMT")); + EXPECT_TRUE( + this->SetCookie(cs, this->http_www_foo_.url(), + kValidCookieLine + FutureCookieExpirationString())); this->MatchCookieLines("A=B", this->GetCookies(cs, this->http_www_foo_.url())); @@ -1404,9 +1407,9 @@ TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) { std::string()); // Create a persistent cookie. - EXPECT_TRUE(this->SetCookie( - cs, this->http_www_foo_.url(), - std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-62 22:50:13 GMT")); + EXPECT_TRUE( + this->SetCookie(cs, this->http_www_foo_.url(), + kValidCookieLine + FutureCookieExpirationString())); this->MatchCookieLines("A=B", this->GetCookies(cs, this->http_www_foo_.url())); // Delete it via Expires. @@ -1417,9 +1420,9 @@ TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) { this->GetCookies(cs, this->http_www_foo_.url())); // Create a persistent cookie. - EXPECT_TRUE(this->SetCookie( - cs, this->http_www_foo_.url(), - std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-62 22:50:13 GMT")); + EXPECT_TRUE( + this->SetCookie(cs, this->http_www_foo_.url(), + kValidCookieLine + FutureCookieExpirationString())); this->MatchCookieLines("A=B", this->GetCookies(cs, this->http_www_foo_.url())); // Check that it is not deleted with significant enough clock skew. @@ -1434,9 +1437,9 @@ TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) { this->GetCookies(cs, this->http_www_foo_.url())); // Create a persistent cookie. - EXPECT_TRUE(this->SetCookie( - cs, this->http_www_foo_.url(), - std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-62 22:50:13 GMT")); + EXPECT_TRUE( + this->SetCookie(cs, this->http_www_foo_.url(), + kValidCookieLine + FutureCookieExpirationString())); this->MatchCookieLines("A=B", this->GetCookies(cs, this->http_www_foo_.url())); // Delete it via Expires, with a unix epoch of 0. @@ -1456,7 +1459,7 @@ TYPED_TEST_P(CookieStoreTest, TestDeleteAll) { // Set a persistent cookie. EXPECT_TRUE(this->SetCookie(cs, this->http_www_foo_.url(), - "C=D; expires=Mon, 18-Apr-62 22:50:13 GMT")); + "C=D" + FutureCookieExpirationString())); EXPECT_EQ(2u, this->GetAllCookies(cs).size()); @@ -1600,14 +1603,12 @@ TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) { CookieStore* cs = this->GetCookieStore(); // Insert a cookie "a" for path "/path1" - EXPECT_TRUE(this->SetCookie(cs, url_foo, - "a=val1; path=/path1; " - "expires=Mon, 18-Apr-62 22:50:13 GMT")); + EXPECT_TRUE(this->SetCookie( + cs, url_foo, "a=val1; path=/path1" + FutureCookieExpirationString())); // Insert a cookie "b" for path "/path1" - EXPECT_TRUE(this->SetCookie(cs, url_foo, - "b=val1; path=/path1; " - "expires=Mon, 18-Apr-62 22:50:14 GMT")); + EXPECT_TRUE(this->SetCookie( + cs, url_foo, "b=val1; path=/path1" + FutureCookieExpirationString())); // Insert a cookie "b" for path "/path1", that is httponly. This should // overwrite the non-http-only version. @@ -1615,28 +1616,26 @@ TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) { allow_httponly.set_include_httponly(); allow_httponly.set_same_site_cookie_context( net::CookieOptions::SameSiteCookieContext::MakeInclusive()); - EXPECT_TRUE(this->CreateAndSetCookie(cs, url_foo, - "b=val2; path=/path1; httponly; " - "expires=Mon, 18-Apr-62 22:50:14 GMT", - allow_httponly)); + EXPECT_TRUE(this->CreateAndSetCookie( + cs, url_foo, + "b=val2; path=/path1; httponly" + FutureCookieExpirationString(), + allow_httponly)); // Insert a cookie "a" for path "/path1". This should overwrite. - EXPECT_TRUE(this->SetCookie(cs, url_foo, - "a=val33; path=/path1; " - "expires=Mon, 18-Apr-62 22:50:14 GMT")); + EXPECT_TRUE(this->SetCookie( + cs, url_foo, "a=val33; path=/path1" + FutureCookieExpirationString())); // Insert a cookie "a" for path "/path2". This should NOT overwrite // cookie "a", since the path is different. - EXPECT_TRUE(this->SetCookie(cs, url_foo, - "a=val9; path=/path2; " - "expires=Mon, 18-Apr-62 22:50:14 GMT")); + EXPECT_TRUE(this->SetCookie( + cs, url_foo, "a=val9; path=/path2" + FutureCookieExpirationString())); // 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, url_chromium, - "a=val99; path=/path1; " - "expires=Mon, 18-Apr-62 22:50:14 GMT")); + EXPECT_TRUE( + this->SetCookie(cs, url_chromium, + "a=val99; path=/path1" + FutureCookieExpirationString())); if (TypeParam::supports_http_only) { this->MatchCookieLines( @@ -1870,8 +1869,8 @@ TYPED_TEST_P(CookieStoreTest, DeleteSessionCookie) { std::string(kValidCookieLine))); EXPECT_TRUE(this->SetCookie( cs, this->http_www_foo_.url(), - this->http_www_foo_.Format("C=D; path=/; domain=%D;" - "expires=Mon, 18-Apr-62 22:50:13 GMT"))); + this->http_www_foo_.Format("C=D; path=/; domain=%D" + + FutureCookieExpirationString()))); this->MatchCookieLines("A=B; C=D", this->GetCookies(cs, this->http_www_foo_.url())); // Delete the session cookie. diff --git a/chromium/net/cookies/cookie_util.cc b/chromium/net/cookies/cookie_util.cc index d90f82eaa38..d91b562fc0f 100644 --- a/chromium/net/cookies/cookie_util.cc +++ b/chromium/net/cookies/cookie_util.cc @@ -307,6 +307,12 @@ std::string GetEffectiveDomain(const std::string& scheme, bool GetCookieDomainWithString(const GURL& url, const std::string& domain_string, std::string* result) { + // Disallow non-ASCII domain names. + if (base::FeatureList::IsEnabled(features::kCookieDomainRejectNonASCII) && + !base::IsStringASCII(domain_string)) { + return false; + } + const std::string url_host(url.host()); // If no domain was specified in the domain string, default to a host cookie. // We match IE/Firefox in allowing a domain=IPADDR if it matches (case diff --git a/chromium/net/cookies/cookie_util_unittest.cc b/chromium/net/cookies/cookie_util_unittest.cc index 6020776afea..6ab824e2666 100644 --- a/chromium/net/cookies/cookie_util_unittest.cc +++ b/chromium/net/cookies/cookie_util_unittest.cc @@ -1538,7 +1538,7 @@ TEST(CookieUtilTest, GetSamePartyStatus_NotInSet) { base::Time now = base::Time::Now(); std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateUnsafeCookieForTesting( - "cookie", "tasty", "example.test", "/", now, now, now, + "cookie", "tasty", "example.test", "/", now, now, now, now, secure, httponly, same_site, CookiePriority::COOKIE_PRIORITY_DEFAULT, same_party); @@ -1575,7 +1575,7 @@ TEST(CookieUtilTest, GetSamePartyStatus_FeatureDisabled) { base::Time now = base::Time::Now(); std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateUnsafeCookieForTesting( - "cookie", "tasty", "example.test", "/", now, now, now, + "cookie", "tasty", "example.test", "/", now, now, now, now, secure, httponly, same_site, CookiePriority::COOKIE_PRIORITY_DEFAULT, same_party); @@ -1611,8 +1611,9 @@ TEST(CookieUtilTest, GetSamePartyStatus_NotSameParty) { base::Time now = base::Time::Now(); std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateUnsafeCookieForTesting( - "cookie", "tasty", "example.test", "/", now, now, now, secure, - httponly, same_site, CookiePriority::COOKIE_PRIORITY_DEFAULT, + "cookie", "tasty", "example.test", "/", now, now, now, now, + secure, httponly, same_site, + CookiePriority::COOKIE_PRIORITY_DEFAULT, false /* same_party */); options.set_same_party_context(SamePartyContext(party_context_type)); @@ -1667,7 +1668,7 @@ TEST(CookieUtilTest, GetSamePartyStatus_SamePartySemantics) { base::Time now = base::Time::Now(); std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::CreateUnsafeCookieForTesting( - "cookie", "tasty", "example.test", "/", now, now, now, + "cookie", "tasty", "example.test", "/", now, now, now, now, true /* secure */, httponly, same_site, CookiePriority::COOKIE_PRIORITY_DEFAULT, true /* same_party */); diff --git a/chromium/net/cookies/parsed_cookie.cc b/chromium/net/cookies/parsed_cookie.cc index d64b8690bf3..17e64f13c9b 100644 --- a/chromium/net/cookies/parsed_cookie.cc +++ b/chromium/net/cookies/parsed_cookie.cc @@ -46,6 +46,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/numerics/checked_math.h" #include "base/strings/string_util.h" #include "net/base/features.h" #include "net/cookies/cookie_constants.h" @@ -307,8 +308,6 @@ bool ParsedCookie::SetPath(const std::string& path) { } bool ParsedCookie::SetDomain(const std::string& domain) { - UMA_HISTOGRAM_BOOLEAN("Cookie.EmptyDomain.SetDomain", - domain == std::string()); return SetString(&domain_index_, kDomainTokenName, domain); } @@ -762,24 +761,11 @@ void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line, } void ParsedCookie::SetupAttributes() { - // For the UMA_HISTOGRAMS below. - int domain_count = - std::count_if(pairs_.begin(), pairs_.end(), - [](const std::pair<std::string, std::string>& pair) { - return pair.first == kDomainTokenName; - }); // We skip over the first token/value, the user supplied one. for (size_t i = 1; i < pairs_.size(); ++i) { if (pairs_[i].first == kPathTokenName) { path_index_ = i; } else if (pairs_[i].first == kDomainTokenName) { - // Record usage metrics for the empty string domain. - UMA_HISTOGRAM_BOOLEAN( - "Cookie.EmptyDomain.SetupAttributes.Single", - (domain_count == 1) && (pairs_[i].second == std::string())); - UMA_HISTOGRAM_BOOLEAN( - "Cookie.EmptyDomain.SetupAttributes.Multiple", - (domain_count > 1) && (pairs_[i].second == std::string())); // Domain can be the empty string if the flag is enabled. if (base::FeatureList::IsEnabled( features::kCookieDomainAttributeEmptyString) || diff --git a/chromium/net/cookies/same_party_context.cc b/chromium/net/cookies/same_party_context.cc index d531652e356..93a14af7f47 100644 --- a/chromium/net/cookies/same_party_context.cc +++ b/chromium/net/cookies/same_party_context.cc @@ -4,6 +4,7 @@ #include "net/cookies/same_party_context.h" +#include <sstream> #include <tuple> #include "net/cookies/cookie_constants.h" |