diff options
Diffstat (limited to 'chromium/net/cookies')
33 files changed, 875 insertions, 777 deletions
diff --git a/chromium/net/cookies/canonical_cookie.cc b/chromium/net/cookies/canonical_cookie.cc index f31ac89afbe..06fbffaee10 100644 --- a/chromium/net/cookies/canonical_cookie.cc +++ b/chromium/net/cookies/canonical_cookie.cc @@ -76,17 +76,20 @@ using base::Time; namespace net { static constexpr int kMinutesInTwelveHours = 12 * 60; +static constexpr int kMinutesInTwentyFourHours = 24 * 60; namespace { // Determine the cookie domain to use for setting the specified cookie. bool GetCookieDomain(const GURL& url, const ParsedCookie& pc, + CookieInclusionStatus& status, std::string* result) { std::string domain_string; if (pc.HasDomain()) domain_string = pc.Domain(); - return cookie_util::GetCookieDomainWithString(url, domain_string, result); + return cookie_util::GetCookieDomainWithString(url, domain_string, status, + result); } // Compares cookies using name, domain and path, so that "equivalent" cookies @@ -304,32 +307,6 @@ void ApplySameSiteCookieWarningToStatus( status->MaybeClearSameSiteWarning(); } -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. -enum class SameSiteNonePartyContextType { - // SameSite=None was required in order for the cookie to be included. - kSameSiteNoneRequired = 0, - // The cookie would have been included if it were SameParty (using only the - // top frame and resource URL). - kSamePartyTopResource = 1, - // The cookie would have been included if it were SameParty (using the - // resource URL and all frame ancestors). - kSamePartyAncestors = 2, - // The cookie would have been included if it were SameSite=Lax. - kSameSiteLax = 3, - // The cookie would have been included if it were SameSite=Strict. - kSameSiteStrict = 4, - kMaxValue = kSameSiteStrict -}; - -void RecordSameSiteNoneReadContextMetric(SameSiteNonePartyContextType type) { - UMA_HISTOGRAM_ENUMERATION("Cookie.SameSiteNone.PartyContext.Read", type); -} - -void RecordSameSiteNoneWriteContextMetric(SameSiteNonePartyContextType type) { - UMA_HISTOGRAM_ENUMERATION("Cookie.SameSiteNone.PartyContext.Write", type); -} - // Converts CookieSameSite to CookieSameSiteForMetrics by adding 1 to it. CookieSameSiteForMetrics CookieSameSiteToCookieSameSiteForMetrics( CookieSameSite enum_in) { @@ -359,17 +336,6 @@ bool HasValidHostPrefixAttributes(const GURL& url, return domain.empty() || (url.HostIsIPAddress() && url.host() == domain); } -// 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 CookieAccessParams::CookieAccessParams(CookieAccessSemantics access_semantics, @@ -492,18 +458,32 @@ Time CanonicalCookie::ParseExpiration(const ParsedCookie& pc, 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(); + // Determine the new expiry with clock skew factored in. + Time adjusted_expiry = parsed_expiry + (current - server_time); if (clock_skew.is_positive() || clock_skew.is_zero()) { UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ClockSkew.AddMinutes", clock_skew_magnitude, 1, kMinutesInTwelveHours, 100); + UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ClockSkew.AddMinutes12To24Hours", + clock_skew_magnitude, kMinutesInTwelveHours, + kMinutesInTwentyFourHours, 100); + // Also record the range of minutes added that allowed the cookie to + // avoid expiring immediately. + if (parsed_expiry <= Time::Now() && adjusted_expiry > Time::Now()) { + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Cookie.ClockSkew.WithoutAddMinutesExpires", clock_skew_magnitude, + 1, kMinutesInTwentyFourHours, 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); + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Cookie.ClockSkew.SubtractMinutes12To24Hours", clock_skew_magnitude, + kMinutesInTwelveHours, kMinutesInTwentyFourHours, 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( @@ -578,7 +558,7 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::Create( !base::IsStringASCII(parsed_cookie.Domain())); std::string cookie_domain; - if (!GetCookieDomain(url, parsed_cookie, &cookie_domain)) { + if (!GetCookieDomain(url, parsed_cookie, *status, &cookie_domain)) { DVLOG(net::cookie_util::kVlogSetCookies) << "Create() failed to get a valid cookie domain"; status->AddExclusionReason(CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN); @@ -761,7 +741,7 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateSanitizedCookie( status->AddExclusionReason( net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN); } else if (!cookie_util::GetCookieDomainWithString(url, domain_attribute, - &cookie_domain)) { + *status, &cookie_domain)) { status->AddExclusionReason( net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN); } @@ -824,9 +804,8 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateSanitizedCookie( status->AddExclusionReason( net::CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY); } - if (!IsCookiePartitionedValid(url, secure, cookie_path, + if (!IsCookiePartitionedValid(url, secure, /*is_partitioned=*/partition_key.has_value(), - /*is_same_party=*/same_party, /*partition_has_nonce=*/ CookiePartitionKey::HasNonce(partition_key))) { status->AddExclusionReason( @@ -1154,47 +1133,6 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL( UMA_HISTOGRAM_ENUMERATION("Cookie.IncludedRequestEffectiveSameSite", effective_same_site, CookieEffectiveSameSite::COUNT); - - if (SameSite() == CookieSameSite::NO_RESTRICTION) { - SamePartyContext::Type top_resource = - options.same_party_context().top_resource_for_metrics_only(); - SamePartyContext::Type ancestors = - options.same_party_context().ancestors_for_metrics_only(); - - if (top_resource == SamePartyContext::Type::kCrossParty) { - status.AddWarningReason( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED); - RecordSameSiteNoneReadContextMetric( - SameSiteNonePartyContextType::kSameSiteNoneRequired); - } else if (ancestors == SamePartyContext::Type::kCrossParty) { - status.AddWarningReason( - CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE); - RecordSameSiteNoneReadContextMetric( - SameSiteNonePartyContextType::kSamePartyTopResource); - } else if (cookie_inclusion_context < - CookieOptions::SameSiteCookieContext::ContextType:: - SAME_SITE_LAX) { - status.AddWarningReason( - CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS); - RecordSameSiteNoneReadContextMetric( - SameSiteNonePartyContextType::kSamePartyAncestors); - } else if (cookie_inclusion_context < - CookieOptions::SameSiteCookieContext::ContextType:: - SAME_SITE_STRICT) { - status.AddWarningReason( - CookieInclusionStatus::WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX); - RecordSameSiteNoneReadContextMetric( - SameSiteNonePartyContextType::kSameSiteLax); - } else { - status.AddWarningReason( - CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT); - RecordSameSiteNoneReadContextMetric( - SameSiteNonePartyContextType::kSameSiteStrict); - } - } } using ContextRedirectTypeBug1221316 = CookieOptions::SameSiteCookieContext:: @@ -1397,42 +1335,6 @@ CookieAccessResult CanonicalCookie::IsSetPermittedInContext( UMA_HISTOGRAM_ENUMERATION("Cookie.IncludedResponseEffectiveSameSite", access_result.effective_same_site, CookieEffectiveSameSite::COUNT); - - if (SameSite() == CookieSameSite::NO_RESTRICTION) { - SamePartyContext::Type top_resource = - options.same_party_context().top_resource_for_metrics_only(); - SamePartyContext::Type ancestors = - options.same_party_context().ancestors_for_metrics_only(); - - if (top_resource == SamePartyContext::Type::kCrossParty) { - access_result.status.AddWarningReason( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED); - RecordSameSiteNoneWriteContextMetric( - SameSiteNonePartyContextType::kSameSiteNoneRequired); - } else if (ancestors == SamePartyContext::Type::kCrossParty) { - access_result.status.AddWarningReason( - CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE); - RecordSameSiteNoneWriteContextMetric( - SameSiteNonePartyContextType::kSamePartyTopResource); - } else if (cookie_inclusion_context < - CookieOptions::SameSiteCookieContext::ContextType:: - SAME_SITE_LAX) { - access_result.status.AddWarningReason( - CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS); - RecordSameSiteNoneWriteContextMetric( - SameSiteNonePartyContextType::kSamePartyAncestors); - } else { - // NB: unlike when sending a cookie, there's no distinction between - // SameSite=Lax and SameSite=Strict when setting a cookie. - access_result.status.AddWarningReason( - CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT); - RecordSameSiteNoneWriteContextMetric( - SameSiteNonePartyContextType::kSameSiteStrict); - } - } } using ContextRedirectTypeBug1221316 = CookieOptions::SameSiteCookieContext:: @@ -1547,9 +1449,8 @@ bool CanonicalCookie::IsCanonicalForFromStorage() const { if (IsPartitioned()) { if (CookiePartitionKey::HasNonce(partition_key_)) return true; - if (!secure_ || path_ != "/" || same_party_) { + if (!secure_) return false; - } } return true; @@ -1587,6 +1488,43 @@ std::string CanonicalCookie::BuildCookieLine( } // static +std::string CanonicalCookie::BuildCookieAttributesLine( + const CanonicalCookie& cookie) { + std::string cookie_line; + // In Mozilla, if you set a cookie like "AAA", it will have an empty token + // and a value of "AAA". When it sends the cookie back, it will send "AAA", + // so we need to avoid sending "=AAA" for a blank token value. + if (!cookie.Name().empty()) + cookie_line += cookie.Name() + "="; + cookie_line += cookie.Value(); + if (!cookie.Domain().empty()) + cookie_line += "; domain=" + cookie.Domain(); + if (!cookie.Path().empty()) + cookie_line += "; path=" + cookie.Path(); + if (cookie.ExpiryDate() != base::Time()) + cookie_line += "; expires=" + TimeFormatHTTP(cookie.ExpiryDate()); + if (cookie.IsSecure()) + cookie_line += "; secure"; + if (cookie.IsHttpOnly()) + cookie_line += "; httponly"; + switch (cookie.SameSite()) { + case CookieSameSite::NO_RESTRICTION: + cookie_line += "; samesite=none"; + break; + case CookieSameSite::LAX_MODE: + cookie_line += "; samesite=lax"; + break; + case CookieSameSite::STRICT_MODE: + cookie_line += "; samesite=strict"; + break; + case CookieSameSite::UNSPECIFIED: + // Don't append any text if the samesite attribute wasn't explicitly set. + break; + } + return cookie_line; +} + +// static CanonicalCookie::CookiePrefix CanonicalCookie::GetCookiePrefix( const std::string& name) { const char kSecurePrefix[] = "__Secure-"; @@ -1726,26 +1664,21 @@ bool CanonicalCookie::IsCookiePartitionedValid( bool partition_has_nonce) { return IsCookiePartitionedValid( url, /*secure=*/parsed_cookie.IsSecure(), - parsed_cookie.HasPath() ? parsed_cookie.Path() : "", - /*is_partitioned=*/parsed_cookie.IsPartitioned(), - /*is_same_party=*/parsed_cookie.IsSameParty(), partition_has_nonce); + /*is_partitioned=*/parsed_cookie.IsPartitioned(), partition_has_nonce); } // static bool CanonicalCookie::IsCookiePartitionedValid(const GURL& url, bool secure, - const std::string& path, bool is_partitioned, - bool is_same_party, bool partition_has_nonce) { if (!is_partitioned) return true; if (partition_has_nonce) return true; - bool result = - HasValidAttributesForPartitioned(url, secure, path, is_same_party); + bool result = url.SchemeIsCryptographic() && secure; 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 1ddf1b1532b..7afdc20a502 100644 --- a/chromium/net/cookies/canonical_cookie.h +++ b/chromium/net/cookies/canonical_cookie.h @@ -429,6 +429,11 @@ class NET_EXPORT CanonicalCookie { // (ignores the access result). static std::string BuildCookieLine(const CookieAccessResultList& cookies); + // Takes a single CanonicalCookie and returns a cookie line containing the + // attributes of |cookie| formatted like a http set cookie header. + // (e.g. "cookie1=value1; domain=abc.com; path=/; secure"). + static std::string BuildCookieAttributesLine(const CanonicalCookie& cookie); + private: FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestPrefixHistograms); FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestHasHiddenPrefixName); @@ -512,16 +517,13 @@ class NET_EXPORT CanonicalCookie { // Returns true iff the cookie is a partitioned cookie with a nonce or that // does not violate the semantics of the Partitioned attribute: - // - Must have the Secure and Path=/ attributes - // - Must not have the Domain or SameParty attributes + // - Must have the Secure attribute OR the cookie partition contains a nonce. static bool IsCookiePartitionedValid(const GURL& url, const ParsedCookie& parsed_cookie, bool partition_has_nonce); static bool IsCookiePartitionedValid(const GURL& url, bool secure, - const std::string& path, bool is_partitioned, - bool is_same_party, bool partition_has_nonce); // Keep defaults here in sync with diff --git a/chromium/net/cookies/canonical_cookie_unittest.cc b/chromium/net/cookies/canonical_cookie_unittest.cc index e49d701ca5c..49cbaf3ea55 100644 --- a/chromium/net/cookies/canonical_cookie_unittest.cc +++ b/chromium/net/cookies/canonical_cookie_unittest.cc @@ -366,10 +366,6 @@ TEST(CanonicalCookieTest, Create) { // Test that a cookie string with an empty domain attribute generates a // canonical host cookie. TEST(CanonicalCookieTest, CreateHostCookieFromString) { - // Enable the feature flag for this test. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - features::kCookieDomainAttributeEmptyString); // Create a new canonical host cookie via empty string domain in the // cookie_line. GURL url("http://www.example.com/test/foo.html"); @@ -471,7 +467,10 @@ TEST(CanonicalCookieTest, CreateWithNonASCIIDomain) { absl::nullopt /* cookie_partition_key */, &status); EXPECT_EQ(nullptr, cookie.get()); EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( - {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN})); + {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN, + CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII})); + EXPECT_FALSE( + status.HasWarningReason(CookieInclusionStatus::WARN_DOMAIN_NON_ASCII)); } // Test with feature flag disabled. @@ -486,6 +485,8 @@ TEST(CanonicalCookieTest, CreateWithNonASCIIDomain) { EXPECT_TRUE(cookie2.get()); EXPECT_TRUE(status2.IsInclude()); + EXPECT_TRUE( + status2.HasWarningReason(CookieInclusionStatus::WARN_DOMAIN_NON_ASCII)); } // Test that regular ascii punycode still works. @@ -495,6 +496,8 @@ TEST(CanonicalCookieTest, CreateWithNonASCIIDomain) { absl::nullopt /* cookie_partition_key */, &status3); EXPECT_TRUE(cookie3.get()); EXPECT_TRUE(status3.IsInclude()); + EXPECT_FALSE( + status3.HasWarningReason(CookieInclusionStatus::WARN_DOMAIN_NON_ASCII)); } TEST(CanonicalCookieTest, CreateWithDomainAsIP) { @@ -645,23 +648,25 @@ TEST(CanonicalCookieTest, CreateWithPartitioned) { EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); - // Invalid Partitioned attribute: No Path attribute. + // Partitioned attribute: No Path attribute. status = CookieInclusionStatus(); cookie = CanonicalCookie::Create(url, "A=2; Partitioned; Secure", creation_time, server_time, partition_key, &status); - EXPECT_FALSE(cookie.get()); - EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( - {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); + EXPECT_TRUE(cookie.get()); + EXPECT_TRUE(status.IsInclude()); + EXPECT_TRUE(cookie->IsPartitioned()); + EXPECT_EQ(partition_key, cookie->PartitionKey()); - // Invalid Partitioned attribute: invalid Path attribute. + // Partitioned attribute: Path attribute not equal to "/". status = CookieInclusionStatus(); cookie = CanonicalCookie::Create( url, "A=2; Partitioned; Path=/foobar; Secure", creation_time, server_time, partition_key, &status); - EXPECT_FALSE(cookie.get()); - EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( - {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); + EXPECT_TRUE(cookie.get()); + EXPECT_TRUE(status.IsInclude()); + EXPECT_TRUE(cookie->IsPartitioned()); + EXPECT_EQ(partition_key, cookie->PartitionKey()); // Partitioned attribute: Domain cookie. status = CookieInclusionStatus(); @@ -674,30 +679,11 @@ TEST(CanonicalCookieTest, CreateWithPartitioned) { EXPECT_TRUE(cookie->IsPartitioned()); EXPECT_EQ(partition_key, cookie->PartitionKey()); - // Invalid Partitioned attribute: SameParty cookie. + // No Partitioned attribute but with a nonce. status = CookieInclusionStatus(); - cookie = CanonicalCookie::Create( - url, "A=2; Partitioned; Path=/; Secure; SameParty", creation_time, - server_time, partition_key, &status); - EXPECT_FALSE(cookie.get()); - EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( - {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); - - // Invalid Partitioned attribute: SameParty cookie but with a nonce. auto partition_key_with_nonce = absl::make_optional(CookiePartitionKey::FromURLForTesting( GURL("https://toplevelsite.com"), base::UnguessableToken::Create())); - status = CookieInclusionStatus(); - cookie = CanonicalCookie::Create( - url, "A=2; Partitioned; Path=/; Secure; SameParty", creation_time, - server_time, partition_key_with_nonce, &status); - EXPECT_TRUE(cookie.get()); - EXPECT_TRUE(status.IsInclude()); - EXPECT_TRUE(cookie->IsPartitioned()); - EXPECT_EQ(partition_key_with_nonce, cookie->PartitionKey()); - - // No Partitioned attribute but with a nonce. - status = CookieInclusionStatus(); cookie = CanonicalCookie::Create(url, "__Host-A=2; Path=/; Secure", creation_time, server_time, partition_key_with_nonce, &status); @@ -1633,25 +1619,21 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) { {"Common=10;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION, SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, {"Common=11;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION, SameSiteCookieContext( SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, {"Common=12;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION, SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, {"Common=13;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION, SameSiteCookieContext( SameSiteCookieContext::ContextType::SAME_SITE_STRICT), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, // Because NO_RESTRICTION cookies are always sent, the schemeful context // downgrades shouldn't matter. {"Common=14;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, @@ -1659,35 +1641,30 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) { SameSiteCookieContext( SameSiteCookieContext::ContextType::SAME_SITE_STRICT, SameSiteCookieContext::ContextType::SAME_SITE_LAX), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, {"Common=15;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION, SameSiteCookieContext( SameSiteCookieContext::ContextType::SAME_SITE_STRICT, SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, {"Common=16;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION, SameSiteCookieContext( SameSiteCookieContext::ContextType::SAME_SITE_STRICT, SameSiteCookieContext::ContextType::CROSS_SITE), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, {"Common=17;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION, SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX, SameSiteCookieContext::ContextType::CROSS_SITE), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, {"Common=18;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION, SameSiteCookieContext( SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE, SameSiteCookieContext::ContextType::CROSS_SITE), - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)}, + CookieInclusionStatus()}, }; // Test cases where the unspecified-SameSite cookie defaults to SameSite=None @@ -2088,10 +2065,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURL_SameSiteNone_Metrics) { CookieAccessParams(CookieAccessSemantics::LEGACY, delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement)), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_party_cookie->IncludeForRequestURL( url, options, @@ -2106,20 +2080,15 @@ TEST(CanonicalCookieTest, IncludeForRequestURL_SameSiteNone_Metrics) { // though they would differ unless we changed the real definition.) Then // check that if we modify the cookie as indicated, the set would be allowed, // but the next-most-restrictive variation would still be blocked. - options.set_same_party_context(SamePartyContext( - SamePartyContextType::kSameParty, SamePartyContextType::kCrossParty, - SamePartyContextType::kSameParty)); + options.set_same_party_context( + SamePartyContext(SamePartyContextType::kSameParty)); EXPECT_THAT( same_site_none_cookie->IncludeForRequestURL( url, options, CookieAccessParams(CookieAccessSemantics::LEGACY, delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement)), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_party_cookie->IncludeForRequestURL( url, options, @@ -2143,11 +2112,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURL_SameSiteNone_Metrics) { CookieAccessParams(CookieAccessSemantics::LEGACY, delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement)), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_party_cookie->IncludeForRequestURL( url, options, @@ -2172,11 +2137,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURL_SameSiteNone_Metrics) { CookieAccessParams(CookieAccessSemantics::LEGACY, delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement)), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_site_lax_cookie->IncludeForRequestURL( url, options, @@ -2201,11 +2162,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURL_SameSiteNone_Metrics) { CookieAccessParams(CookieAccessSemantics::LEGACY, delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement)), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_site_strict_cookie->IncludeForRequestURL( url, options, @@ -3009,27 +2966,16 @@ TEST(CanonicalCookieTest, IsCanonical) { GURL("https://toplevelsite.com"))) ->IsCanonical()); - // Partitioned attribute invalid, no Path. - EXPECT_FALSE(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, invalid Path. - EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( - "A", "B", "x.y", "/foobar", 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 is valid when Path != "/". + EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( + "A", "B", "x.y", "/foo/bar", 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 is valid when Domain attribute also included. EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting( @@ -3042,17 +2988,6 @@ TEST(CanonicalCookieTest, IsCanonical) { 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(), base::Time(), /*secure=*/true, - /*httponly=*/false, CookieSameSite::UNSPECIFIED, - COOKIE_PRIORITY_LOW, - /*same_party=*/true, - CookiePartitionKey::FromURLForTesting( - GURL("https://toplevelsite.com"))) - ->IsCanonical()); - // Hidden cookie prefixes. EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting( "", "__Secure-a=b", "x.y", "/", base::Time(), base::Time(), @@ -3170,6 +3105,36 @@ TEST(CanonicalCookieTest, BuildCookieLine) { MatchCookieLineToVector("A=B; C; D=E; F=G; D=E; H=I", cookies); } +TEST(CanonicalCookieTest, BuildCookieAttributesLine) { + std::unique_ptr<CanonicalCookie> cookie; + GURL url("https://example.com/"); + base::Time now = base::Time::Now(); + absl::optional<base::Time> server_time = absl::nullopt; + + cookie = CanonicalCookie::Create(url, "A=B", now, server_time, + absl::nullopt /* cookie_partition_key */); + EXPECT_EQ("A=B; domain=example.com; path=/", + CanonicalCookie::BuildCookieAttributesLine(*cookie)); + // Nameless cookies are sent back without a prefixed '='. + cookie = CanonicalCookie::Create(url, "C", now, server_time, + absl::nullopt /* cookie_partition_key */); + EXPECT_EQ("C; domain=example.com; path=/", + CanonicalCookie::BuildCookieAttributesLine(*cookie)); + // BuildCookieAttributesLine should match the spec in the case of an empty + // name with a value containing an equal sign (even if it currently produces + // "invalid" cookie lines). + cookie = CanonicalCookie::Create(url, "=H=I", now, server_time, + absl::nullopt /* cookie_partition_key */); + EXPECT_EQ("H=I; domain=example.com; path=/", + CanonicalCookie::BuildCookieAttributesLine(*cookie)); + // BuildCookieAttributesLine should include all attributes. + cookie = CanonicalCookie::Create( + url, "A=B; domain=.example.com; path=/; secure; httponly; samesite=lax", + now, server_time, absl::nullopt /* cookie_partition_key */); + EXPECT_EQ("A=B; domain=.example.com; path=/; secure; httponly; samesite=lax", + CanonicalCookie::BuildCookieAttributesLine(*cookie)); +} + // Confirm that input arguments are reflected in the output cookie. TEST(CanonicalCookieTest, CreateSanitizedCookie_Inputs) { base::Time two_hours_ago = base::Time::Now() - base::Hours(2); @@ -3828,7 +3793,7 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) { {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); // Invalid: invalid Path. status = CookieInclusionStatus(); - EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie( + EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie( GURL("https://www.foo.com"), "A", "B", std::string(), "/foobar", two_hours_ago, one_hour_from_now, one_hour_ago, /*secure=*/true, /*http_only=*/false, CookieSameSite::NO_RESTRICTION, @@ -3837,8 +3802,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()); // Domain attribute present is still valid. status = CookieInclusionStatus(); EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie( @@ -3850,18 +3814,6 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) { GURL("https://toplevelsite.com"))), &status)); EXPECT_TRUE(status.IsInclude()); - // Invalid: SameParty attribute present. - status = CookieInclusionStatus(); - EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie( - GURL("https://www.foo.com"), "A", "B", std::string(), "/", two_hours_ago, - one_hour_from_now, one_hour_ago, /*secure=*/true, /*http_only=*/false, - CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT, - /*same_party=*/true, - absl::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting( - GURL("https://toplevelsite.com"))), - &status)); - EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting( - {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED})); status = CookieInclusionStatus(); @@ -5021,10 +4973,7 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameSiteNone_Metrics) { delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement), kCookieableSchemes), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_party_cookie->IsSetPermittedInContext( url, options, @@ -5039,9 +4988,8 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameSiteNone_Metrics) { // "real" same-partyness value match the value computed for the metric, even // though they would differ unless we changed the real definition.) Then // check that if we modify the cookie as indicated, the set would be allowed. - options.set_same_party_context(SamePartyContext( - SamePartyContextType::kSameParty, SamePartyContextType::kCrossParty, - SamePartyContextType::kSameParty)); + options.set_same_party_context( + SamePartyContext(SamePartyContextType::kSameParty)); EXPECT_THAT( same_site_none_cookie->IsSetPermittedInContext( url, options, @@ -5049,11 +4997,7 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameSiteNone_Metrics) { delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement), kCookieableSchemes), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_party_cookie->IsSetPermittedInContext( url, options, @@ -5080,11 +5024,7 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameSiteNone_Metrics) { delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement), kCookieableSchemes), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_party_cookie->IsSetPermittedInContext( url, options, @@ -5112,11 +5052,7 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameSiteNone_Metrics) { delegate_treats_url_as_trustworthy, CookieSamePartyStatus::kNoSamePartyEnforcement), kCookieableSchemes), - MatchesCookieAccessResult( - CookieInclusionStatus::MakeFromReasonsForTesting( - {}, {CookieInclusionStatus:: - WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT}), - _, _, true)); + MatchesCookieAccessResult(CookieInclusionStatus(), _, _, true)); EXPECT_THAT( same_site_lax_cookie->IsSetPermittedInContext( url, options, @@ -5364,8 +5300,12 @@ TEST(CanonicalCookieTest, TestHasHiddenPrefixName) { {" \t ", false}, {"\t", false}, {"__Secure-abc", false}, + {"__Secure=-", false}, + {"__Secure=-abc", false}, {"__Secur=e-abc", false}, {"__Secureabc", false}, + {"__Host=-", false}, + {"__Host=-abc", false}, {"__Host-abc", false}, {"__Hos=t-abc", false}, {"_Host", false}, @@ -5373,12 +5313,16 @@ TEST(CanonicalCookieTest, TestHasHiddenPrefixName) { {"\t__Host-", false}, {"a__Host-abc=123", false}, {"a__Secure-abc=123", false}, + {"__Host-=", true}, + {"__Host-=123", true}, {"__Host-abc=", true}, {"__Host-abc=123", true}, {" __Host-abc=123", true}, {" __Host-abc=", true}, {"\t\t\t\t\t__Host-abc=123", true}, {"\t __Host-abc=", true}, + {"__Secure-=", true}, + {"__Secure-=123", true}, {"__Secure-abc=", true}, {"__Secure-abc=123", true}, {" __Secure-abc=123", true}, diff --git a/chromium/net/cookies/cookie_access_delegate.cc b/chromium/net/cookies/cookie_access_delegate.cc index 9ed9ed4a15e..87422832773 100644 --- a/chromium/net/cookies/cookie_access_delegate.cc +++ b/chromium/net/cookies/cookie_access_delegate.cc @@ -7,22 +7,21 @@ #include <set> #include "base/callback.h" -#include "base/stl_util.h" #include "net/base/schemeful_site.h" #include "net/cookies/cookie_partition_key.h" -#include "net/cookies/first_party_set_metadata.h" +#include "net/cookies/first_party_set_entry.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace net { namespace { -CookiePartitionKey CreateCookiePartitionKeyFromFirstPartySetOwner( +CookiePartitionKey CreateCookiePartitionKeyFromFirstPartySetEntry( const CookiePartitionKey& cookie_partition_key, - absl::optional<SchemefulSite> first_party_set_owner) { - if (!first_party_set_owner) { + base::flat_map<net::SchemefulSite, FirstPartySetEntry> entries) { + if (entries.empty()) { return cookie_partition_key; } - return CookiePartitionKey::FromWire(first_party_set_owner.value(), + return CookiePartitionKey::FromWire(entries.begin()->second.primary(), cookie_partition_key.nonce()); } } // namespace @@ -48,15 +47,15 @@ CookieAccessDelegate::FirstPartySetifyPartitionKey( return cookie_partition_key; } - absl::optional<absl::optional<SchemefulSite>> maybe_owner = - delegate->FindFirstPartySetOwner( - cookie_partition_key.site(), - base::BindOnce(&CreateCookiePartitionKeyFromFirstPartySetOwner, + absl::optional<base::flat_map<net::SchemefulSite, FirstPartySetEntry>> + maybe_entries = delegate->FindFirstPartySetOwners( + {cookie_partition_key.site()}, + base::BindOnce(&CreateCookiePartitionKeyFromFirstPartySetEntry, cookie_partition_key) .Then(std::move(callback))); - if (maybe_owner.has_value()) - return CreateCookiePartitionKeyFromFirstPartySetOwner(cookie_partition_key, - maybe_owner.value()); + if (maybe_entries.has_value()) + return CreateCookiePartitionKeyFromFirstPartySetEntry( + cookie_partition_key, maybe_entries.value()); return absl::nullopt; } diff --git a/chromium/net/cookies/cookie_access_delegate.h b/chromium/net/cookies/cookie_access_delegate.h index 71878fad70b..3d69dbe7d38 100644 --- a/chromium/net/cookies/cookie_access_delegate.h +++ b/chromium/net/cookies/cookie_access_delegate.h @@ -15,6 +15,7 @@ #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_partition_key.h" +#include "net/cookies/first_party_set_entry.h" #include "net/cookies/first_party_set_metadata.h" #include "net/cookies/same_party_context.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -67,34 +68,21 @@ class NET_EXPORT CookieAccessDelegate { const std::set<net::SchemefulSite>& party_context, base::OnceCallback<void(FirstPartySetMetadata)> callback) const = 0; - // Computes the owner of a `site`'s First-Party Set if `site` is in a - // non-trivial set; `nullopt` otherwise. - // - // This may return a result synchronously, or asynchronously invoke `callback` - // with the result. The callback will be invoked iff the return value is - // nullopt; i.e. a result will be provided via return value or callback, but - // not both, and not neither. - [[nodiscard]] virtual absl::optional<absl::optional<net::SchemefulSite>> - FindFirstPartySetOwner( - const net::SchemefulSite& site, - base::OnceCallback<void(absl::optional<net::SchemefulSite>)> callback) - const = 0; - - // Computes the owners of a set of sites' First-Party Sets if the site are in - // non-trivial sets. If a given site is not in a non-trivial set, the output - // does not contain a corresponding owner. + // Returns the entries of a set of sites if the sites are in non-trivial sets. + // If a given site is not in a non-trivial set, the output does not contain a + // corresponding entry. // // This may return a result synchronously, or asynchronously invoke `callback` // with the result. The callback will be invoked iff the return value is // nullopt; i.e. a result will be provided via return value or callback, but // not both, and not neither. [[nodiscard]] virtual absl::optional< - base::flat_map<net::SchemefulSite, net::SchemefulSite>> + base::flat_map<net::SchemefulSite, net::FirstPartySetEntry>> FindFirstPartySetOwners( const base::flat_set<net::SchemefulSite>& sites, - base::OnceCallback<void( - base::flat_map<net::SchemefulSite, net::SchemefulSite>)> callback) - const = 0; + base::OnceCallback< + void(base::flat_map<net::SchemefulSite, net::FirstPartySetEntry>)> + callback) const = 0; // Converts the CookiePartitionKey's site to its First-Party Set owner if // the site is in a nontrivial set. @@ -108,19 +96,6 @@ class NET_EXPORT CookieAccessDelegate { const CookieAccessDelegate* delegate, const CookiePartitionKey& cookie_partition_key, base::OnceCallback<void(CookiePartitionKey)> callback); - - // Computes the First-Party Sets. - // - // This may return a result synchronously, or asynchronously invoke `callback` - // with the result. The callback will be invoked iff the return value is - // nullopt; i.e. a result will be provided via return value or callback, but - // not both, and not neither. - [[nodiscard]] virtual absl::optional< - base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>>> - RetrieveFirstPartySets( - base::OnceCallback<void( - base::flat_map<net::SchemefulSite, std::set<net::SchemefulSite>>)> - callback) const = 0; }; } // namespace net diff --git a/chromium/net/cookies/cookie_constants.h b/chromium/net/cookies/cookie_constants.h index 52f1aca96d9..30e9ea6203d 100644 --- a/chromium/net/cookies/cookie_constants.h +++ b/chromium/net/cookies/cookie_constants.h @@ -306,28 +306,6 @@ enum class CookieSourceSchemeName { kMaxValue = kChromeExtensionScheme }; -// This enum must match the numbering for FirstPartySetsContextType in -// histograms/enums.xml. Do not reorder or remove items, only add new items at -// the end. -enum class FirstPartySetsContextType { - // Unknown context type. - kUnknown = 0, - // The top frame was ignored, and the rest of the context consisted of at - // least 2 different parties. - kTopFrameIgnoredMixed = 1, - // The top frame was ignored, and the rest of the context was a single party. - kTopFrameIgnoredHomogeneous = 2, - // The top frame and resource URL were of different parties. - kTopResourceMismatch = 3, - // The top frame and resource URL were both of the same party, and there was - // at least one intervening frame of a different party. - kTopResourceMatchMixed = 4, - // The top frame, resource URL, and all intervening frames were all from the - // same party. - kHomogeneous = 5, - kMaxValue = kHomogeneous, -}; - // Returns the Set-Cookie header priority token corresponding to |priority|. NET_EXPORT std::string CookiePriorityToString(CookiePriority priority); diff --git a/chromium/net/cookies/cookie_inclusion_status.cc b/chromium/net/cookies/cookie_inclusion_status.cc index 46342570471..58f0e738abd 100644 --- a/chromium/net/cookies/cookie_inclusion_status.cc +++ b/chromium/net/cookies/cookie_inclusion_status.cc @@ -170,28 +170,26 @@ CookieInclusionStatus::GetBreakingDowngradeMetricsEnumValue( switch (reason) { case WarningReason::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE: return url_is_secure - ? ContextDowngradeMetricValues::STRICT_LAX_STRICT_SECURE - : ContextDowngradeMetricValues::STRICT_LAX_STRICT_INSECURE; + ? ContextDowngradeMetricValues::kStrictLaxStrictSecure + : ContextDowngradeMetricValues::kStrictLaxStrictInsecure; case WarningReason::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE: return url_is_secure - ? ContextDowngradeMetricValues::STRICT_CROSS_STRICT_SECURE - : ContextDowngradeMetricValues::STRICT_CROSS_STRICT_INSECURE; + ? ContextDowngradeMetricValues::kStrictCrossStrictSecure + : ContextDowngradeMetricValues::kStrictCrossStrictInsecure; case WarningReason::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE: return url_is_secure - ? ContextDowngradeMetricValues::STRICT_CROSS_LAX_SECURE - : ContextDowngradeMetricValues::STRICT_CROSS_LAX_INSECURE; + ? ContextDowngradeMetricValues::kStrictCrossLaxSecure + : ContextDowngradeMetricValues::kStrictCrossLaxInsecure; case WarningReason::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE: return url_is_secure - ? ContextDowngradeMetricValues::LAX_CROSS_STRICT_SECURE - : ContextDowngradeMetricValues::LAX_CROSS_STRICT_INSECURE; + ? ContextDowngradeMetricValues::kLaxCrossStrictSecure + : ContextDowngradeMetricValues::kLaxCrossStrictInsecure; case WarningReason::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE: - return url_is_secure - ? ContextDowngradeMetricValues::LAX_CROSS_LAX_SECURE - : ContextDowngradeMetricValues::LAX_CROSS_LAX_INSECURE; + return url_is_secure ? ContextDowngradeMetricValues::kLaxCrossLaxSecure + : ContextDowngradeMetricValues::kLaxCrossLaxInsecure; default: - return url_is_secure - ? ContextDowngradeMetricValues::NO_DOWNGRADE_SECURE - : ContextDowngradeMetricValues::NO_DOWNGRADE_INSECURE; + return url_is_secure ? ContextDowngradeMetricValues::kNoDowngradeSecure + : ContextDowngradeMetricValues::kNoDowngradeInsecure; } } @@ -227,6 +225,7 @@ std::string CookieInclusionStatus::GetDebugString() const { "EXCLUDE_NAME_VALUE_PAIR_EXCEEDS_MAX_SIZE"}, {EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE, "EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE"}, + {EXCLUDE_DOMAIN_NON_ASCII, "EXCLUDE_DOMAIN_NON_ASCII"}, }) { if (HasExclusionReason(reason.first)) base::StrAppend(&out, {reason.second, ", "}); @@ -261,19 +260,11 @@ std::string CookieInclusionStatus::GetDebugString() const { "WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE"}, {WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE, "WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE"}, - {WARN_SAMESITE_NONE_REQUIRED, "WARN_SAMESITE_NONE_REQUIRED"}, - {WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE, - "WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE"}, - {WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS, - "WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS"}, - {WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX, - "WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX"}, - {WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT, - "WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT"}, {WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION, "WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION"}, {WARN_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE, "WARN_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE"}, + {WARN_DOMAIN_NON_ASCII, "WARN_DOMAIN_NON_ASCII"}, }) { if (HasWarningReason(reason.first)) base::StrAppend(&out, {reason.second, ", "}); diff --git a/chromium/net/cookies/cookie_inclusion_status.h b/chromium/net/cookies/cookie_inclusion_status.h index 2e9c319a3d2..246fe025f27 100644 --- a/chromium/net/cookies/cookie_inclusion_status.h +++ b/chromium/net/cookies/cookie_inclusion_status.h @@ -94,6 +94,8 @@ class NET_EXPORT CookieInclusionStatus { // whole cookie to be rejected. There will be a corresponding WarningReason // to notify users that an attribute value was ignored in that case. EXCLUDE_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE = 20, + // Cookie was set with a Domain attribute containing non ASCII characters. + EXCLUDE_DOMAIN_NON_ASCII = 21, // This should be kept last. NUM_EXCLUSION_REASONS @@ -186,26 +188,6 @@ class NET_EXPORT CookieInclusionStatus { // contexts, for cookies that are 'SameParty; SameSite=Lax'.) WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE = 11, - // This cookie was SameSite=None and was included, but would have been - // excluded if it had been SameParty and the SameParty context had been - // computed using *either* top & current or the whole ancestor tree. - WARN_SAMESITE_NONE_REQUIRED = 12, - // This cookie was SameSite=None, was included, would have been included if - // it had been SameParty and the SameParty context type had been computed - // with only the top frame & resource URL, but would have been excluded if - // the SameParty context type had been computed using all ancestor frames. - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE = 13, - // This cookie was SameSite=None, was included, and would have been included - // if it had been SameParty and the SameParty context type had been computed - // using all ancestor frames. - WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS = 14, - // This cookie was SameSite=None, was included, and would have been included - // if it had been SameSite=Lax. - WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX = 15, - // This cookie was SameSite=None, was included, and would have been included - // if it had been SameSite=Strict. - WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT = 16, - // The cookie would have been included prior to the spec change considering // redirects in the SameSite context calculation // (https://github.com/httpwg/http-extensions/pull/1348) @@ -216,13 +198,16 @@ class NET_EXPORT CookieInclusionStatus { // was actually used for the inclusion decision). This is not applied if // the context was downgraded but the cookie would have been // included/excluded in both cases. - WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION = 17, + WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION = 12, // The cookie exceeded the attribute size limit. RFC6265bis indicates that // large attributes should be ignored instead of causing the whole cookie // to be rejected. This is applied by the code that parses cookie lines and // notifies the user that an attribute value was ignored. - WARN_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE = 18, + WARN_ATTRIBUTE_VALUE_EXCEEDS_MAX_SIZE = 13, + + // Cookie was set with a Domain attribute containing non ASCII characters. + WARN_DOMAIN_NON_ASCII = 14, // This should be kept last. NUM_WARNING_REASONS @@ -230,30 +215,30 @@ class NET_EXPORT CookieInclusionStatus { // These enums encode the context downgrade warnings + the secureness of the // url sending/setting the cookie. They're used for metrics only. The format - // is {context}_{schemeful_context}_{samesite_value}_{securness}. - // NO_DOWNGRADE_{securness} indicates that a cookie didn't have a breaking + // is k{context}{schemeful_context}{samesite_value}{securness}. + // kNoDowngrade{securness} indicates that a cookie didn't have a breaking // context downgrade and was A) included B) excluded only due to insufficient // same-site context. I.e. the cookie wasn't excluded due to other reasons // such as third-party cookie blocking. Keep this in line with // SameSiteCookieContextBreakingDowngradeWithSecureness in enums.xml. - enum ContextDowngradeMetricValues { - NO_DOWNGRADE_INSECURE = 0, - NO_DOWNGRADE_SECURE = 1, - - STRICT_LAX_STRICT_INSECURE = 2, - STRICT_CROSS_STRICT_INSECURE = 3, - STRICT_CROSS_LAX_INSECURE = 4, - LAX_CROSS_STRICT_INSECURE = 5, - LAX_CROSS_LAX_INSECURE = 6, - - STRICT_LAX_STRICT_SECURE = 7, - STRICT_CROSS_STRICT_SECURE = 8, - STRICT_CROSS_LAX_SECURE = 9, - LAX_CROSS_STRICT_SECURE = 10, - LAX_CROSS_LAX_SECURE = 11, + enum class ContextDowngradeMetricValues { + kNoDowngradeInsecure = 0, + kNoDowngradeSecure = 1, + + kStrictLaxStrictInsecure = 2, + kStrictCrossStrictInsecure = 3, + kStrictCrossLaxInsecure = 4, + kLaxCrossStrictInsecure = 5, + kLaxCrossLaxInsecure = 6, + + kStrictLaxStrictSecure = 7, + kStrictCrossStrictSecure = 8, + kStrictCrossLaxSecure = 9, + kLaxCrossStrictSecure = 10, + kLaxCrossLaxSecure = 11, // Keep last. - kMaxValue = LAX_CROSS_LAX_SECURE + kMaxValue = kLaxCrossLaxSecure }; using ExclusionReasonBitset = diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc index 644e5fc1371..937e61e2663 100644 --- a/chromium/net/cookies/cookie_monster.cc +++ b/chromium/net/cookies/cookie_monster.cc @@ -59,6 +59,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/ranges/algorithm.h" +#include "base/strings/strcat.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -82,6 +83,7 @@ #include "url/origin.h" #include "url/third_party/mozilla/url_parse.h" #include "url/url_canon.h" +#include "url/url_constants.h" using base::Time; using base::TimeTicks; @@ -159,6 +161,13 @@ bool IncludeUnpartitionedCookies( return false; } +size_t NameValueSizeBytes(const std::string& name, const std::string& value) { + base::CheckedNumeric<size_t> name_value_pair_size = name.size(); + name_value_pair_size += value.size(); + DCHECK(name_value_pair_size.IsValid()); + return name_value_pair_size.ValueOrDie(); +} + } // namespace namespace net { @@ -993,12 +1002,11 @@ void CookieMonster::EnsureCookiesMapIsValid() { DCHECK(thread_checker_.CalledOnValidThread()); // Iterate through all the of the cookies, grouped by host. - auto prev_range_end = cookies_.begin(); - while (prev_range_end != cookies_.end()) { - auto cur_range_begin = prev_range_end; + for (auto next = cookies_.begin(); next != cookies_.end();) { + auto cur_range_begin = next; const std::string key = cur_range_begin->first; // Keep a copy. auto cur_range_end = cookies_.upper_bound(key); - prev_range_end = cur_range_end; + next = cur_range_end; // Ensure no equivalent cookies for this host. TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end, @@ -1117,8 +1125,10 @@ void CookieMonster::TrimDuplicateCookiesForKey( } std::vector<CanonicalCookie*> -CookieMonster::FindCookiesForRegistryControlledHost(const GURL& url, - CookieMap* cookie_map) { +CookieMonster::FindCookiesForRegistryControlledHost( + const GURL& url, + CookieMap* cookie_map, + CookieMonster::PartitionedCookieMap::iterator* partition_it) { DCHECK(thread_checker_.CalledOnValidThread()); if (!cookie_map) @@ -1138,7 +1148,14 @@ CookieMonster::FindCookiesForRegistryControlledHost(const GURL& url, // If the cookie is expired, delete it. if (cc->IsExpired(current_time)) { - InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED); + if (cc->IsPartitioned()) { + DCHECK(partition_it); + DCHECK_EQ((*partition_it)->second.get(), cookie_map); + InternalDeletePartitionedCookie(*partition_it, curit, true, + DELETE_COOKIE_EXPIRED); + } else { + InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPIRED); + } continue; } cookies.push_back(cc); @@ -1157,7 +1174,7 @@ CookieMonster::FindPartitionedCookiesForRegistryControlledHost( if (it == partitioned_cookies_.end()) return std::vector<CanonicalCookie*>(); - return FindCookiesForRegistryControlledHost(url, it->second.get()); + return FindCookiesForRegistryControlledHost(url, it->second.get(), &it); } void CookieMonster::FilterCookiesWithOptions( @@ -1542,6 +1559,11 @@ void CookieMonster::SetCanonicalCookie( 1 + IsolationInfo::kPartyContextMaxSize); } + if (cc->IsEffectivelySameSiteNone()) { + UMA_HISTOGRAM_COUNTS_10000("Cookie.SameSiteNoneSizeBytes", + NameValueSizeBytes(cc->Name(), cc->Value())); + } + bool is_partitioned_cookie = cc->IsPartitioned(); CookiePartitionKey cookie_partition_key; if (is_partitioned_cookie) @@ -1562,11 +1584,11 @@ void CookieMonster::SetCanonicalCookie( CookieSource cookie_source_sample = (source_url.SchemeIsCryptographic() ? (cc->IsSecure() - ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME - : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME) + ? CookieSource::kSecureCookieCryptographicScheme + : CookieSource::kNonsecureCookieCryptographicScheme) : (cc->IsSecure() - ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME - : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME)); + ? CookieSource::kSecureCookieNoncryptographicScheme + : CookieSource::kNonsecureCookieNoncryptographicScheme)); UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSourceScheme", cookie_source_sample); @@ -2238,8 +2260,20 @@ bool CookieMonster::DoRecordPeriodicStats() { base::UmaHistogramCounts100000("Cookie.Count2", cookies_.size()); if (cookie_access_delegate()) { - absl::optional<base::flat_map<SchemefulSite, std::set<SchemefulSite>>> - maybe_sets = cookie_access_delegate()->RetrieveFirstPartySets( + std::vector<SchemefulSite> sites; + for (const auto& entry : cookies_) { + sites.emplace_back( + GURL(base::StrCat({url::kHttpsScheme, "://", entry.first}))); + } + for (const auto& [partition_key, cookie_map] : partitioned_cookies_) { + for (const auto& [domain, unused_cookie] : *cookie_map) { + sites.emplace_back( + GURL(base::StrCat({url::kHttpsScheme, "://", domain}))); + } + } + absl::optional<base::flat_map<SchemefulSite, FirstPartySetEntry>> + maybe_sets = cookie_access_delegate()->FindFirstPartySetOwners( + sites, base::BindOnce(&CookieMonster::RecordPeriodicFirstPartySetsStats, weak_ptr_factory_.GetWeakPtr())); if (maybe_sets.has_value()) @@ -2252,6 +2286,20 @@ bool CookieMonster::DoRecordPeriodicStats() { // Can be up to kMaxCookies. UMA_HISTOGRAM_COUNTS_10000("Cookie.NumKeys", num_keys_); + std::map<std::string, size_t> n_same_site_none_cookies; + for (const auto& [host_key, host_cookie] : cookies_) { + if (!host_cookie || !host_cookie->IsEffectivelySameSiteNone()) + continue; + n_same_site_none_cookies[host_key]++; + } + size_t max_n_cookies = 0; + for (const auto& entry : n_same_site_none_cookies) { + max_n_cookies = std::max(max_n_cookies, entry.second); + } + // Can be up to 180 cookies, the max per-domain. + base::UmaHistogramCounts1000("Cookie.MaxSameSiteNoneCookiesPerKey", + max_n_cookies); + // Collect stats for partitioned cookies if they are enabled. if (base::FeatureList::IsEnabled(features::kPartitionedCookies)) { base::UmaHistogramCounts1000("Cookie.PartitionCount", @@ -2264,8 +2312,12 @@ bool CookieMonster::DoRecordPeriodicStats() { } void CookieMonster::RecordPeriodicFirstPartySetsStats( - base::flat_map<SchemefulSite, std::set<SchemefulSite>> sets) const { - for (const auto& set : sets) { + base::flat_map<SchemefulSite, FirstPartySetEntry> sets) const { + base::flat_map<SchemefulSite, std::set<SchemefulSite>> grouped_by_owner; + for (const auto& [site, entry] : sets) { + grouped_by_owner[entry.primary()].insert(site); + } + for (const auto& set : grouped_by_owner) { int sample = std::accumulate( set.second.begin(), set.second.end(), 0, [this](int acc, const net::SchemefulSite& site) -> int { diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h index d2cfebf4900..213d37d2509 100644 --- a/chromium/net/cookies/cookie_monster.h +++ b/chromium/net/cookies/cookie_monster.h @@ -344,17 +344,17 @@ class NET_EXPORT CookieMonster : public CookieStore { // entries. New items MUST be added at the end of the list, and kMaxValue // should be updated to the last value. // - // COOKIE_SOURCE_(NON)SECURE_COOKIE_(NON)CRYPTOGRAPHIC_SCHEME means + // CookieSource::k(Non)SecureCookie(Non)CryptographicScheme means // that a cookie was set or overwritten from a URL with the given type // of scheme. This enum should not be used when cookies are *cleared*, // because its purpose is to understand if Chrome can deprecate the // ability of HTTP urls to set/overwrite Secure cookies. - enum CookieSource { - COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME = 0, - COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, - COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, - COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, - kMaxValue = COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME + enum class CookieSource : uint8_t { + kSecureCookieCryptographicScheme = 0, + kSecureCookieNoncryptographicScheme, + kNonsecureCookieCryptographicScheme, + kNonsecureCookieNoncryptographicScheme, + kMaxValue = kNonsecureCookieNoncryptographicScheme }; // Enum for collecting metrics on how frequently a cookie is sent to the same @@ -483,7 +483,8 @@ class NET_EXPORT CookieMonster : public CookieStore { std::vector<CanonicalCookie*> FindCookiesForRegistryControlledHost( const GURL& url, - CookieMap* cookie_map = nullptr); + CookieMap* cookie_map = nullptr, + PartitionedCookieMap::iterator* partition_it = nullptr); std::vector<CanonicalCookie*> FindPartitionedCookiesForRegistryControlledHost( const CookiePartitionKey& cookie_partition_key, @@ -688,10 +689,8 @@ class NET_EXPORT CookieMonster : public CookieStore { // First-Party Sets presents a potentially asynchronous interface, these stats // may be collected asynchronously w.r.t. the rest of the stats collected by // `RecordPeriodicStats`. - // TODO(https://crbug.com/1266014): don't assume that the sets can all fit in - // memory at once. void RecordPeriodicFirstPartySetsStats( - base::flat_map<SchemefulSite, std::set<SchemefulSite>> sets) const; + base::flat_map<SchemefulSite, FirstPartySetEntry> sets) const; // Defers the callback until the full coookie database has been loaded. If // it's already been loaded, runs the callback synchronously. diff --git a/chromium/net/cookies/cookie_monster_perftest.cc b/chromium/net/cookies/cookie_monster_perftest.cc index 12de7b53e46..6ad5922a685 100644 --- a/chromium/net/cookies/cookie_monster_perftest.cc +++ b/chromium/net/cookies/cookie_monster_perftest.cc @@ -63,7 +63,7 @@ perf_test::PerfResultReporter SetUpCookieMonsterReporter( class CookieMonsterTest : public testing::Test { public: - CookieMonsterTest() {} + CookieMonsterTest() = default; private: base::test::SingleThreadTaskEnvironment task_environment_{ @@ -220,7 +220,7 @@ TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) { std::string cookie(kCookieLine); std::vector<GURL> gurls; // just wanna have ffffuunnn for (int i = 0; i < kNumCookies; ++i) { - gurls.push_back(GURL(base::StringPrintf("https://a%04d.izzle", i))); + gurls.emplace_back(base::StringPrintf("https://a%04d.izzle", i)); } SetCookieCallback setCookieCallback; @@ -356,7 +356,7 @@ TEST_F(CookieMonsterTest, TestDomainLine) { } TEST_F(CookieMonsterTest, TestImport) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies; GetCookieListCallback getCookieListCallback; @@ -377,8 +377,8 @@ TEST_F(CookieMonsterTest, TestImport) { store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm( - new CookieMonster(store.get(), nullptr, kFirstPartySetsEnabled)); + auto cm = std::make_unique<CookieMonster>(store.get(), nullptr, + kFirstPartySetsEnabled); // Import will happen on first access. GURL gurl("www.foo.com"); @@ -394,8 +394,8 @@ TEST_F(CookieMonsterTest, TestImport) { } TEST_F(CookieMonsterTest, TestGetKey) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, kFirstPartySetsEnabled)); + auto cm = + std::make_unique<CookieMonster>(nullptr, nullptr, kFirstPartySetsEnabled); auto reporter = SetUpCookieMonsterReporter("baseline_story"); base::ElapsedTimer get_key_timer; for (int i = 0; i < kNumCookies; i++) diff --git a/chromium/net/cookies/cookie_monster_store_test.cc b/chromium/net/cookies/cookie_monster_store_test.cc index 1bc8e950827..38bce0b9b6a 100644 --- a/chromium/net/cookies/cookie_monster_store_test.cc +++ b/chromium/net/cookies/cookie_monster_store_test.cc @@ -141,8 +141,10 @@ void MockSimplePersistentCookieStore::Load( const NetLogWithSource& /* net_log */) { std::vector<std::unique_ptr<CanonicalCookie>> out_cookies; - for (auto it = cookies_.begin(); it != cookies_.end(); it++) - out_cookies.push_back(std::make_unique<CanonicalCookie>(it->second)); + for (const auto& cookie_map_it : cookies_) { + out_cookies.push_back( + std::make_unique<CanonicalCookie>(cookie_map_it.second)); + } base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, @@ -203,8 +205,7 @@ std::unique_ptr<CookieMonster> CreateMonsterFromStoreForGC( int days_old) { base::Time current(base::Time::Now()); base::Time past_creation(base::Time::Now() - base::Days(100)); - scoped_refptr<MockSimplePersistentCookieStore> store( - new MockSimplePersistentCookieStore); + auto store = base::MakeRefCounted<MockSimplePersistentCookieStore>(); int total_cookies = num_secure_cookies + num_non_secure_cookies; int base = 0; // Must expire to be persistent diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc index f143924451e..7150e7399cb 100644 --- a/chromium/net/cookies/cookie_monster_unittest.cc +++ b/chromium/net/cookies/cookie_monster_unittest.cc @@ -376,9 +376,9 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { const std::string& domain, const std::string& name) { CookieList cookies = this->GetAllCookies(cm); - for (auto it = cookies.begin(); it != cookies.end(); ++it) - if (it->Domain() == domain && it->Name() == name) - return this->DeleteCanonicalCookie(cm, *it); + for (auto& cookie : cookies) + if (cookie.Domain() == domain && cookie.Name() == name) + return this->DeleteCanonicalCookie(cm, cookie); return false; } @@ -557,7 +557,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { CookiePriorityToString(priority).c_str(), is_secure ? "secure" : ""); EXPECT_TRUE(SetCookie(cm, https_www_foo_.url(), cookie)); - cookie_data.push_back(std::make_pair(is_secure, priority)); + cookie_data.emplace_back(is_secure, priority); id_list[is_secure][priority].push_back(next_cookie_id); } } @@ -957,9 +957,9 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { // Function for creating a CM with a number of cookies in it, // no store (and hence no ability to affect access time). - CookieMonster* CreateMonsterForGC(int num_cookies) { - CookieMonster* cm( - new CookieMonster(nullptr, net::NetLog::Get(), kFirstPartySetsDefault)); + std::unique_ptr<CookieMonster> CreateMonsterForGC(int num_cookies) { + auto cm = std::make_unique<CookieMonster>(nullptr, net::NetLog::Get(), + kFirstPartySetsDefault); base::Time creation_time = base::Time::Now(); for (int i = 0; i < num_cookies; i++) { std::unique_ptr<CanonicalCookie> cc( @@ -979,16 +979,16 @@ class CookieMonsterTestBase : public CookieStoreTest<T> { } bool IsCookieInList(const CanonicalCookie& cookie, const CookieList& list) { - for (auto it = list.begin(); it != list.end(); ++it) { - if (it->Name() == cookie.Name() && it->Value() == cookie.Value() && - it->Domain() == cookie.Domain() && it->Path() == cookie.Path() && - 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()) { + for (const auto& c : list) { + if (c.Name() == cookie.Name() && c.Value() == cookie.Value() && + c.Domain() == cookie.Domain() && c.Path() == cookie.Path() && + c.CreationDate() == cookie.CreationDate() && + c.ExpiryDate() == cookie.ExpiryDate() && + c.LastAccessDate() == cookie.LastAccessDate() && + c.LastUpdateDate() == cookie.LastUpdateDate() && + c.IsSecure() == cookie.IsSecure() && + c.IsHttpOnly() == cookie.IsHttpOnly() && + c.Priority() == cookie.Priority()) { return true; } } @@ -1443,9 +1443,9 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) { } TEST_F(CookieMonsterTest, TestCookieDeleteAll) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); CookieOptions options = CookieOptions::MakeAllInclusive(); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), kValidCookieLine)); @@ -1740,9 +1740,9 @@ static const base::TimeDelta kAccessDelay = kLastAccessThreshold + base::Milliseconds(20); TEST_F(CookieMonsterTest, TestLastAccess) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, kLastAccessThreshold, net::NetLog::Get(), - kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(nullptr, kLastAccessThreshold, + net::NetLog::Get(), + kFirstPartySetsDefault); EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=B")); const Time last_access_date(GetFirstCookieAccessDate(cm.get())); @@ -1803,8 +1803,8 @@ TEST_F(CookieMonsterTest, SetCookieableSchemes) { auto cm = std::make_unique<CookieMonster>(nullptr, net::NetLog::Get(), kFirstPartySetsDefault); - std::unique_ptr<CookieMonster> cm_foo( - new CookieMonster(nullptr, net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm_foo = std::make_unique<CookieMonster>(nullptr, net::NetLog::Get(), + kFirstPartySetsDefault); // Only cm_foo should allow foo:// cookies. std::vector<std::string> schemes; @@ -1865,9 +1865,9 @@ TEST_F(CookieMonsterTest, SetCookieableSchemes) { } TEST_F(CookieMonsterTest, GetAllCookiesForURL) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, kLastAccessThreshold, net::NetLog::Get(), - kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(nullptr, kLastAccessThreshold, + net::NetLog::Get(), + kFirstPartySetsDefault); // Create an httponly cookie. CookieOptions options = CookieOptions::MakeAllInclusive(); @@ -1983,9 +1983,9 @@ TEST_F(CookieMonsterTest, GetAllCookiesForURL) { } TEST_F(CookieMonsterTest, GetExcludedCookiesForURL) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, kLastAccessThreshold, net::NetLog::Get(), - kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(nullptr, kLastAccessThreshold, + net::NetLog::Get(), + kFirstPartySetsDefault); // Create an httponly cookie. CookieOptions options = CookieOptions::MakeAllInclusive(); @@ -2248,13 +2248,44 @@ TEST_F(CookieMonsterTest, DeleteExpiredCookiesOnGet) { EXPECT_EQ(1u, cookies.size()); } +// Test that cookie expiration works when there are only partitioned cookies and +// expiration happens without SetCookie. +TEST_F(CookieMonsterTest, DeleteExpiredPartitionedCookiesOnlyOnGet) { + auto cm = std::make_unique<CookieMonster>( + /*store=*/nullptr, net::NetLog::Get(), kFirstPartySetsDefault); + auto cookie_partition_key = + CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com")); + + EXPECT_TRUE(SetCookie(cm.get(), https_www_bar_.url(), + "__Host-A=B; secure; path=/; partitioned", + cookie_partition_key)); + // Set a cookie with a Max-Age. Since we only parse integers for this + // attribute, 1 second is the minimum allowable time. + EXPECT_TRUE(SetCookie(cm.get(), https_www_bar_.url(), + "__Host-C=D; secure; path=/; partitioned; max-age=1", + cookie_partition_key)); + + CookieList cookies = + GetAllCookiesForURL(cm.get(), https_www_bar_.url(), + CookiePartitionKeyCollection(cookie_partition_key)); + EXPECT_EQ(2u, cookies.size()); + + // Sleep for entire Max-Age of the second cookie. + base::PlatformThread::Sleep(base::Seconds(1)); + + cookies = + GetAllCookiesForURL(cm.get(), https_www_bar_.url(), + CookiePartitionKeyCollection(cookie_partition_key)); + EXPECT_EQ(1u, cookies.size()); +} + // Tests importing from a persistent cookie store that contains duplicate // equivalent cookies. This situation should be handled by removing the // duplicate cookie (both from the in-memory cache, and from the backing store). // // This is a regression test for: http://crbug.com/17855. TEST_F(CookieMonsterTest, DontImportDuplicateCookies) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); // We will fill some initial cookies into the PersistentCookieStore, // to simulate a database with 4 duplicates. Note that we need to @@ -2304,8 +2335,8 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) { // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); // Verify that duplicates were not imported for path "/". // (If this had failed, GetCookies() would have also returned X=1, X=2, X=4). @@ -2349,9 +2380,9 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies_PartitionedCookies) { Time::Now() + base::Days(1), absl::nullopt, cookie_partition_key); initial_cookies.push_back(std::move(cc)); - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); store->SetLoadExpectation(true, std::move(initial_cookies)); @@ -2372,7 +2403,7 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies_PartitionedCookies) { // // This is a regression test for: http://crbug.com/43188. TEST_F(CookieMonsterTest, ImportDuplicateCreationTimes) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); Time now(Time::Now()); Time earlier(now - base::Days(1)); @@ -2403,8 +2434,8 @@ TEST_F(CookieMonsterTest, ImportDuplicateCreationTimes) { // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); CookieList list(GetAllCookies(cm.get())); EXPECT_EQ(2U, list.size()); @@ -2417,7 +2448,7 @@ TEST_F(CookieMonsterTest, ImportDuplicateCreationTimes) { } TEST_F(CookieMonsterTest, ImportDuplicateCreationTimes_PartitionedCookies) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); Time now(Time::Now()); Time earlier(now - base::Days(1)); @@ -2461,8 +2492,8 @@ TEST_F(CookieMonsterTest, ImportDuplicateCreationTimes_PartitionedCookies) { // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); CookieList list(GetAllCookies(cm.get())); EXPECT_EQ(2U, list.size()); @@ -2533,8 +2564,7 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) { // Store details for cookies transforming through the backing store interface. base::Time current(base::Time::Now()); - scoped_refptr<MockSimplePersistentCookieStore> store( - new MockSimplePersistentCookieStore); + auto store = base::MakeRefCounted<MockSimplePersistentCookieStore>(); base::Time expires(base::Time::Now() + base::Seconds(100)); const CookiesInputInfo input_info[] = { @@ -2551,8 +2581,8 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) { // Create new cookies and flush them to the store. { - std::unique_ptr<CookieMonster> cmout(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cmout = std::make_unique<CookieMonster>( + store.get(), net::NetLog::Get(), kFirstPartySetsDefault); for (const auto& cookie : input_info) { EXPECT_TRUE(SetCanonicalCookie( cmout.get(), @@ -2571,8 +2601,8 @@ TEST_F(CookieMonsterTest, BackingStoreCommunication) { // Create a new cookie monster and make sure that everything is correct { - std::unique_ptr<CookieMonster> cmin(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cmin = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); CookieList cookies(GetAllCookies(cmin.get())); ASSERT_EQ(2u, cookies.size()); // Ordering is path length, then creation time. So second cookie @@ -2777,10 +2807,10 @@ TEST_F(CookieMonsterTest, GarbageCollectWithSecureCookiesOnly) { TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) { const GURL kUrl = GURL(kTopLevelDomainPlus1); - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); store->set_store_load_commands(true); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); auto cookie = CanonicalCookie::Create( kUrl, "a=b", base::Time::Now(), absl::nullopt /* server_time */, @@ -2827,10 +2857,10 @@ TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) { TEST_F(CookieMonsterTest, WhileLoadingDeleteAllGetForURL) { const GURL kUrl = GURL(kTopLevelDomainPlus1); - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); store->set_store_load_commands(true); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); ResultSavingCookieCallback<uint32_t> delete_callback; cm->DeleteAllAsync(delete_callback.MakeCallback()); @@ -2867,10 +2897,10 @@ TEST_F(CookieMonsterTest, WhileLoadingDeleteAllGetForURL) { TEST_F(CookieMonsterTest, WhileLoadingGetAllSetGetAll) { const GURL kUrl = GURL(kTopLevelDomainPlus1); - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); store->set_store_load_commands(true); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); GetAllCookiesCallback get_cookies_callback1; cm->GetAllCookiesAsync(get_cookies_callback1.MakeCallback()); @@ -2918,10 +2948,10 @@ void RunClosureOnAllCookiesReceived(base::OnceClosure closure, TEST_F(CookieMonsterTest, CheckOrderOfCookieTaskQueueWhenLoadingCompletes) { const GURL kUrl = GURL(kTopLevelDomainPlus1); - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); store->set_store_load_commands(true); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); // Get all cookies task that queues a task to set a cookie when executed. auto cookie = CanonicalCookie::Create( @@ -3016,7 +3046,7 @@ TEST_F(CookieMonsterTest, FlushStore) { } TEST_F(CookieMonsterTest, SetAllCookies) { - scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto store = base::MakeRefCounted<FlushablePersistentStore>(); auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), kFirstPartySetsDefault); cm->SetPersistSessionCookies(true); @@ -3088,7 +3118,7 @@ TEST_F(CookieMonsterTest, SetAllCookies) { // Check that DeleteAll does flush (as a quick check that flush_count() works). TEST_F(CookieMonsterTest, DeleteAll) { - scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto store = base::MakeRefCounted<FlushablePersistentStore>(); auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), kFirstPartySetsDefault); cm->SetPersistSessionCookies(true); @@ -3162,9 +3192,9 @@ TEST_F(CookieMonsterTest, InvalidExpiryTime) { // Test that CookieMonster writes session cookies into the underlying // CookieStore if the "persist session cookies" option is on. TEST_F(CookieMonsterTest, PersistSessionCookies) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); cm->SetPersistSessionCookies(true); // All cookies set with SetCookie are session cookies. @@ -3200,9 +3230,9 @@ TEST_F(CookieMonsterTest, PersistSessionCookies) { // Test the commands sent to the persistent cookie store. TEST_F(CookieMonsterTest, PersisentCookieStorageTest) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); // Add a cookie. EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), @@ -3251,7 +3281,7 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { const std::string domain("host"); const std::string path("/path"); - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies; @@ -3300,8 +3330,8 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { // Inject our initial cookies into the mock PersistentCookieStore. store->SetLoadExpectation(true, std::move(initial_cookies)); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); EXPECT_EQ("foo=bar; hello=world", GetCookies(cm.get(), url, @@ -3313,9 +3343,9 @@ TEST_F(CookieMonsterTest, CookieSourceHistogram) { base::HistogramTester histograms; const std::string cookie_source_histogram = "Cookie.CookieSourceScheme"; - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); histograms.ExpectTotalCount(cookie_source_histogram, 0); @@ -3324,21 +3354,21 @@ TEST_F(CookieMonsterTest, CookieSourceHistogram) { histograms.ExpectTotalCount(cookie_source_histogram, 1); histograms.ExpectBucketCount( cookie_source_histogram, - CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, 1); + CookieMonster::CookieSource::kSecureCookieCryptographicScheme, 1); // Set a non-secure cookie on a cryptographic scheme. EXPECT_TRUE(SetCookie(cm.get(), https_www_foo_.url(), "C=D; path=/;")); histograms.ExpectTotalCount(cookie_source_histogram, 2); histograms.ExpectBucketCount( cookie_source_histogram, - CookieMonster::COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, 1); + CookieMonster::CookieSource::kNonsecureCookieCryptographicScheme, 1); // Set a secure cookie on a non-cryptographic scheme. EXPECT_FALSE(SetCookie(cm.get(), http_www_foo_.url(), "D=E; path=/; Secure")); histograms.ExpectTotalCount(cookie_source_histogram, 2); histograms.ExpectBucketCount( cookie_source_histogram, - CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, 0); + CookieMonster::CookieSource::kSecureCookieNoncryptographicScheme, 0); // Overwrite a secure cookie (set by a cryptographic scheme) on a // non-cryptographic scheme. @@ -3346,10 +3376,10 @@ TEST_F(CookieMonsterTest, CookieSourceHistogram) { histograms.ExpectTotalCount(cookie_source_histogram, 2); histograms.ExpectBucketCount( cookie_source_histogram, - CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, 1); + CookieMonster::CookieSource::kSecureCookieCryptographicScheme, 1); histograms.ExpectBucketCount( cookie_source_histogram, - CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, 0); + CookieMonster::CookieSource::kSecureCookieNoncryptographicScheme, 0); // Test that attempting to clear a secure cookie on a http:// URL does // nothing. @@ -3368,7 +3398,7 @@ TEST_F(CookieMonsterTest, CookieSourceHistogram) { histograms.ExpectTotalCount(cookie_source_histogram, 4); histograms.ExpectBucketCount( cookie_source_histogram, - CookieMonster::COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, 1); + CookieMonster::CookieSource::kNonsecureCookieNoncryptographicScheme, 1); } // Test that inserting the first cookie for a key and deleting the last cookie @@ -3377,7 +3407,7 @@ TEST_F(CookieMonsterTest, NumKeysHistogram) { const char kHistogramName[] = "Cookie.NumKeys"; // Test loading cookies from store. - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies; initial_cookies.push_back(CanonicalCookie::Create( GURL("http://domain1.test"), "A=1", base::Time::Now(), @@ -3470,6 +3500,57 @@ TEST_F(CookieMonsterTest, NumKeysHistogram) { } } +TEST_F(CookieMonsterTest, MaxSameSiteNoneCookiesPerKey) { + const char kHistogramName[] = "Cookie.MaxSameSiteNoneCookiesPerKey"; + + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); + ASSERT_EQ(0u, GetAllCookies(cm.get()).size()); + + { // Only SameSite cookies should not log a sample. + base::HistogramTester histogram_tester; + + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain1.test"), + "A=1;SameSite=Lax", + CookieOptions::MakeAllInclusive())); + ASSERT_EQ(1u, GetAllCookies(cm.get()).size()); + ASSERT_TRUE(cm->DoRecordPeriodicStatsForTesting()); + histogram_tester.ExpectUniqueSample(kHistogramName, 0 /* sample */, + 1 /* count */); + } + + { // SameSite=None cookie should log a sample. + base::HistogramTester histogram_tester; + + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain1.test"), + "B=2;SameSite=None;Secure", + CookieOptions::MakeAllInclusive())); + ASSERT_EQ(2u, GetAllCookies(cm.get()).size()); + ASSERT_TRUE(cm->DoRecordPeriodicStatsForTesting()); + histogram_tester.ExpectUniqueSample(kHistogramName, 1 /* sample */, + 1 /* count */); + } + + { // Should log the maximum number of SameSite=None cookies. + base::HistogramTester histogram_tester; + + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain2.test"), + "A=1;SameSite=None;Secure", + CookieOptions::MakeAllInclusive())); + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain2.test"), + "B=2;SameSite=None;Secure", + CookieOptions::MakeAllInclusive())); + ASSERT_TRUE(CreateAndSetCookie(cm.get(), GURL("https://domain3.test"), + "A=1;SameSite=None;Secure", + CookieOptions::MakeAllInclusive())); + ASSERT_EQ(5u, GetAllCookies(cm.get()).size()); + ASSERT_TRUE(cm->DoRecordPeriodicStatsForTesting()); + histogram_tester.ExpectUniqueSample(kHistogramName, 2 /* sample */, + 1 /* count */); + } +} + // Test that localhost URLs can set and get secure cookies, even if // non-cryptographic. TEST_F(CookieMonsterTest, SecureCookieLocalhost) { @@ -3547,9 +3628,9 @@ TEST_F(CookieMonsterTest, SecureCookieLocalhost) { } TEST_F(CookieMonsterTest, MaybeDeleteEquivalentCookieAndUpdateStatus) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); // Set a secure, httponly cookie from a secure origin auto preexisting_cookie = CanonicalCookie::Create( @@ -3654,9 +3735,9 @@ TEST_F(CookieMonsterTest, MaybeDeleteEquivalentCookieAndUpdateStatus) { TEST_F(CookieMonsterTest, MaybeDeleteEquivalentCookieAndUpdateStatus_PartitionedCookies) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); // Test adding two cookies with the same name, domain, and path but different // partition keys. @@ -3698,9 +3779,9 @@ TEST_F(CookieMonsterTest, // Test skipping a cookie in MaybeDeleteEquivalentCookieAndUpdateStatus for // multiple reasons (Secure and HttpOnly). TEST_F(CookieMonsterTest, SkipDontOverwriteForMultipleReasons) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); // Set a secure, httponly cookie from a secure origin auto preexisting_cookie = CanonicalCookie::Create( @@ -3737,9 +3818,9 @@ TEST_F(CookieMonsterTest, SkipDontOverwriteForMultipleReasons) { // Test that when we check for equivalent cookies, we don't remove any if the // cookie should not be set. TEST_F(CookieMonsterTest, DontDeleteEquivalentCookieIfSetIsRejected) { - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); auto preexisting_cookie = CanonicalCookie::Create( http_www_foo_.url(), "cookie=foo", base::Time::Now(), @@ -4387,8 +4468,8 @@ TEST_F(CookieMonsterTest, EvictSecureCookies) { // Tests that strict secure cookies doesn't trip equivalent cookie checks // accidentally. Regression test for https://crbug.com/569943. TEST_F(CookieMonsterTest, EquivalentCookies) { - std::unique_ptr<CookieMonster> cm( - new CookieMonster(nullptr, nullptr, kFirstPartySetsDefault)); + auto cm = + std::make_unique<CookieMonster>(nullptr, nullptr, kFirstPartySetsDefault); GURL http_url("http://www.foo.com"); GURL http_superdomain_url("http://foo.com"); GURL https_url("https://www.foo.com"); @@ -4463,7 +4544,7 @@ TEST_F(CookieMonsterTest, DeleteDuplicateCTime) { // This gets tested a few times with different deletion target, to make sure // that the implementation doesn't just happen to pick the right one because // of implementation details. - for (size_t run = 0; run < std::size(kNames); ++run) { + for (const auto* name : kNames) { CookieMonster cm(nullptr, nullptr, kFirstPartySetsDefault); Time now = Time::Now(); GURL url("http://www.example.com"); @@ -4480,7 +4561,7 @@ TEST_F(CookieMonsterTest, DeleteDuplicateCTime) { ASSERT_EQ(all_cookies.size(), std::size(kNames)); for (size_t i = 0; i < std::size(kNames); ++i) { const CanonicalCookie& cookie = all_cookies[i]; - if (cookie.Name() == kNames[run]) { + if (cookie.Name() == name) { EXPECT_TRUE(DeleteCanonicalCookie(&cm, cookie)); } } @@ -4491,7 +4572,7 @@ TEST_F(CookieMonsterTest, DeleteDuplicateCTime) { ASSERT_EQ(all_cookies.size(), std::size(kNames) - 1); for (size_t i = 0; i < std::size(kNames) - 1; ++i) { const CanonicalCookie& cookie = all_cookies[i]; - EXPECT_NE(cookie.Name(), kNames[run]); + EXPECT_NE(cookie.Name(), name); } } } @@ -4639,9 +4720,7 @@ TEST_F(CookieMonsterTest, CookiesWithoutSameSiteMustBeSecure) { {true, "A=B", // not-recently-set session cookie. CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE, kLongAge}, // Cookie set from a secure URL with SameSite=None and Secure is set. - {true, "A=B; SameSite=None; Secure", - CookieInclusionStatus( - CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED), + {true, "A=B; SameSite=None; Secure", CookieInclusionStatus(), CookieEffectiveSameSite::NO_RESTRICTION}, // Cookie set from a secure URL with SameSite=None but not specifying // Secure is rejected. @@ -4699,9 +4778,10 @@ class CookieMonsterNotificationTest : public CookieMonsterTest { public: CookieMonsterNotificationTest() : test_url_("http://www.foo.com/foo"), - store_(new MockPersistentCookieStore), - monster_( - new CookieMonster(store_.get(), nullptr, kFirstPartySetsDefault)) {} + store_(base::MakeRefCounted<MockPersistentCookieStore>()), + monster_(std::make_unique<CookieMonster>(store_.get(), + nullptr, + kFirstPartySetsDefault)) {} ~CookieMonsterNotificationTest() override = default; @@ -4729,7 +4809,7 @@ void RecordCookieChanges(std::vector<CanonicalCookie>* out_cookies, TEST_F(CookieMonsterNotificationTest, NoNotificationOnLoad) { // Create a persistent store that will not synchronously satisfy the // loading requirement. - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); store->set_store_load_commands(true); // Bind it to a CookieMonster @@ -4983,9 +5063,9 @@ TEST_F(CookieMonsterTest, CookieDomainSetHistogram) { base::HistogramTester histograms; const char kHistogramName[] = "Cookie.DomainSet"; - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); histograms.ExpectTotalCount(kHistogramName, 0); @@ -5012,9 +5092,9 @@ TEST_F(CookieMonsterTest, CookiePortReadHistogram) { const char kHistogramName[] = "Cookie.Port.Read.RemoteHost"; const char kHistogramNameLocal[] = "Cookie.Port.Read.Localhost"; - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); histograms.ExpectTotalCount(kHistogramName, 0); @@ -5066,9 +5146,9 @@ TEST_F(CookieMonsterTest, CookiePortSetHistogram) { const char kHistogramName[] = "Cookie.Port.Set.RemoteHost"; const char kHistogramNameLocal[] = "Cookie.Port.Set.Localhost"; - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); histograms.ExpectTotalCount(kHistogramName, 0); @@ -5121,9 +5201,9 @@ TEST_F(CookieMonsterTest, CookiePortReadDiffersFromSetHistogram) { const char kHistogramNameDomainSet[] = "Cookie.Port.ReadDiffersFromSet.DomainSet"; - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); histograms.ExpectTotalCount(kHistogramName, 0); @@ -5221,9 +5301,9 @@ TEST_F(CookieMonsterTest, CookieSourceSchemeNameHistogram) { base::HistogramTester histograms; const char kHistogramName[] = "Cookie.CookieSourceSchemeName"; - scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::unique_ptr<CookieMonster> cm(new CookieMonster( - store.get(), net::NetLog::Get(), kFirstPartySetsDefault)); + auto store = base::MakeRefCounted<MockPersistentCookieStore>(); + auto cm = std::make_unique<CookieMonster>(store.get(), net::NetLog::Get(), + kFirstPartySetsDefault); histograms.ExpectTotalCount(kHistogramName, 0); @@ -5302,23 +5382,22 @@ class FirstPartySetEnabledCookieMonsterTest : public CookieMonsterTest { }; TEST_F(FirstPartySetEnabledCookieMonsterTest, RecordsPeriodicFPSSizes) { + net::SchemefulSite owner1(GURL("https://owner1.test")); + net::SchemefulSite owner2(GURL("https://owner2.test")); + net::SchemefulSite member1(GURL("https://member1.test")); + net::SchemefulSite member2(GURL("https://member2.test")); + net::SchemefulSite member3(GURL("https://member3.test")); + net::SchemefulSite member4(GURL("https://member4.test")); + access_delegate_->SetFirstPartySets({ - { - SchemefulSite(GURL("https://owner1.test")), - { - SchemefulSite(GURL("https://owner1.test")), - SchemefulSite(GURL("https://member1.test")), - SchemefulSite(GURL("https://member2.test")), - }, - }, - { - SchemefulSite(GURL("https://owner2.test")), - { - SchemefulSite(GURL("https://owner2.test")), - SchemefulSite(GURL("https://member3.test")), - SchemefulSite(GURL("https://member4.test")), - }, - }, + {owner1, + net::FirstPartySetEntry(owner1, net::SiteType::kPrimary, absl::nullopt)}, + {member1, net::FirstPartySetEntry(owner1, net::SiteType::kAssociated, 0)}, + {member2, net::FirstPartySetEntry(owner1, net::SiteType::kAssociated, 1)}, + {owner2, + net::FirstPartySetEntry(owner2, net::SiteType::kPrimary, absl::nullopt)}, + {member3, net::FirstPartySetEntry(owner2, net::SiteType::kAssociated, 0)}, + {member4, net::FirstPartySetEntry(owner2, net::SiteType::kAssociated, 1)}, }); ASSERT_TRUE(SetCookie(cm(), GURL("https://owner1.test"), kValidCookieLine)); @@ -5337,8 +5416,11 @@ TEST_F(FirstPartySetEnabledCookieMonsterTest, RecordsPeriodicFPSSizes) { base::HistogramTester histogram_tester; EXPECT_TRUE(cm()->DoRecordPeriodicStatsForTesting()); EXPECT_THAT(histogram_tester.GetAllSamples("Cookie.PerFirstPartySetCount"), - testing::ElementsAre(base::Bucket(2 /* min */, 1 /* samples */), - base::Bucket(3 /* min */, 1 /* samples */))); + testing::ElementsAre( // + // owner2.test & member3.test + base::Bucket(2 /* min */, 1 /* samples */), + // owner1.test, member1.test, & member2.test + base::Bucket(3 /* min */, 1 /* samples */))); } TEST_F(CookieMonsterTest, GetAllCookiesForURLNonce) { @@ -5599,7 +5681,7 @@ INSTANTIATE_TEST_SUITE_P(/* no label */, // creation and expiry dates expected given whether or not clamping is on. TEST_P(CookieMonsterWithClampingTest, FromStorageCookieCreated300DaysAgoThenUpdatedNow) { - scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto store = base::MakeRefCounted<FlushablePersistentStore>(); auto cookie_monster = std::make_unique<CookieMonster>( store.get(), net::NetLog::Get(), kFirstPartySetsDefault); cookie_monster->SetPersistSessionCookies(true); @@ -5654,7 +5736,7 @@ TEST_P(CookieMonsterWithClampingTest, // creation and expiry dates expected given whether or not clamping is on. TEST_P(CookieMonsterWithClampingTest, FromStorageCookieCreated500DaysAgoThenUpdatedNow) { - scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto store = base::MakeRefCounted<FlushablePersistentStore>(); auto cookie_monster = std::make_unique<CookieMonster>( store.get(), net::NetLog::Get(), kFirstPartySetsDefault); cookie_monster->SetPersistSessionCookies(true); @@ -5709,7 +5791,7 @@ TEST_P(CookieMonsterWithClampingTest, // expected given whether or not clamping is on. TEST_P(CookieMonsterWithClampingTest, SanitizedCookieCreated300DaysAgoThenUpdatedNow) { - scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto store = base::MakeRefCounted<FlushablePersistentStore>(); auto cookie_monster = std::make_unique<CookieMonster>( store.get(), net::NetLog::Get(), kFirstPartySetsDefault); cookie_monster->SetPersistSessionCookies(true); @@ -5774,7 +5856,7 @@ TEST_P(CookieMonsterWithClampingTest, // expected given whether or not clamping is on. TEST_P(CookieMonsterWithClampingTest, SanitizedCookieCreated500DaysAgoThenUpdatedNow) { - scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); + auto store = base::MakeRefCounted<FlushablePersistentStore>(); auto cookie_monster = std::make_unique<CookieMonster>( store.get(), net::NetLog::Get(), kFirstPartySetsDefault); cookie_monster->SetPersistSessionCookies(true); diff --git a/chromium/net/cookies/cookie_partition_key_collection.cc b/chromium/net/cookies/cookie_partition_key_collection.cc index 907a4e68356..9a336885d0b 100644 --- a/chromium/net/cookies/cookie_partition_key_collection.cc +++ b/chromium/net/cookies/cookie_partition_key_collection.cc @@ -14,20 +14,21 @@ #include "net/base/schemeful_site.h" #include "net/cookies/cookie_access_delegate.h" #include "net/cookies/cookie_partition_key.h" +#include "net/cookies/first_party_set_entry.h" namespace net { namespace { -CookiePartitionKeyCollection TransformWithFirstPartySetOwners( +CookiePartitionKeyCollection TransformWithFirstPartySetEntries( const base::flat_set<CookiePartitionKey>& keys, - base::flat_map<SchemefulSite, SchemefulSite> sites_to_owners) { + base::flat_map<SchemefulSite, FirstPartySetEntry> sites_to_entries) { std::vector<CookiePartitionKey> canonicalized_keys; canonicalized_keys.reserve(keys.size()); for (const CookiePartitionKey& key : keys) { - const auto first_party_set_owner_iter = sites_to_owners.find(key.site()); + const auto it = sites_to_entries.find(key.site()); canonicalized_keys.push_back( - !key.nonce() && first_party_set_owner_iter != sites_to_owners.end() - ? CookiePartitionKey::FromWire(first_party_set_owner_iter->second) + !key.nonce() && it != sites_to_entries.end() + ? CookiePartitionKey::FromWire(it->second.primary()) : key); } return CookiePartitionKeyCollection(canonicalized_keys); @@ -80,15 +81,15 @@ CookiePartitionKeyCollection::FirstPartySetify( } if (sites.empty()) return *this; - absl::optional<base::flat_map<SchemefulSite, SchemefulSite>> - maybe_sites_to_owners = cookie_access_delegate->FindFirstPartySetOwners( + absl::optional<base::flat_map<SchemefulSite, FirstPartySetEntry>> + maybe_sites_to_entries = cookie_access_delegate->FindFirstPartySetOwners( sites, - base::BindOnce(&TransformWithFirstPartySetOwners, PartitionKeys()) + base::BindOnce(&TransformWithFirstPartySetEntries, PartitionKeys()) .Then(std::move(callback))); - if (maybe_sites_to_owners.has_value()) - return TransformWithFirstPartySetOwners(PartitionKeys(), - maybe_sites_to_owners.value()); + if (maybe_sites_to_entries.has_value()) + return TransformWithFirstPartySetEntries(PartitionKeys(), + maybe_sites_to_entries.value()); return absl::nullopt; } diff --git a/chromium/net/cookies/cookie_partition_key_collection_unittest.cc b/chromium/net/cookies/cookie_partition_key_collection_unittest.cc index 25b5b155504..01a9bad3d59 100644 --- a/chromium/net/cookies/cookie_partition_key_collection_unittest.cc +++ b/chromium/net/cookies/cookie_partition_key_collection_unittest.cc @@ -112,10 +112,12 @@ TEST(CookiePartitionKeyCollectionTest, FirstPartySetify) { CookiePartitionKey::FromURLForTesting(kNonMemberURL); TestCookieAccessDelegate delegate; - base::flat_map<SchemefulSite, std::set<SchemefulSite>> first_party_sets; - first_party_sets.insert(std::make_pair( - kOwnerSite, std::set<SchemefulSite>({kOwnerSite, kMemberSite}))); - delegate.SetFirstPartySets(first_party_sets); + delegate.SetFirstPartySets({ + {kOwnerSite, net::FirstPartySetEntry(kOwnerSite, net::SiteType::kPrimary, + absl::nullopt)}, + {kMemberSite, + net::FirstPartySetEntry(kOwnerSite, net::SiteType::kAssociated, 0)}, + }); CookiePartitionKeyCollection empty_key_collection; EXPECT_TRUE( diff --git a/chromium/net/cookies/cookie_partition_key_unittest.cc b/chromium/net/cookies/cookie_partition_key_unittest.cc index 8a68fcf314f..4bbb7cfdc17 100644 --- a/chromium/net/cookies/cookie_partition_key_unittest.cc +++ b/chromium/net/cookies/cookie_partition_key_unittest.cc @@ -3,33 +3,39 @@ // found in the LICENSE file. #include <string> +#include <tuple> -#include "net/cookies/cookie_partition_key.h" #include "base/test/scoped_feature_list.h" #include "net/base/features.h" #include "net/cookies/cookie_constants.h" +#include "net/cookies/cookie_partition_key.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { -class CookiePartitionKeyTest : public testing::TestWithParam<bool> { +class CookiePartitionKeyTest + : public testing::TestWithParam<std::tuple<bool, bool>> { protected: // testing::Test void SetUp() override { - if (PartitionedCookiesEnabled()) - scoped_feature_list_.InitAndEnableFeature(features::kPartitionedCookies); - testing::TestWithParam<bool>::SetUp(); + scoped_feature_list_[0].InitWithFeatureState(features::kPartitionedCookies, + PartitionedCookiesEnabled()); + scoped_feature_list_[1].InitWithFeatureState( + features::kNoncedPartitionedCookies, NoncedPartitionedCookiesEnabled()); } - bool PartitionedCookiesEnabled() { return GetParam(); } + bool PartitionedCookiesEnabled() { return std::get<0>(GetParam()); } + bool NoncedPartitionedCookiesEnabled() { return std::get<1>(GetParam()); } private: - base::test::ScopedFeatureList scoped_feature_list_; + base::test::ScopedFeatureList scoped_feature_list_[2]; }; INSTANTIATE_TEST_SUITE_P(/* no label */, CookiePartitionKeyTest, - testing::Bool()); + ::testing::Values(std::make_tuple(false, false), + std::make_tuple(false, true), + std::make_tuple(true, true))); TEST_P(CookiePartitionKeyTest, Serialization) { base::UnguessableToken nonce = base::UnguessableToken::Create(); @@ -261,7 +267,8 @@ TEST_P(CookiePartitionKeyTest, Equality_WithNonce) { EXPECT_NE(nonce1, nonce2); auto key1 = CookiePartitionKey::FromNetworkIsolationKey( NetworkIsolationKey(top_level_site, frame_site, &nonce1)); - bool partitioned_cookies_enabled = PartitionedCookiesEnabled(); + bool partitioned_cookies_enabled = + PartitionedCookiesEnabled() || NoncedPartitionedCookiesEnabled(); EXPECT_EQ(partitioned_cookies_enabled, key1.has_value()); if (!partitioned_cookies_enabled) return; diff --git a/chromium/net/cookies/cookie_store_test_callbacks.h b/chromium/net/cookies/cookie_store_test_callbacks.h index ee319423e68..2387a94bbcb 100644 --- a/chromium/net/cookies/cookie_store_test_callbacks.h +++ b/chromium/net/cookies/cookie_store_test_callbacks.h @@ -62,8 +62,7 @@ class CookieCallback { template <typename T> class ResultSavingCookieCallback : public CookieCallback { public: - ResultSavingCookieCallback() { - } + ResultSavingCookieCallback() = default; explicit ResultSavingCookieCallback(base::Thread* run_in_thread) : CookieCallback(run_in_thread) { } diff --git a/chromium/net/cookies/cookie_store_test_helpers.cc b/chromium/net/cookies/cookie_store_test_helpers.cc index 31c95384063..3e7e5c4fb45 100644 --- a/chromium/net/cookies/cookie_store_test_helpers.cc +++ b/chromium/net/cookies/cookie_store_test_helpers.cc @@ -72,9 +72,10 @@ DelayedCookieMonsterChangeDispatcher::AddCallbackForAllChanges( } DelayedCookieMonster::DelayedCookieMonster() - : cookie_monster_(new CookieMonster(nullptr /* store */, - nullptr /* netlog */, - false /* first_party_sets_enabled */)), + : cookie_monster_(std::make_unique<CookieMonster>( + nullptr /* store */, + nullptr /* netlog */, + false /* first_party_sets_enabled */)), result_(CookieAccessResult(CookieInclusionStatus( CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE))) {} diff --git a/chromium/net/cookies/cookie_util.cc b/chromium/net/cookies/cookie_util.cc index d91b562fc0f..13c70c26a33 100644 --- a/chromium/net/cookies/cookie_util.cc +++ b/chromium/net/cookies/cookie_util.cc @@ -27,6 +27,7 @@ #include "net/base/url_util.h" #include "net/cookies/cookie_access_delegate.h" #include "net/cookies/cookie_constants.h" +#include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_options.h" #include "net/cookies/first_party_set_metadata.h" @@ -35,8 +36,7 @@ #include "url/gurl.h" #include "url/url_constants.h" -namespace net { -namespace cookie_util { +namespace net::cookie_util { namespace { @@ -306,11 +306,16 @@ std::string GetEffectiveDomain(const std::string& scheme, bool GetCookieDomainWithString(const GURL& url, const std::string& domain_string, + CookieInclusionStatus& status, std::string* result) { // Disallow non-ASCII domain names. - if (base::FeatureList::IsEnabled(features::kCookieDomainRejectNonASCII) && - !base::IsStringASCII(domain_string)) { - return false; + if (!base::IsStringASCII(domain_string)) { + if (base::FeatureList::IsEnabled(features::kCookieDomainRejectNonASCII)) { + status.AddExclusionReason( + CookieInclusionStatus::EXCLUDE_DOMAIN_NON_ASCII); + return false; + } + status.AddWarningReason(CookieInclusionStatus::WARN_DOMAIN_NON_ASCII); } const std::string url_host(url.host()); @@ -614,12 +619,12 @@ void ParseRequestCookieLine(const std::string& header_value, std::string SerializeRequestCookieLine( const ParsedRequestCookies& parsed_cookies) { std::string buffer; - for (auto i = parsed_cookies.begin(); i != parsed_cookies.end(); ++i) { + for (const auto& parsed_cookie : parsed_cookies) { if (!buffer.empty()) buffer.append("; "); - buffer.append(i->first.begin(), i->first.end()); + buffer.append(parsed_cookie.first.begin(), parsed_cookie.first.end()); buffer.push_back('='); - buffer.append(i->second.begin(), i->second.end()); + buffer.append(parsed_cookie.second.begin(), parsed_cookie.second.end()); } return buffer; } @@ -891,5 +896,4 @@ NET_EXPORT void DCheckIncludedAndExcludedCookieLists( base::ranges::is_sorted(included_cookies, CookieWithAccessResultSorter)); } -} // namespace cookie_util -} // namespace net +} // namespace net::cookie_util diff --git a/chromium/net/cookies/cookie_util.h b/chromium/net/cookies/cookie_util.h index c869e8fbc0c..27dd1705652 100644 --- a/chromium/net/cookies/cookie_util.h +++ b/chromium/net/cookies/cookie_util.h @@ -27,6 +27,7 @@ namespace net { class IsolationInfo; class SchemefulSite; class CookieAccessDelegate; +class CookieInclusionStatus; namespace cookie_util { @@ -63,6 +64,7 @@ NET_EXPORT std::string GetEffectiveDomain(const std::string& scheme, // begin with a '.' character. NET_EXPORT bool GetCookieDomainWithString(const GURL& url, const std::string& domain_string, + CookieInclusionStatus& status, std::string* result); // Returns true if a domain string represents a host-only cookie, diff --git a/chromium/net/cookies/cookie_util_unittest.cc b/chromium/net/cookies/cookie_util_unittest.cc index 6ab824e2666..bd028aa709f 100644 --- a/chromium/net/cookies/cookie_util_unittest.cc +++ b/chromium/net/cookies/cookie_util_unittest.cc @@ -209,26 +209,26 @@ TEST(CookieUtilTest, TestRequestCookieParsing) { std::vector<RequestCookieParsingTest> tests; // Simple case. - tests.push_back(RequestCookieParsingTest()); + tests.emplace_back(); tests.back().str = "key=value"; tests.back().parsed.push_back(std::make_pair(std::string("key"), std::string("value"))); // Multiple key/value pairs. - tests.push_back(RequestCookieParsingTest()); + tests.emplace_back(); tests.back().str = "key1=value1; key2=value2"; tests.back().parsed.push_back(std::make_pair(std::string("key1"), std::string("value1"))); tests.back().parsed.push_back(std::make_pair(std::string("key2"), std::string("value2"))); // Empty value. - tests.push_back(RequestCookieParsingTest()); + tests.emplace_back(); tests.back().str = "key=; otherkey=1234"; tests.back().parsed.push_back(std::make_pair(std::string("key"), std::string())); tests.back().parsed.push_back(std::make_pair(std::string("otherkey"), std::string("1234"))); // Special characters (including equals signs) in value. - tests.push_back(RequestCookieParsingTest()); + tests.emplace_back(); tests.back().str = "key=; a2=s=(./&t=:&u=a#$; a3=+~"; tests.back().parsed.push_back(std::make_pair(std::string("key"), std::string())); @@ -237,7 +237,7 @@ TEST(CookieUtilTest, TestRequestCookieParsing) { tests.back().parsed.push_back(std::make_pair(std::string("a3"), std::string("+~"))); // Quoted value. - tests.push_back(RequestCookieParsingTest()); + tests.emplace_back(); tests.back().str = "key=\"abcdef\"; otherkey=1234"; tests.back().parsed.push_back(std::make_pair(std::string("key"), std::string("\"abcdef\""))); diff --git a/chromium/net/cookies/first_party_set_entry.cc b/chromium/net/cookies/first_party_set_entry.cc new file mode 100644 index 00000000000..0bb5cca7601 --- /dev/null +++ b/chromium/net/cookies/first_party_set_entry.cc @@ -0,0 +1,77 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cookies/first_party_set_entry.h" + +#include <tuple> + +#include "net/base/schemeful_site.h" + +namespace net { + +FirstPartySetEntry::SiteIndex::SiteIndex() = default; + +FirstPartySetEntry::SiteIndex::SiteIndex(uint32_t value) : value_(value) {} + +bool FirstPartySetEntry::SiteIndex::operator==(const SiteIndex& other) const { + return value_ == other.value_; +} + +FirstPartySetEntry::FirstPartySetEntry() = default; + +FirstPartySetEntry::FirstPartySetEntry( + SchemefulSite primary, + SiteType site_type, + absl::optional<FirstPartySetEntry::SiteIndex> site_index) + : primary_(primary), site_type_(site_type), site_index_(site_index) { + if (site_type_ == SiteType::kPrimary) { + DCHECK(!site_index_.has_value()); + } +} + +FirstPartySetEntry::FirstPartySetEntry(SchemefulSite primary, + SiteType site_type, + uint32_t site_index) + : FirstPartySetEntry( + primary, + site_type, + absl::make_optional(FirstPartySetEntry::SiteIndex(site_index))) {} + +FirstPartySetEntry::FirstPartySetEntry(const FirstPartySetEntry&) = default; +FirstPartySetEntry& FirstPartySetEntry::operator=(const FirstPartySetEntry&) = + default; +FirstPartySetEntry::FirstPartySetEntry(FirstPartySetEntry&&) = default; +FirstPartySetEntry& FirstPartySetEntry::operator=(FirstPartySetEntry&&) = + default; + +FirstPartySetEntry::~FirstPartySetEntry() = default; + +bool FirstPartySetEntry::operator==(const FirstPartySetEntry& other) const { + return std::tie(primary_, site_type_, site_index_) == + std::tie(other.primary_, other.site_type_, other.site_index_); +} + +bool FirstPartySetEntry::operator!=(const FirstPartySetEntry& other) const { + return !(*this == other); +} + +std::ostream& operator<<(std::ostream& os, + const FirstPartySetEntry::SiteIndex& index) { + os << index.value(); + return os; +} + +std::ostream& operator<<(std::ostream& os, const FirstPartySetEntry& entry) { + os << "{" << entry.primary() << ", " << static_cast<int>(entry.site_type()) + << ", "; + if (entry.site_index().has_value()) { + os << entry.site_index().value(); + } else { + os << "{}"; + } + os << "}"; + return os; +} + +} // namespace net diff --git a/chromium/net/cookies/first_party_set_entry.h b/chromium/net/cookies/first_party_set_entry.h new file mode 100644 index 00000000000..d4a8b7e8d12 --- /dev/null +++ b/chromium/net/cookies/first_party_set_entry.h @@ -0,0 +1,84 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_COOKIES_FIRST_PARTY_SET_ENTRY_H_ +#define NET_COOKIES_FIRST_PARTY_SET_ENTRY_H_ + +#include "net/base/net_export.h" +#include "net/base/schemeful_site.h" + +namespace net { + +enum class SiteType { + // The First-Party Set declaration listed this site as the "primary" site for + // the set. + kPrimary, + // The First-Party Set declaration listed this site as an associated site in + // the set. + kAssociated, +}; + +// This class bundles together metadata associated with an entry in a +// First-Party Set. +class NET_EXPORT FirstPartySetEntry { + public: + class NET_EXPORT SiteIndex { + public: + SiteIndex(); + explicit SiteIndex(uint32_t value); + + bool operator==(const SiteIndex& other) const; + + uint32_t value() const { return value_; } + + private: + uint32_t value_; + }; + + FirstPartySetEntry(); + // `primary` is the primary site in the First-Party Set associated with this + // entry. + FirstPartySetEntry(SchemefulSite primary, + SiteType site_type, + absl::optional<SiteIndex> site_index); + FirstPartySetEntry(SchemefulSite primary, + SiteType site_type, + uint32_t site_index); + + FirstPartySetEntry(const FirstPartySetEntry&); + FirstPartySetEntry& operator=(const FirstPartySetEntry&); + FirstPartySetEntry(FirstPartySetEntry&&); + FirstPartySetEntry& operator=(FirstPartySetEntry&&); + + ~FirstPartySetEntry(); + + bool operator==(const FirstPartySetEntry& other) const; + bool operator!=(const FirstPartySetEntry& other) const; + + const SchemefulSite& primary() const { return primary_; } + + SiteType site_type() const { return site_type_; } + + const absl::optional<SiteIndex>& site_index() const { return site_index_; } + + private: + // The primary site associated with this site's set. + SchemefulSite primary_; + // The type associated with this site. + SiteType site_type_; + // The index of this site in the set declaration, if a meaningful index + // exists. Primary sites do not have indices, nor do sites that were defined + // or affected by an enterprise policy set. + absl::optional<SiteIndex> site_index_; +}; + +NET_EXPORT std::ostream& operator<<( + std::ostream& os, + const FirstPartySetEntry::SiteIndex& site_index); +NET_EXPORT std::ostream& operator<<(std::ostream& os, + const FirstPartySetEntry& fpse); + +} // namespace net + +#endif // NET_COOKIES_FIRST_PARTY_SET_ENTRY_H_ diff --git a/chromium/net/cookies/first_party_set_metadata.cc b/chromium/net/cookies/first_party_set_metadata.cc index 60f1988bb0c..0937d897ee3 100644 --- a/chromium/net/cookies/first_party_set_metadata.cc +++ b/chromium/net/cookies/first_party_set_metadata.cc @@ -7,20 +7,18 @@ #include <tuple> #include "base/stl_util.h" -#include "net/cookies/cookie_constants.h" +#include "net/cookies/first_party_set_entry.h" namespace net { FirstPartySetMetadata::FirstPartySetMetadata() = default; FirstPartySetMetadata::FirstPartySetMetadata( const SamePartyContext& context, - const SchemefulSite* frame_owner, - const SchemefulSite* top_frame_owner, - FirstPartySetsContextType first_party_sets_context_type) + const FirstPartySetEntry* frame_entry, + const FirstPartySetEntry* top_frame_entry) : context_(context), - frame_owner_(base::OptionalFromPtr(frame_owner)), - top_frame_owner_(base::OptionalFromPtr(top_frame_owner)), - first_party_sets_context_type_(first_party_sets_context_type) {} + frame_entry_(base::OptionalFromPtr(frame_entry)), + top_frame_entry_(base::OptionalFromPtr(top_frame_entry)) {} FirstPartySetMetadata::FirstPartySetMetadata(FirstPartySetMetadata&&) = default; FirstPartySetMetadata& FirstPartySetMetadata::operator=( @@ -30,18 +28,15 @@ FirstPartySetMetadata::~FirstPartySetMetadata() = default; bool FirstPartySetMetadata::operator==( const FirstPartySetMetadata& other) const { - return std::tie(context_, frame_owner_, top_frame_owner_, - first_party_sets_context_type_) == - std::tie(other.context_, other.frame_owner_, other.top_frame_owner_, - other.first_party_sets_context_type_); + return std::tie(context_, frame_entry_, top_frame_entry_) == + std::tie(other.context_, other.frame_entry_, other.top_frame_entry_); } std::ostream& operator<<(std::ostream& os, const FirstPartySetMetadata& metadata) { os << "{" << metadata.context() << ", " - << base::OptionalOrNullptr(metadata.frame_owner()) << ", " - << base::OptionalOrNullptr(metadata.top_frame_owner()) << ", " - << static_cast<int>(metadata.first_party_sets_context_type()) << "}"; + << base::OptionalOrNullptr(metadata.frame_entry()) << ", " + << base::OptionalOrNullptr(metadata.top_frame_entry()) << "}"; return os; } diff --git a/chromium/net/cookies/first_party_set_metadata.h b/chromium/net/cookies/first_party_set_metadata.h index 1b6562d2713..5d54d5564ac 100644 --- a/chromium/net/cookies/first_party_set_metadata.h +++ b/chromium/net/cookies/first_party_set_metadata.h @@ -5,9 +5,8 @@ #ifndef NET_COOKIES_FIRST_PARTY_SET_METADATA_H_ #define NET_COOKIES_FIRST_PARTY_SET_METADATA_H_ -#include "base/stl_util.h" #include "net/base/net_export.h" -#include "net/base/schemeful_site.h" +#include "net/cookies/first_party_set_entry.h" #include "net/cookies/same_party_context.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -19,14 +18,12 @@ class NET_EXPORT FirstPartySetMetadata { public: FirstPartySetMetadata(); - // `frame_owner` and `top_frame_owner` must live for the duration of the ctor; + // `frame_entry` and `top_frame_entry` must live for the duration of the ctor; // nullptr indicates that there's no First-Party Set that's associated with // the current frame or the top frame, respectively, in the given context. - FirstPartySetMetadata( - const SamePartyContext& context, - const SchemefulSite* frame_owner, - const SchemefulSite* top_frame_owner, - FirstPartySetsContextType first_party_sets_context_type); + FirstPartySetMetadata(const SamePartyContext& context, + const FirstPartySetEntry* frame_entry, + const FirstPartySetEntry* top_frame_entry); FirstPartySetMetadata(FirstPartySetMetadata&&); FirstPartySetMetadata& operator=(FirstPartySetMetadata&&); @@ -39,23 +36,17 @@ class NET_EXPORT FirstPartySetMetadata { // Returns a optional<T>& instead of a T* so that operator== can be defined // more easily. - const absl::optional<SchemefulSite>& frame_owner() const { - return frame_owner_; + const absl::optional<FirstPartySetEntry>& frame_entry() const { + return frame_entry_; } - const absl::optional<SchemefulSite>& top_frame_owner() const { - return top_frame_owner_; - } - - FirstPartySetsContextType first_party_sets_context_type() const { - return first_party_sets_context_type_; + const absl::optional<FirstPartySetEntry>& top_frame_entry() const { + return top_frame_entry_; } private: SamePartyContext context_ = SamePartyContext(); - absl::optional<SchemefulSite> frame_owner_ = absl::nullopt; - absl::optional<SchemefulSite> top_frame_owner_ = absl::nullopt; - FirstPartySetsContextType first_party_sets_context_type_ = - FirstPartySetsContextType::kUnknown; + absl::optional<FirstPartySetEntry> frame_entry_ = absl::nullopt; + absl::optional<FirstPartySetEntry> top_frame_entry_ = absl::nullopt; }; NET_EXPORT std::ostream& operator<<(std::ostream& os, diff --git a/chromium/net/cookies/first_party_sets_context_config.cc b/chromium/net/cookies/first_party_sets_context_config.cc new file mode 100644 index 00000000000..e075437e0d3 --- /dev/null +++ b/chromium/net/cookies/first_party_sets_context_config.cc @@ -0,0 +1,24 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cookies/first_party_sets_context_config.h" + +namespace net { + +FirstPartySetsContextConfig::FirstPartySetsContextConfig(bool enabled) + : enabled_(enabled) {} + +FirstPartySetsContextConfig::FirstPartySetsContextConfig( + const FirstPartySetsContextConfig& other) = default; + +FirstPartySetsContextConfig::~FirstPartySetsContextConfig() = default; + +void FirstPartySetsContextConfig::SetCustomizations( + OverrideSets customizations) { + DCHECK(customizations_.empty()); + if (enabled_) + customizations_ = std::move(customizations); +} + +} // namespace net diff --git a/chromium/net/cookies/first_party_sets_context_config.h b/chromium/net/cookies/first_party_sets_context_config.h new file mode 100644 index 00000000000..eb7ee732549 --- /dev/null +++ b/chromium/net/cookies/first_party_sets_context_config.h @@ -0,0 +1,42 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_COOKIES_FIRST_PARTY_SETS_CONTEXT_CONFIG_H_ +#define NET_COOKIES_FIRST_PARTY_SETS_CONTEXT_CONFIG_H_ + +#include "base/containers/flat_map.h" +#include "net/base/schemeful_site.h" +#include "net/cookies/first_party_set_entry.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace net { + +// This struct bundles together the customized settings to First-Party Sets +// info in the given network context. +class NET_EXPORT FirstPartySetsContextConfig { + public: + using OverrideSets = + base::flat_map<SchemefulSite, absl::optional<FirstPartySetEntry>>; + + explicit FirstPartySetsContextConfig(bool enabled); + + FirstPartySetsContextConfig(const FirstPartySetsContextConfig& other); + + ~FirstPartySetsContextConfig(); + + bool is_enabled() const { return enabled_; } + + void SetCustomizations(OverrideSets customizations); + + const OverrideSets& customizations() const { return customizations_; } + + private: + bool enabled_ = true; + + OverrideSets customizations_; +}; + +} // namespace net + +#endif // NET_COOKIES_FIRST_PARTY_SETS_CONTEXT_CONFIG_H_
\ No newline at end of file diff --git a/chromium/net/cookies/parsed_cookie.cc b/chromium/net/cookies/parsed_cookie.cc index 17e64f13c9b..ebec5b77828 100644 --- a/chromium/net/cookies/parsed_cookie.cc +++ b/chromium/net/cookies/parsed_cookie.cc @@ -766,12 +766,7 @@ void ParsedCookie::SetupAttributes() { if (pairs_[i].first == kPathTokenName) { path_index_ = i; } else if (pairs_[i].first == kDomainTokenName) { - // Domain can be the empty string if the flag is enabled. - if (base::FeatureList::IsEnabled( - features::kCookieDomainAttributeEmptyString) || - pairs_[i].second != "") { - domain_index_ = i; - } + domain_index_ = i; } else if (pairs_[i].first == kExpiresTokenName) { expires_index_ = i; } else if (pairs_[i].first == kMaxAgeTokenName) { diff --git a/chromium/net/cookies/parsed_cookie_unittest.cc b/chromium/net/cookies/parsed_cookie_unittest.cc index a2a265fa0fa..2d6c4bf119a 100644 --- a/chromium/net/cookies/parsed_cookie_unittest.cc +++ b/chromium/net/cookies/parsed_cookie_unittest.cc @@ -877,10 +877,6 @@ TEST(ParsedCookieTest, SetAttributes) { // Setting the domain attribute to the empty string should be valid. TEST(ParsedCookieTest, EmptyDomainAttributeValid) { - // Enable the feature flag for this test. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - features::kCookieDomainAttributeEmptyString); ParsedCookie pc("name=value; domain="); EXPECT_TRUE(pc.IsValid()); } @@ -888,10 +884,6 @@ TEST(ParsedCookieTest, EmptyDomainAttributeValid) { // Set the domain attribute twice in a cookie line. If the second attribute's // value is empty, it should equal the empty string. TEST(ParsedCookieTest, MultipleDomainAttributes) { - // Enable the feature flag for this test. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - features::kCookieDomainAttributeEmptyString); ParsedCookie pc1("name=value; domain=foo.com; domain=bar.com"); EXPECT_EQ("bar.com", pc1.Domain()); ParsedCookie pc2("name=value; domain=foo.com; domain="); diff --git a/chromium/net/cookies/same_party_context.cc b/chromium/net/cookies/same_party_context.cc index 93a14af7f47..1e97738b649 100644 --- a/chromium/net/cookies/same_party_context.cc +++ b/chromium/net/cookies/same_party_context.cc @@ -4,35 +4,19 @@ #include "net/cookies/same_party_context.h" -#include <sstream> -#include <tuple> - -#include "net/cookies/cookie_constants.h" +#include <ostream> namespace net { -SamePartyContext::SamePartyContext(Type type) - : SamePartyContext(type, type, type) {} - -SamePartyContext::SamePartyContext(Type context_type, - Type ancestors_for_metrics, - Type top_resource_for_metrics) - : context_type_(context_type), - ancestors_for_metrics_only_(ancestors_for_metrics), - top_resource_for_metrics_only_(top_resource_for_metrics) {} +SamePartyContext::SamePartyContext(Type context_type) + : context_type_(context_type) {} bool SamePartyContext::operator==(const SamePartyContext& other) const { - return std::make_tuple(context_type(), ancestors_for_metrics_only(), - top_resource_for_metrics_only()) == - std::make_tuple(other.context_type(), - other.ancestors_for_metrics_only(), - other.top_resource_for_metrics_only()); + return context_type_ == other.context_type_; } std::ostream& operator<<(std::ostream& os, const SamePartyContext& spc) { - os << "{" << static_cast<int>(spc.context_type()) << ", " - << static_cast<int>(spc.ancestors_for_metrics_only()) << ", " - << static_cast<int>(spc.top_resource_for_metrics_only()) << "}"; + os << "{" << static_cast<int>(spc.context_type()) << "}"; return os; } @@ -40,4 +24,5 @@ std::ostream& operator<<(std::ostream& os, const SamePartyContext& spc) { SamePartyContext SamePartyContext::MakeInclusive() { return SamePartyContext(Type::kSameParty); } + } // namespace net diff --git a/chromium/net/cookies/same_party_context.h b/chromium/net/cookies/same_party_context.h index 2de8e2c0ac7..7235492281c 100644 --- a/chromium/net/cookies/same_party_context.h +++ b/chromium/net/cookies/same_party_context.h @@ -5,8 +5,9 @@ #ifndef NET_COOKIES_SAME_PARTY_CONTEXT_H_ #define NET_COOKIES_SAME_PARTY_CONTEXT_H_ +#include <ostream> + #include "net/base/net_export.h" -#include "net/cookies/cookie_constants.h" namespace net { @@ -27,10 +28,7 @@ class NET_EXPORT SamePartyContext { }; SamePartyContext() = default; - explicit SamePartyContext(Type type); - SamePartyContext(Type context_type, - Type ancestors_for_metrics, - Type top_resource_for_metrics); + explicit SamePartyContext(Type context_type); bool operator==(const SamePartyContext& other) const; @@ -38,25 +36,11 @@ class NET_EXPORT SamePartyContext { // SameParty cookies. Default is not trusted, e.g. kCrossParty. Type context_type() const { return context_type_; } - // We store the type of the SameParty context if we inferred singleton sets, - // for the purpose of metrics. - Type ancestors_for_metrics_only() const { - return ancestors_for_metrics_only_; - } - // We also store the type of the SameParty context if it were computed using - // only the top frame and resource URL and inferred singleton sets, for the - // purpose of metrics. - Type top_resource_for_metrics_only() const { - return top_resource_for_metrics_only_; - } - // Creates a SamePartyContext that is as permissive as possible. static SamePartyContext MakeInclusive(); private: Type context_type_ = Type::kCrossParty; - Type ancestors_for_metrics_only_ = Type::kCrossParty; - Type top_resource_for_metrics_only_ = Type::kCrossParty; }; NET_EXPORT std::ostream& operator<<(std::ostream& os, diff --git a/chromium/net/cookies/test_cookie_access_delegate.cc b/chromium/net/cookies/test_cookie_access_delegate.cc index b9b5af545c7..31451884f97 100644 --- a/chromium/net/cookies/test_cookie_access_delegate.cc +++ b/chromium/net/cookies/test_cookie_access_delegate.cc @@ -19,6 +19,7 @@ #include "net/base/schemeful_site.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_util.h" +#include "net/cookies/first_party_set_entry.h" #include "net/cookies/first_party_set_metadata.h" #include "net/cookies/same_party_context.h" @@ -54,62 +55,42 @@ TestCookieAccessDelegate::ComputeFirstPartySetMetadataMaybeAsync( const SchemefulSite* top_frame_site, const std::set<SchemefulSite>& party_context, base::OnceCallback<void(FirstPartySetMetadata)> callback) const { - absl::optional<SchemefulSite> top_frame_owner = + absl::optional<FirstPartySetEntry> top_frame_owner = top_frame_site ? FindFirstPartySetOwnerSync(*top_frame_site) : absl::nullopt; return RunMaybeAsync( FirstPartySetMetadata( SamePartyContext(), base::OptionalOrNullptr(FindFirstPartySetOwnerSync(site)), - base::OptionalOrNullptr(top_frame_owner), - FirstPartySetsContextType::kUnknown), + base::OptionalOrNullptr(top_frame_owner)), std::move(callback)); } -absl::optional<SchemefulSite> +absl::optional<FirstPartySetEntry> TestCookieAccessDelegate::FindFirstPartySetOwnerSync( const SchemefulSite& site) const { - auto owner_set_iter = - base::ranges::find_if(first_party_sets_, [&](const auto& set_iter) { - return base::Contains(set_iter.second, site); - }); - - return owner_set_iter != first_party_sets_.end() - ? absl::make_optional(owner_set_iter->first) - : absl::nullopt; -} + auto entry = first_party_sets_.find(site); -absl::optional<absl::optional<SchemefulSite>> -TestCookieAccessDelegate::FindFirstPartySetOwner( - const SchemefulSite& site, - base::OnceCallback<void(absl::optional<SchemefulSite>)> callback) const { - return RunMaybeAsync(FindFirstPartySetOwnerSync(site), std::move(callback)); + return entry != first_party_sets_.end() ? absl::make_optional(entry->second) + : absl::nullopt; } -absl::optional<base::flat_map<SchemefulSite, SchemefulSite>> +absl::optional<base::flat_map<SchemefulSite, FirstPartySetEntry>> TestCookieAccessDelegate::FindFirstPartySetOwners( const base::flat_set<SchemefulSite>& sites, - base::OnceCallback<void(base::flat_map<SchemefulSite, SchemefulSite>)> + base::OnceCallback<void(base::flat_map<SchemefulSite, FirstPartySetEntry>)> callback) const { - std::vector<std::pair<SchemefulSite, SchemefulSite>> mapping; + std::vector<std::pair<SchemefulSite, FirstPartySetEntry>> mapping; for (const SchemefulSite& site : sites) { - absl::optional<SchemefulSite> owner = FindFirstPartySetOwnerSync(site); - if (owner) - mapping.emplace_back(site, *owner); + absl::optional<FirstPartySetEntry> entry = FindFirstPartySetOwnerSync(site); + if (entry) + mapping.emplace_back(site, *entry); } - return RunMaybeAsync<base::flat_map<SchemefulSite, SchemefulSite>>( + return RunMaybeAsync<base::flat_map<SchemefulSite, FirstPartySetEntry>>( mapping, std::move(callback)); } -absl::optional<base::flat_map<SchemefulSite, std::set<SchemefulSite>>> -TestCookieAccessDelegate::RetrieveFirstPartySets( - base::OnceCallback< - void(base::flat_map<SchemefulSite, std::set<SchemefulSite>>)> callback) - const { - return RunMaybeAsync(first_party_sets_, std::move(callback)); -} - template <class T> absl::optional<T> TestCookieAccessDelegate::RunMaybeAsync( T result, @@ -142,7 +123,7 @@ std::string TestCookieAccessDelegate::GetKeyForDomainValue( } void TestCookieAccessDelegate::SetFirstPartySets( - const base::flat_map<SchemefulSite, std::set<SchemefulSite>>& sets) { + const base::flat_map<SchemefulSite, FirstPartySetEntry>& sets) { first_party_sets_ = sets; } diff --git a/chromium/net/cookies/test_cookie_access_delegate.h b/chromium/net/cookies/test_cookie_access_delegate.h index 969447f7080..c07c887a415 100644 --- a/chromium/net/cookies/test_cookie_access_delegate.h +++ b/chromium/net/cookies/test_cookie_access_delegate.h @@ -15,8 +15,8 @@ #include "net/base/schemeful_site.h" #include "net/cookies/cookie_access_delegate.h" #include "net/cookies/cookie_constants.h" +#include "net/cookies/first_party_set_entry.h" #include "net/cookies/first_party_set_metadata.h" -#include "net/cookies/same_party_context.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -46,19 +46,11 @@ class TestCookieAccessDelegate : public CookieAccessDelegate { const SchemefulSite* top_frame_site, const std::set<SchemefulSite>& party_context, base::OnceCallback<void(FirstPartySetMetadata)> callback) const override; - absl::optional<absl::optional<SchemefulSite>> FindFirstPartySetOwner( - const SchemefulSite& site, - base::OnceCallback<void(absl::optional<SchemefulSite>)> callback) - const override; - absl::optional<base::flat_map<SchemefulSite, SchemefulSite>> + absl::optional<base::flat_map<SchemefulSite, FirstPartySetEntry>> FindFirstPartySetOwners( const base::flat_set<SchemefulSite>& sites, - base::OnceCallback<void(base::flat_map<SchemefulSite, SchemefulSite>)> - callback) const override; - absl::optional<base::flat_map<SchemefulSite, std::set<SchemefulSite>>> - RetrieveFirstPartySets( - base::OnceCallback<void( - base::flat_map<SchemefulSite, std::set<SchemefulSite>>)> callback) + base::OnceCallback< + void(base::flat_map<SchemefulSite, FirstPartySetEntry>)> callback) const override; // Sets the expected return value for any cookie whose Domain @@ -74,11 +66,10 @@ class TestCookieAccessDelegate : public CookieAccessDelegate { const std::string& site_for_cookies_scheme, bool require_secure_origin); - // Set the test delegate's First-Party Sets. The map is keyed on the set's - // owner site. The owner site should still be included in the std::set stored - // in the map. + // Set the test delegate's First-Party Sets. The map's keys are the sites in + // the sets. Owner sites must be included among the keys for a given set. void SetFirstPartySets( - const base::flat_map<SchemefulSite, std::set<SchemefulSite>>& sets); + const base::flat_map<SchemefulSite, FirstPartySetEntry>& sets); void set_invoke_callbacks_asynchronously(bool async) { invoke_callbacks_asynchronously_ = async; @@ -86,7 +77,7 @@ class TestCookieAccessDelegate : public CookieAccessDelegate { private: // Synchronous version of FindFirstPartySetOwner, for convenience. - absl::optional<SchemefulSite> FindFirstPartySetOwnerSync( + absl::optional<FirstPartySetEntry> FindFirstPartySetOwnerSync( const SchemefulSite& site) const; // Discard any leading dot in the domain string. @@ -100,7 +91,7 @@ class TestCookieAccessDelegate : public CookieAccessDelegate { std::map<std::string, CookieAccessSemantics> expectations_; std::map<std::string, bool> ignore_samesite_restrictions_schemes_; - base::flat_map<SchemefulSite, std::set<SchemefulSite>> first_party_sets_; + base::flat_map<SchemefulSite, FirstPartySetEntry> first_party_sets_; bool invoke_callbacks_asynchronously_ = false; }; |