summaryrefslogtreecommitdiff
path: root/chromium/net/cookies
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-09-01 11:08:40 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-01 12:16:21 +0000
commit03c549e0392f92c02536d3f86d5e1d8dfa3435ac (patch)
treefe49d170a929b34ba82cd10db1a0bd8e3760fa4b /chromium/net/cookies
parent5d013f5804a0d91fcf6c626b2d6fb6eca5c845b0 (diff)
downloadqtwebengine-chromium-03c549e0392f92c02536d3f86d5e1d8dfa3435ac.tar.gz
BASELINE: Update Chromium to 91.0.4472.160
Change-Id: I0def1f08a2412aeed79a9ab95dd50eb5c3f65f31 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net/cookies')
-rw-r--r--chromium/net/cookies/README.md7
-rw-r--r--chromium/net/cookies/canonical_cookie.cc35
-rw-r--r--chromium/net/cookies/canonical_cookie_unittest.cc83
-rw-r--r--chromium/net/cookies/cookie_access_delegate.h5
-rw-r--r--chromium/net/cookies/cookie_constants.cc55
-rw-r--r--chromium/net/cookies/cookie_constants.h36
-rw-r--r--chromium/net/cookies/cookie_monster.cc109
-rw-r--r--chromium/net/cookies/cookie_monster.h24
-rw-r--r--chromium/net/cookies/cookie_monster_change_dispatcher.h2
-rw-r--r--chromium/net/cookies/cookie_monster_unittest.cc201
-rw-r--r--chromium/net/cookies/cookie_store_unittest.h21
-rw-r--r--chromium/net/cookies/cookie_util.cc126
-rw-r--r--chromium/net/cookies/cookie_util.h44
-rw-r--r--chromium/net/cookies/cookie_util_unittest.cc406
-rw-r--r--chromium/net/cookies/parsed_cookie.cc8
-rw-r--r--chromium/net/cookies/site_for_cookies.cc7
-rw-r--r--chromium/net/cookies/site_for_cookies.h30
-rw-r--r--chromium/net/cookies/site_for_cookies_unittest.cc70
-rw-r--r--chromium/net/cookies/static_cookie_policy_unittest.cc3
-rw-r--r--chromium/net/cookies/test_cookie_access_delegate.cc2
-rw-r--r--chromium/net/cookies/test_cookie_access_delegate.h2
21 files changed, 961 insertions, 315 deletions
diff --git a/chromium/net/cookies/README.md b/chromium/net/cookies/README.md
index 73cd8392244..8b43af9a67e 100644
--- a/chromium/net/cookies/README.md
+++ b/chromium/net/cookies/README.md
@@ -76,9 +76,10 @@ name and value.
The `ParsedCookie` is then converted into a `CanonicalCookie`. This is the main
data type representing cookies. Any cookie consumer that does not deal directly
with HTTP headers operates on `CanonicalCookie`s. A `CanonicalCookie` has some
-additional guarantees of validity over a `ParsedCookie`, such as sane expiration
-times, valid domain and path attributes, etc. Once a `CanonicalCookie` is
-created, you will almost never see a `ParsedCookie` used for anything else.
+additional guarantees of validity over a `ParsedCookie`, such as valid
+expiration times, valid domain and path attributes, etc. Once a
+`CanonicalCookie` is created, you will almost never see a `ParsedCookie` used
+for anything else.
If a valid `CanonicalCookie` could not be created (due to some illegal syntax,
inconsistent attribute values, or other circumstances preventing parsing), then
diff --git a/chromium/net/cookies/canonical_cookie.cc b/chromium/net/cookies/canonical_cookie.cc
index 9168c32f3c1..8af2c1b14b4 100644
--- a/chromium/net/cookies/canonical_cookie.cc
+++ b/chromium/net/cookies/canonical_cookie.cc
@@ -44,6 +44,7 @@
#include "net/cookies/canonical_cookie.h"
+#include <limits>
#include <sstream>
#include <utility>
@@ -54,6 +55,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/features.h"
@@ -334,15 +336,30 @@ Time CanonicalCookie::CanonExpiration(const ParsedCookie& pc,
const Time& current,
const Time& server_time) {
// First, try the Max-Age attribute.
- uint64_t max_age = 0;
- if (pc.HasMaxAge() &&
-#ifdef COMPILER_MSVC
- sscanf_s(
-#else
- sscanf(
-#endif
- pc.MaxAge().c_str(), " %" PRIu64, &max_age) == 1) {
- return current + TimeDelta::FromSeconds(max_age);
+ if (pc.HasMaxAge()) {
+ int64_t max_age = 0;
+ // Use the output if StringToInt64 returns true ("perfect" conversion). This
+ // case excludes overflow/underflow, leading/trailing whitespace, non-number
+ // strings, and empty string. (ParsedCookie trims whitespace.)
+ if (base::StringToInt64(pc.MaxAge(), &max_age)) {
+ // RFC 6265bis algorithm for parsing Max-Age:
+ // "If delta-seconds is less than or equal to zero (0), let expiry-
+ // time be the earliest representable date and time. ... "
+ if (max_age <= 0)
+ return Time::Min();
+ // "... Otherwise, let the expiry-time be the current date and time plus
+ // delta-seconds seconds."
+ return current + TimeDelta::FromSeconds(max_age);
+ } else {
+ // If the conversion wasn't perfect, but the best-effort conversion
+ // resulted in an overflow/underflow, use the min/max representable time.
+ // (This is alluded to in the spec, which says the user agent MAY clip an
+ // Expires attribute to a saturated time. We'll do the same for Max-Age.)
+ if (max_age == std::numeric_limits<int64_t>::min())
+ return Time::Min();
+ if (max_age == std::numeric_limits<int64_t>::max())
+ return Time::Max();
+ }
}
// Try the Expires attribute.
diff --git a/chromium/net/cookies/canonical_cookie_unittest.cc b/chromium/net/cookies/canonical_cookie_unittest.cc
index 921eb2260f0..d42132030c8 100644
--- a/chromium/net/cookies/canonical_cookie_unittest.cc
+++ b/chromium/net/cookies/canonical_cookie_unittest.cc
@@ -452,6 +452,89 @@ TEST(CanonicalCookieTest, CreateSameParty) {
{CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY}));
}
+TEST(CanonicalCookieTest, CreateWithMaxAge) {
+ GURL url("http://www.example.com/test/foo.html");
+ base::Time creation_time = base::Time::Now();
+ base::Optional<base::Time> server_time = base::nullopt;
+
+ // Max-age with positive integer.
+ std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
+ url, "A=1; max-age=60", creation_time, server_time);
+ EXPECT_TRUE(cookie.get());
+ EXPECT_TRUE(cookie->IsPersistent());
+ EXPECT_FALSE(cookie->IsExpired(creation_time));
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60) + creation_time,
+ cookie->ExpiryDate());
+
+ // Max-age with expires (max-age should take precedence).
+ cookie = CanonicalCookie::Create(
+ url, "A=1; expires=01-Jan-1970, 00:00:00 GMT; max-age=60", creation_time,
+ server_time);
+ EXPECT_TRUE(cookie.get());
+ EXPECT_TRUE(cookie->IsPersistent());
+ EXPECT_FALSE(cookie->IsExpired(creation_time));
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60) + creation_time,
+ cookie->ExpiryDate());
+
+ // Max-age=0 should create an expired cookie with expiry equal to the earliest
+ // representable time.
+ cookie = CanonicalCookie::Create(url, "A=1; max-age=0", creation_time,
+ server_time);
+ EXPECT_TRUE(cookie.get());
+ EXPECT_TRUE(cookie->IsPersistent());
+ EXPECT_TRUE(cookie->IsExpired(creation_time));
+ EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate());
+
+ // Negative max-age should create an expired cookie with expiry equal to the
+ // earliest representable time.
+ cookie = CanonicalCookie::Create(url, "A=1; max-age=-1", creation_time,
+ server_time);
+ EXPECT_TRUE(cookie.get());
+ EXPECT_TRUE(cookie->IsPersistent());
+ EXPECT_TRUE(cookie->IsExpired(creation_time));
+ EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate());
+
+ // Max-age with whitespace (should be trimmed out).
+ cookie = CanonicalCookie::Create(url, "A=1; max-age = 60 ; Secure",
+ creation_time, server_time);
+ EXPECT_TRUE(cookie.get());
+ EXPECT_TRUE(cookie->IsPersistent());
+ EXPECT_FALSE(cookie->IsExpired(creation_time));
+ EXPECT_EQ(base::TimeDelta::FromSeconds(60) + creation_time,
+ cookie->ExpiryDate());
+
+ // Max-age with non-integer should be ignored.
+ cookie = CanonicalCookie::Create(url, "A=1; max-age=abcd", creation_time,
+ server_time);
+ EXPECT_TRUE(cookie.get());
+ EXPECT_FALSE(cookie->IsPersistent());
+ EXPECT_FALSE(cookie->IsExpired(creation_time));
+
+ // Overflow max-age should be clipped.
+ cookie = CanonicalCookie::Create(url,
+ "A=1; "
+ "max-age="
+ "9999999999999999999999999999999999999999999"
+ "999999999999999999999999999999999999999999",
+ creation_time, server_time);
+ EXPECT_TRUE(cookie.get());
+ EXPECT_TRUE(cookie->IsPersistent());
+ EXPECT_FALSE(cookie->IsExpired(creation_time));
+ EXPECT_EQ(base::Time::Max(), cookie->ExpiryDate());
+
+ // Underflow max-age should be clipped.
+ cookie = CanonicalCookie::Create(url,
+ "A=1; "
+ "max-age=-"
+ "9999999999999999999999999999999999999999999"
+ "999999999999999999999999999999999999999999",
+ creation_time, server_time);
+ EXPECT_TRUE(cookie.get());
+ EXPECT_TRUE(cookie->IsPersistent());
+ EXPECT_TRUE(cookie->IsExpired(creation_time));
+ EXPECT_EQ(base::Time::Min(), cookie->ExpiryDate());
+}
+
TEST(CanonicalCookieTest, EmptyExpiry) {
GURL url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
base::Time creation_time = base::Time::Now();
diff --git a/chromium/net/cookies/cookie_access_delegate.h b/chromium/net/cookies/cookie_access_delegate.h
index f1866725621..f9ecd912c3e 100644
--- a/chromium/net/cookies/cookie_access_delegate.h
+++ b/chromium/net/cookies/cookie_access_delegate.h
@@ -39,10 +39,11 @@ class NET_EXPORT CookieAccessDelegate {
const SiteForCookies& site_for_cookies) const = 0;
// Returns whether `site` is same-party with `party_context` and
- // `top_frame_site`.
+ // `top_frame_site`. If `top_frame_site` is nullopt, then `site` will be
+ // checked only against `party_context`.
virtual bool IsContextSamePartyWithSite(
const net::SchemefulSite& site,
- const net::SchemefulSite& top_frame_site,
+ const base::Optional<net::SchemefulSite>& top_frame_site,
const std::set<net::SchemefulSite>& party_context) const = 0;
// Returns whether `site` belongs to a non-singleton First-Party Set.
diff --git a/chromium/net/cookies/cookie_constants.cc b/chromium/net/cookies/cookie_constants.cc
index 117fe0c90f5..e6c5c429eb4 100644
--- a/chromium/net/cookies/cookie_constants.cc
+++ b/chromium/net/cookies/cookie_constants.cc
@@ -8,6 +8,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/string_util.h"
+#include "url/url_constants.h"
namespace net {
@@ -294,4 +295,58 @@ CookiePort ReducePortRangeForCookieHistogram(const int port) {
}
}
+CookieSourceSchemeName GetSchemeNameEnum(const GURL& url) {
+ // The most likely schemes are first, to improve performance.
+ if (url.SchemeIs(url::kHttpsScheme)) {
+ return CookieSourceSchemeName::kHttpsScheme;
+ } else if (url.SchemeIs(url::kHttpScheme)) {
+ return CookieSourceSchemeName::kHttpScheme;
+ } else if (url.SchemeIs(url::kWssScheme)) {
+ return CookieSourceSchemeName::kWssScheme;
+ } else if (url.SchemeIs(url::kWsScheme)) {
+ return CookieSourceSchemeName::kWsScheme;
+ } else if (url.SchemeIs("chrome-extension")) {
+ return CookieSourceSchemeName::kChromeExtensionScheme;
+ } else if (url.SchemeIs(url::kFileScheme)) {
+ return CookieSourceSchemeName::kFileScheme;
+ }
+ // These all aren't marked as cookieable and so are much less likely to
+ // occur.
+ else if (url.SchemeIs(url::kAboutBlankURL)) {
+ return CookieSourceSchemeName::kAboutBlankURL;
+ } else if (url.SchemeIs(url::kAboutSrcdocURL)) {
+ return CookieSourceSchemeName::kAboutSrcdocURL;
+ } else if (url.SchemeIs(url::kAboutBlankPath)) {
+ return CookieSourceSchemeName::kAboutBlankPath;
+ } else if (url.SchemeIs(url::kAboutSrcdocPath)) {
+ return CookieSourceSchemeName::kAboutSrcdocPath;
+ } else if (url.SchemeIs(url::kAboutScheme)) {
+ return CookieSourceSchemeName::kAboutScheme;
+ } else if (url.SchemeIs(url::kBlobScheme)) {
+ return CookieSourceSchemeName::kBlobScheme;
+ } else if (url.SchemeIs(url::kContentScheme)) {
+ return CookieSourceSchemeName::kContentScheme;
+ } else if (url.SchemeIs(url::kContentIDScheme)) {
+ return CookieSourceSchemeName::kContentIDScheme;
+ } else if (url.SchemeIs(url::kDataScheme)) {
+ return CookieSourceSchemeName::kDataScheme;
+ } else if (url.SchemeIs(url::kFileSystemScheme)) {
+ return CookieSourceSchemeName::kFileSystemScheme;
+ } else if (url.SchemeIs(url::kFtpScheme)) {
+ return CookieSourceSchemeName::kFtpScheme;
+ } else if (url.SchemeIs(url::kJavaScriptScheme)) {
+ return CookieSourceSchemeName::kJavaScriptScheme;
+ } else if (url.SchemeIs(url::kMailToScheme)) {
+ return CookieSourceSchemeName::kMailToScheme;
+ } else if (url.SchemeIs(url::kQuicTransportScheme)) {
+ return CookieSourceSchemeName::kQuicTransportScheme;
+ } else if (url.SchemeIs(url::kTelScheme)) {
+ return CookieSourceSchemeName::kTelScheme;
+ } else if (url.SchemeIs(url::kUrnScheme)) {
+ return CookieSourceSchemeName::kUrnScheme;
+ }
+
+ return CookieSourceSchemeName::kOther;
+}
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_constants.h b/chromium/net/cookies/cookie_constants.h
index 04b1656eb37..729d2b1418e 100644
--- a/chromium/net/cookies/cookie_constants.h
+++ b/chromium/net/cookies/cookie_constants.h
@@ -9,6 +9,7 @@
#include "base/time/time.h"
#include "net/base/net_export.h"
+#include "url/gurl.h"
namespace net {
@@ -241,6 +242,38 @@ enum class CookieAccessScheme {
kMaxValue = kTrustworthy // Keep as the last value.
};
+// Used to populate a histogram that measures which schemes are used to set
+// cookies and how frequently. Many of these probably won't/can't be used,
+// but we know about them and there's no harm in including them.
+//
+// Do not reorder or renumber. Used for metrics.
+enum class CookieSourceSchemeName {
+ kOther = 0, // Catch all for any other schemes that may be used.
+ kAboutBlankURL = 1,
+ kAboutSrcdocURL = 2,
+ kAboutBlankPath = 3,
+ kAboutSrcdocPath = 4,
+ kAboutScheme = 5,
+ kBlobScheme = 6,
+ kContentScheme = 7,
+ kContentIDScheme = 8,
+ kDataScheme = 9,
+ kFileScheme = 10,
+ kFileSystemScheme = 11,
+ kFtpScheme = 12,
+ kHttpScheme = 13,
+ kHttpsScheme = 14,
+ kJavaScriptScheme = 15,
+ kMailToScheme = 16,
+ kQuicTransportScheme = 17,
+ kTelScheme = 18,
+ kUrnScheme = 19,
+ kWsScheme = 20,
+ kWssScheme = 21,
+ kChromeExtensionScheme = 22,
+ kMaxValue = kChromeExtensionScheme
+};
+
// Returns the Set-Cookie header priority token corresponding to |priority|.
NET_EXPORT std::string CookiePriorityToString(CookiePriority priority);
@@ -270,6 +303,9 @@ NET_EXPORT void RecordCookieSameSiteAttributeValueHistogram(
// is because UMA cannot handle the full range.
NET_EXPORT CookiePort ReducePortRangeForCookieHistogram(const int port);
+// Returns the appropriate enum value for the scheme of the given GURL.
+CookieSourceSchemeName GetSchemeNameEnum(const GURL& url);
+
} // namespace net
#endif // NET_COOKIES_COOKIE_CONSTANTS_H_
diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc
index e8e5c326c79..dd1ff2e34ab 100644
--- a/chromium/net/cookies/cookie_monster.cc
+++ b/chromium/net/cookies/cookie_monster.cc
@@ -55,7 +55,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/field_trial.h"
-#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/ranges/algorithm.h"
@@ -76,6 +75,7 @@
#include "net/cookies/cookie_monster_netlog_params.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/parsed_cookie.h"
+#include "net/http/http_util.h"
#include "net/log/net_log.h"
#include "net/log/net_log_values.h"
#include "url/origin.h"
@@ -165,7 +165,7 @@ const int CookieMonster::kSafeFromGlobalPurgeDays = 30;
namespace {
bool ContainsControlCharacter(const std::string& s) {
- return base::ranges::any_of(s, [](char c) { return c >= 0 && c <= 31; });
+ return base::ranges::any_of(s, &HttpUtil::IsControlChar);
}
typedef std::vector<CanonicalCookie*> CanonicalCookieVector;
@@ -304,6 +304,27 @@ size_t CountCookiesForPossibleDeletion(
return cookies_count;
}
+// Records minutes until the expiration date of a cookie to the appropriate
+// histogram. Only histograms cookies that have an expiration date (i.e. are
+// persistent).
+void HistogramExpirationDuration(const CanonicalCookie& cookie,
+ base::Time creation_time) {
+ if (!cookie.IsPersistent())
+ return;
+
+ int expiration_duration_minutes =
+ (cookie.ExpiryDate() - creation_time).InMinutes();
+ if (cookie.IsSecure()) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ExpirationDurationMinutesSecure",
+ expiration_duration_minutes, 1,
+ kMinutesInTenYears, 50);
+ } else {
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ExpirationDurationMinutesNonSecure",
+ expiration_duration_minutes, 1,
+ kMinutesInTenYears, 50);
+ }
+}
+
} // namespace
CookieMonster::CookieMonster(scoped_refptr<PersistentCookieStore> store,
@@ -327,7 +348,6 @@ CookieMonster::CookieMonster(scoped_refptr<PersistentCookieStore> store,
last_access_threshold_(last_access_threshold),
last_statistic_record_time_(base::Time::Now()),
persist_session_cookies_(false) {
- InitializeHistograms();
cookieable_schemes_.insert(
cookieable_schemes_.begin(), kDefaultCookieableSchemes,
kDefaultCookieableSchemes + kDefaultCookieableSchemesCount);
@@ -724,7 +744,9 @@ void CookieMonster::OnLoaded(
std::vector<std::unique_ptr<CanonicalCookie>> cookies) {
DCHECK(thread_checker_.CalledOnValidThread());
StoreLoadedCookies(std::move(cookies));
- histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time);
+ base::UmaHistogramCustomTimes(
+ "Cookie.TimeBlockedOnLoad", base::TimeTicks::Now() - beginning_time,
+ TimeDelta::FromMilliseconds(1), TimeDelta::FromMinutes(1), 50);
// Invoke the task queue of cookie request.
InvokeQueue();
@@ -1163,14 +1185,14 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie(
}
auto inserted = cookies_.insert(CookieMap::value_type(key, std::move(cc)));
- // See InitializeHistograms() for details.
int32_t type_sample =
!cc_ptr->IsEffectivelySameSiteNone(access_result.access_semantics)
? 1 << COOKIE_TYPE_SAME_SITE
: 0;
type_sample |= cc_ptr->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0;
type_sample |= cc_ptr->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0;
- histogram_cookie_type_->Add(type_sample);
+ UMA_HISTOGRAM_EXACT_LINEAR("Cookie.Type", type_sample,
+ (1 << COOKIE_TYPE_LAST_ENTRY));
DCHECK(access_result.status.IsInclude());
if (dispatch_change) {
@@ -1265,16 +1287,7 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
// Realize that we might be setting an expired cookie, and the only point
// was to delete the cookie which we've already done.
if (!already_expired) {
- // See InitializeHistograms() for details.
- if (cc->IsPersistent()) {
- if (cc->IsSecure()) {
- histogram_expiration_duration_minutes_secure_->Add(
- (cc->ExpiryDate() - creation_date).InMinutes());
- } else {
- histogram_expiration_duration_minutes_non_secure_->Add(
- (cc->ExpiryDate() - creation_date).InMinutes());
- }
- }
+ HistogramExpirationDuration(*cc, creation_date);
// Histogram the type of scheme used on URLs that set cookies. This
// intentionally includes cookies that are set or overwritten by
@@ -1291,7 +1304,8 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
: (cc->IsSecure()
? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
: COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME));
- histogram_cookie_source_scheme_->Add(cookie_source_sample);
+ UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSourceScheme",
+ cookie_source_sample);
UMA_HISTOGRAM_BOOLEAN("Cookie.DomainSet", cc->IsDomainCookie());
@@ -1321,6 +1335,9 @@ void CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc,
"Cookie.Port.Set.RemoteHost",
ReducePortRangeForCookieHistogram(source_url.EffectiveIntPort()));
}
+
+ UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSourceSchemeName",
+ GetSchemeNameEnum(source_url));
} else {
UMA_HISTOGRAM_BOOLEAN(
"Cookie.SameParty.SetExclusionDecidedBySameParty",
@@ -1349,15 +1366,7 @@ void CookieMonster::SetAllCookies(CookieList list,
if (cookie.IsExpired(creation_time))
continue;
- if (cookie.IsPersistent()) {
- if (cookie.IsSecure()) {
- histogram_expiration_duration_minutes_secure_->Add(
- (cookie.ExpiryDate() - creation_time).InMinutes());
- } else {
- histogram_expiration_duration_minutes_non_secure_->Add(
- (cookie.ExpiryDate() - creation_time).InMinutes());
- }
- }
+ HistogramExpirationDuration(cookie, creation_time);
CookieAccessResult access_result;
access_result.access_semantics = GetAccessSemanticsForCookie(cookie);
@@ -1489,10 +1498,10 @@ size_t CookieMonster::GarbageCollect(const Time& current,
// 4. High-priority non-secure cookies.
// 5. Medium-priority secure cookies.
// 6. High-priority secure cookies.
- const static struct {
+ constexpr struct {
CookiePriority priority;
bool protect_secure_cookies;
- } purge_rounds[] = {
+ } kPurgeRounds[] = {
// 1. Low-priority non-secure cookies.
{COOKIE_PRIORITY_LOW, true},
// 2. Low-priority secure cookies.
@@ -1508,7 +1517,7 @@ size_t CookieMonster::GarbageCollect(const Time& current,
};
size_t quota = 0;
- for (const auto& purge_round : purge_rounds) {
+ for (const auto& purge_round : kPurgeRounds) {
// Adjust quota according to the priority of cookies. Each round should
// protect certain number of cookies in order to avoid starvation.
// For example, when each round starts to remove cookies, the number of
@@ -1636,7 +1645,7 @@ size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies,
secure_cookies = CountCookiesForPossibleDeletion(
priority, cookies, protect_secure_cookies /* count secure cookies */);
cookies_count_possibly_to_be_deleted -=
- std::max(secure_cookies, to_protect - secure_cookies);
+ std::max(secure_cookies, to_protect);
} else {
cookies_count_possibly_to_be_deleted -= to_protect;
}
@@ -1811,8 +1820,7 @@ bool CookieMonster::DoRecordPeriodicStats() {
if (started_fetching_all_cookies_ && !finished_fetching_all_cookies_)
return false;
- // See InitializeHistograms() for details.
- histogram_count_->Add(cookies_.size());
+ base::UmaHistogramCounts100000("Cookie.Count2", cookies_.size());
if (cookie_access_delegate()) {
for (const auto& set : cookie_access_delegate()->RetrieveFirstPartySets()) {
@@ -1837,43 +1845,6 @@ bool CookieMonster::DoRecordPeriodicStats() {
return true;
}
-// Initialize all histogram counter variables used in this class.
-//
-// TODO(https://crbug.com/1087445): remove this in favor of histogram_macros.h
-// or histogram_functions.h usage, since both are now threadsafe.
-void CookieMonster::InitializeHistograms() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // From UMA_HISTOGRAM_CUSTOM_COUNTS
- histogram_expiration_duration_minutes_secure_ = base::Histogram::FactoryGet(
- "Cookie.ExpirationDurationMinutesSecure", 1, kMinutesInTenYears, 50,
- base::Histogram::kUmaTargetedHistogramFlag);
- histogram_expiration_duration_minutes_non_secure_ =
- base::Histogram::FactoryGet("Cookie.ExpirationDurationMinutesNonSecure",
- 1, kMinutesInTenYears, 50,
- base::Histogram::kUmaTargetedHistogramFlag);
-
- // From UMA_HISTOGRAM_COUNTS_100000
- // This replaces Cookie.Count which only counted up to 4000 cookies.
- histogram_count_ =
- base::Histogram::FactoryGet("Cookie.Count2", 1, 100000, 50,
- base::Histogram::kUmaTargetedHistogramFlag);
-
- // From UMA_HISTOGRAM_ENUMERATION
- histogram_cookie_type_ = base::LinearHistogram::FactoryGet(
- "Cookie.Type", 1, (1 << COOKIE_TYPE_LAST_ENTRY) - 1,
- 1 << COOKIE_TYPE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
- histogram_cookie_source_scheme_ = base::LinearHistogram::FactoryGet(
- "Cookie.CookieSourceScheme", 1, COOKIE_SOURCE_LAST_ENTRY - 1,
- COOKIE_SOURCE_LAST_ENTRY, base::Histogram::kUmaTargetedHistogramFlag);
-
- // From UMA_HISTOGRAM_{CUSTOM_,}TIMES
- histogram_time_blocked_on_load_ = base::Histogram::FactoryTimeGet(
- "Cookie.TimeBlockedOnLoad", base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMinutes(1), 50,
- base::Histogram::kUmaTargetedHistogramFlag);
-}
-
void CookieMonster::DoCookieCallback(base::OnceClosure callback) {
DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h
index 42650759651..00446acaabc 100644
--- a/chromium/net/cookies/cookie_monster.h
+++ b/chromium/net/cookies/cookie_monster.h
@@ -37,10 +37,6 @@
#include "net/log/net_log_with_source.h"
#include "url/gurl.h"
-namespace base {
-class HistogramBase;
-} // namespace base
-
namespace net {
class CookieChangeDispatcher;
@@ -284,6 +280,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
// of stored cookies. Please do not reorder the list when adding new entries.
// New items MUST be added at the end of the list, just before
// COOKIE_TYPE_LAST_ENTRY;
+ // There will be 2^COOKIE_TYPE_LAST_ENTRY buckets in the linear histogram.
enum CookieType {
COOKIE_TYPE_SAME_SITE = 0,
COOKIE_TYPE_HTTPONLY,
@@ -295,8 +292,8 @@ class NET_EXPORT CookieMonster : public CookieStore {
// sources of Secure and non-Secure cookies: that is, whether such
// cookies are set by origins with cryptographic or non-cryptographic
// schemes. Please do not reorder the list when adding new
- // entries. New items MUST be added at the end of the list, just
- // before COOKIE_SOURCE_LAST_ENTRY.
+ // 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
// that a cookie was set or overwritten from a URL with the given type
@@ -308,7 +305,7 @@ class NET_EXPORT CookieMonster : public CookieStore {
COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME,
COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME,
COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME,
- COOKIE_SOURCE_LAST_ENTRY
+ kMaxValue = COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME
};
// Enum for collecting metrics on how frequently a cookie is sent to the same
@@ -555,10 +552,6 @@ class NET_EXPORT CookieMonster : public CookieStore {
// cookies. Returns whether stats were recorded.
bool DoRecordPeriodicStats();
- // Initialize the histogram_* variables below; should only be called from
- // the constructor.
- void InitializeHistograms();
-
// Defers the callback until the full coookie database has been loaded. If
// it's already been loaded, runs the callback synchronously.
void DoCookieCallback(base::OnceClosure callback);
@@ -583,15 +576,6 @@ class NET_EXPORT CookieMonster : public CookieStore {
int source_port,
CookieSourceScheme source_scheme);
- // Histogram variables; see CookieMonster::InitializeHistograms() in
- // cookie_monster.cc for details.
- base::HistogramBase* histogram_expiration_duration_minutes_secure_;
- base::HistogramBase* histogram_expiration_duration_minutes_non_secure_;
- base::HistogramBase* histogram_count_;
- base::HistogramBase* histogram_cookie_type_;
- base::HistogramBase* histogram_cookie_source_scheme_;
- base::HistogramBase* histogram_time_blocked_on_load_;
-
// Set of keys (eTLD+1's) for which non-expired cookies have
// been evicted for hitting the per-domain max. The size of this set is
// histogrammed periodically. The size is limited to |kMaxDomainPurgedKeys|.
diff --git a/chromium/net/cookies/cookie_monster_change_dispatcher.h b/chromium/net/cookies/cookie_monster_change_dispatcher.h
index 29a2b1ab6f9..c769efe9b99 100644
--- a/chromium/net/cookies/cookie_monster_change_dispatcher.h
+++ b/chromium/net/cookies/cookie_monster_change_dispatcher.h
@@ -29,7 +29,7 @@ class CookieMonster;
class CookieMonsterChangeDispatcher : public CookieChangeDispatcher {
public:
using CookieChangeCallbackList =
- base::CallbackList<void(const CookieChangeInfo&)>;
+ base::RepeatingCallbackList<void(const CookieChangeInfo&)>;
// Expects |cookie_monster| to outlive this.
explicit CookieMonsterChangeDispatcher(const CookieMonster* cookie_monster);
diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc
index eb883c1f524..db92d8cd2d8 100644
--- a/chromium/net/cookies/cookie_monster_unittest.cc
+++ b/chromium/net/cookies/cookie_monster_unittest.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <algorithm>
+#include <memory>
#include <string>
#include <vector>
@@ -41,6 +42,7 @@
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_monster_store_test.h" // For CookieStore mock
#include "net/cookies/cookie_store_change_unittest.h"
+#include "net/cookies/cookie_store_test_callbacks.h"
#include "net/cookies/cookie_store_test_helpers.h"
#include "net/cookies/cookie_store_unittest.h"
#include "net/cookies/cookie_util.h"
@@ -197,8 +199,9 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
}
// Helper for PredicateSeesAllCookies test; repopulates CM with same layout
- // each time.
- void PopulateCmForPredicateCheck(CookieMonster* cm) {
+ // each time. Returns the time which is strictly greater than any creation
+ // time which was passed to created cookies.
+ base::Time PopulateCmForPredicateCheck(CookieMonster* cm) {
std::string url_top_level_domain_plus_1(GURL(kTopLevelDomainPlus1).host());
std::string url_top_level_domain_plus_2(GURL(kTopLevelDomainPlus2).host());
std::string url_top_level_domain_plus_3(GURL(kTopLevelDomainPlus3).host());
@@ -217,83 +220,84 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
// * Two host path cookies (w.c.b.a/dir1, w.c.b.a/dir1/dir2)
std::vector<std::unique_ptr<CanonicalCookie>> cookies;
+ const base::Time now = base::Time::Now();
// Domain cookies
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "dom_1", "A", ".harvard.edu", "/", base::Time(), base::Time(),
- base::Time(), false, false, CookieSameSite::LAX_MODE,
- COOKIE_PRIORITY_DEFAULT, false));
+ "dom_1", "A", ".harvard.edu", "/", now, base::Time(), base::Time(),
+ false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
+ false));
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "dom_2", "B", ".math.harvard.edu", "/", base::Time(), base::Time(),
- base::Time(), false, false, CookieSameSite::LAX_MODE,
- COOKIE_PRIORITY_DEFAULT, false));
+ "dom_2", "B", ".math.harvard.edu", "/", now, base::Time(), base::Time(),
+ false, false, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
+ false));
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "dom_3", "C", ".bourbaki.math.harvard.edu", "/", base::Time(),
- base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
+ "dom_3", "C", ".bourbaki.math.harvard.edu", "/", now, base::Time(),
+ base::Time(), false, false, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT, false));
// Host cookies
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "host_1", "A", url_top_level_domain_plus_1, "/", base::Time(),
- base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
+ "host_1", "A", url_top_level_domain_plus_1, "/", now, base::Time(),
+ base::Time(), false, false, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT, false));
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "host_2", "B", url_top_level_domain_plus_2, "/", base::Time(),
- base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
+ "host_2", "B", url_top_level_domain_plus_2, "/", now, base::Time(),
+ base::Time(), false, false, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT, false));
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "host_3", "C", url_top_level_domain_plus_3, "/", base::Time(),
- base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
+ "host_3", "C", url_top_level_domain_plus_3, "/", now, base::Time(),
+ base::Time(), false, false, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT, false));
// http_only cookie
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "httpo_check", "A", url_top_level_domain_plus_2, "/", base::Time(),
- base::Time(), base::Time(), false, true, CookieSameSite::LAX_MODE,
+ "httpo_check", "A", url_top_level_domain_plus_2, "/", now, base::Time(),
+ base::Time(), false, true, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT, false));
// same-site cookie
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "same_site_check", "A", url_top_level_domain_plus_2, "/", base::Time(),
+ "same_site_check", "A", url_top_level_domain_plus_2, "/", now,
base::Time(), base::Time(), false, false, CookieSameSite::STRICT_MODE,
COOKIE_PRIORITY_DEFAULT, false));
// same-party cookie
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "same_party_check", "A", url_top_level_domain_plus_2, "/", base::Time(),
+ "same_party_check", "A", url_top_level_domain_plus_2, "/", now,
base::Time(), base::Time(), true /* secure */, false,
CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
true /* same_party */));
// Secure cookies
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "sec_dom", "A", ".math.harvard.edu", "/", base::Time(), base::Time(),
+ "sec_dom", "A", ".math.harvard.edu", "/", now, base::Time(),
base::Time(), true, false, CookieSameSite::NO_RESTRICTION,
COOKIE_PRIORITY_DEFAULT, false));
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "sec_host", "B", url_top_level_domain_plus_2, "/", base::Time(),
- base::Time(), base::Time(), true, false, CookieSameSite::NO_RESTRICTION,
+ "sec_host", "B", url_top_level_domain_plus_2, "/", now, base::Time(),
+ base::Time(), true, false, CookieSameSite::NO_RESTRICTION,
COOKIE_PRIORITY_DEFAULT, false));
// Domain path cookies
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "dom_path_1", "A", ".math.harvard.edu", "/dir1", base::Time(),
- base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
+ "dom_path_1", "A", ".math.harvard.edu", "/dir1", now, base::Time(),
+ base::Time(), false, false, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT, false));
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "dom_path_2", "B", ".math.harvard.edu", "/dir1/dir2", base::Time(),
- base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
+ "dom_path_2", "B", ".math.harvard.edu", "/dir1/dir2", now, base::Time(),
+ base::Time(), false, false, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT, false));
// Host path cookies
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "host_path_1", "A", url_top_level_domain_plus_2, "/dir1", base::Time(),
+ "host_path_1", "A", url_top_level_domain_plus_2, "/dir1", now,
base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT, false));
cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
- "host_path_2", "B", url_top_level_domain_plus_2, "/dir1/dir2",
- base::Time(), base::Time(), base::Time(), false, false,
- CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT, false));
+ "host_path_2", "B", url_top_level_domain_plus_2, "/dir1/dir2", now,
+ base::Time(), base::Time(), false, false, CookieSameSite::LAX_MODE,
+ COOKIE_PRIORITY_DEFAULT, false));
for (auto& cookie : cookies) {
GURL source_url = cookie_util::SimulatedCookieSource(
@@ -303,6 +307,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
}
EXPECT_EQ(cookies.size(), this->GetAllCookies(cm).size());
+ return now + base::TimeDelta::FromMilliseconds(100);
}
Time GetFirstCookieAccessDate(CookieMonster* cm) {
@@ -574,7 +579,7 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
std::unique_ptr<CookieMonster> cm;
if (alt_host_entries == nullptr) {
- cm.reset(new CookieMonster(nullptr, &net_log_));
+ cm = std::make_unique<CookieMonster>(nullptr, &net_log_);
} else {
// When generating all of these cookies on alternate hosts, they need to
// be all older than the max "safe" date for GC, which is currently 30
@@ -620,6 +625,9 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
CookieMonster::kDomainPurgeCookies);
auto cm = std::make_unique<CookieMonster>(nullptr, &net_log_);
+ // Key:
+ // Round 1 => LN; round 2 => LS; round 3 => MN.
+ // Round 4 => HN; round 5 => MS; round 6 => HS
// Each test case adds 181 cookies, so 31 cookies are evicted.
// Cookie same priority, repeated for each priority.
@@ -683,6 +691,9 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
CookieMonster::kDomainPurgeCookies);
auto cm = std::make_unique<CookieMonster>(nullptr, &net_log_);
+ // Key:
+ // Round 1 => LN; round 2 => LS; round 3 => MN.
+ // Round 4 => HN; round 5 => MS; round 6 => HS
// Each test case adds 181 cookies, so 31 cookies are evicted.
// Cookie same priority, repeated for each priority.
@@ -740,6 +751,9 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
CookieMonster::kDomainPurgeCookies);
auto cm = std::make_unique<CookieMonster>(nullptr, &net_log_);
+ // Key:
+ // Round 1 => LN; round 2 => LS; round 3 => MN.
+ // Round 4 => HN; round 5 => MS; round 6 => HS
// Each test case adds 180 secure cookies, and some non-secure cookie. The
// secure cookies take priority, so the non-secure cookie is removed, along
@@ -764,6 +778,18 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
// Round 4 => 1HN; round 5 => none; round 6 => 30HS.
TestPriorityCookieCase(cm.get(), "180HS 1HN", 0U, 0U, 150U, 0U, 150U);
+ // Quotas should be correctly maintained when a given priority has both
+ // secure and non-secure cookies.
+ //
+ // Round 1 => 10LN; round 2 => none; round 3 => none.
+ // Round 4 => 21HN; round 5 => none; round 6 => none.
+ TestPriorityCookieCase(cm.get(), "39LN 1LS 141HN", 30U, 0U, 120U, 149U,
+ 1U);
+ // Round 1 => none; round 2 => none; round 3 => 10MN.
+ // Round 4 => none; round 5 => none; round 6 => 21HS.
+ TestPriorityCookieCase(cm.get(), "29LN 1LS 59MN 1MS 91HS", 30U, 50U, 70U,
+ 78U, 72U);
+
// Low-priority secure cookies are removed before higher priority non-secure
// cookies.
// Round 1 => none; round 2 => 31LS; round 3 => none.
@@ -1752,17 +1778,19 @@ TEST_F(CookieMonsterTest, GetExcludedCookiesForURLPathMatching) {
TEST_F(CookieMonsterTest, CookieSorting) {
std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_));
-
- EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B1; path=/"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B2; path=/foo"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B3; path=/foo/bar"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A1; path=/"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A2; path=/foo"));
- EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "A=A3; path=/foo/bar"));
+ base::Time system_time = base::Time::Now();
+ for (const char* cookie_line :
+ {"B=B1; path=/", "B=B2; path=/foo", "B=B3; path=/foo/bar",
+ "A=A1; path=/", "A=A2; path=/foo", "A=A3; path=/foo/bar"}) {
+ EXPECT_TRUE(SetCookieWithSystemTime(cm.get(), http_www_foo_.url(),
+ cookie_line, system_time));
+ system_time += base::TimeDelta::FromMilliseconds(100);
+ }
// Re-set cookie which should not change sort order, as the creation date
// will be retained, as per RFC 6265 5.3.11.3.
- EXPECT_TRUE(SetCookie(cm.get(), http_www_foo_.url(), "B=B3; path=/foo/bar"));
+ EXPECT_TRUE(SetCookieWithSystemTime(cm.get(), http_www_foo_.url(),
+ "B=B3; path=/foo/bar", system_time));
CookieList cookies = GetAllCookies(cm.get());
ASSERT_EQ(6u, cookies.size());
@@ -1949,10 +1977,10 @@ TEST_F(CookieMonsterTest, ImportDuplicateCreationTimes) {
TEST_F(CookieMonsterTest, PredicateSeesAllCookies) {
std::unique_ptr<CookieMonster> cm(new CookieMonster(nullptr, &net_log_));
- PopulateCmForPredicateCheck(cm.get());
+ const base::Time now = PopulateCmForPredicateCheck(cm.get());
// We test that we can see all cookies with |delete_info|. This includes
// host, http_only, host secure, and all domain cookies.
- CookieDeletionInfo delete_info(base::Time(), base::Time::Now());
+ CookieDeletionInfo delete_info(base::Time(), now);
delete_info.value_for_testing = "A";
EXPECT_EQ(8u, DeleteAllMatchingInfo(cm.get(), std::move(delete_info)));
@@ -2450,7 +2478,7 @@ TEST_F(CookieMonsterTest, FlushStore) {
ASSERT_EQ(2, counter->callback_count());
// If there's no backing store, FlushStore() is always a safe no-op.
- cm.reset(new CookieMonster(nullptr, &net_log_));
+ cm = std::make_unique<CookieMonster>(nullptr, &net_log_);
GetAllCookies(cm.get()); // Force init.
cm->FlushStore(base::DoNothing());
base::RunLoop().RunUntilIdle();
@@ -2523,8 +2551,7 @@ TEST_F(CookieMonsterTest, SetAllCookies) {
NetLogEventPhase::END);
}
-// Check that DeleteAll does flush (as a sanity check that flush_count()
-// works).
+// Check that DeleteAll does flush (as a quick check that flush_count() works).
TEST_F(CookieMonsterTest, DeleteAll) {
scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
auto cm = std::make_unique<CookieMonster>(store.get(), &net_log_);
@@ -2677,6 +2704,7 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) {
const Time now1(Time::Now());
const Time now2(Time::Now() + TimeDelta::FromSeconds(1));
const Time now3(Time::Now() + TimeDelta::FromSeconds(2));
+ const Time now4(Time::Now() + TimeDelta::FromSeconds(3));
const Time later(now1 + TimeDelta::FromDays(1));
const GURL url("http://host/path");
const std::string domain("host");
@@ -2688,18 +2716,29 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) {
AddCookieToList(url, "foo=bar; path=" + path, now1, &initial_cookies);
- // We have to manually build this cookie because it contains a control
- // character, and our cookie line parser rejects control characters.
+ // We have to manually build these cookies because they contain control
+ // characters, and our cookie line parser rejects control characters.
std::unique_ptr<CanonicalCookie> cc =
CanonicalCookie::CreateUnsafeCookieForTesting(
"baz",
"\x05"
"boo",
- "." + domain, path, now2, later, base::Time(), false, false,
- CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
+ "." + domain, path, now2, later, base::Time(), true /* secure */,
+ false /* httponly */, CookieSameSite::NO_RESTRICTION,
+ COOKIE_PRIORITY_DEFAULT, false /* sameparty */);
initial_cookies.push_back(std::move(cc));
- AddCookieToList(url, "hello=world; path=" + path, now3, &initial_cookies);
+ std::unique_ptr<CanonicalCookie> cc2 =
+ CanonicalCookie::CreateUnsafeCookieForTesting(
+ "baz",
+ "\x7F"
+ "boo",
+ "." + domain, path, now3, later, base::Time(), true /* secure */,
+ false /* httponly */, CookieSameSite::NO_RESTRICTION,
+ COOKIE_PRIORITY_DEFAULT, false /* sameparty */);
+ initial_cookies.push_back(std::move(cc2));
+
+ AddCookieToList(url, "hello=world; path=" + path, now4, &initial_cookies);
// Inject our initial cookies into the mock PersistentCookieStore.
store->SetLoadExpectation(true, std::move(initial_cookies));
@@ -4666,6 +4705,68 @@ TEST_F(CookieMonsterTest, CookiePortReadDiffersFromSetHistogram) {
CookieMonster::CookieSentToSamePort::kYes, 2);
}
+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_log_));
+
+ histograms.ExpectTotalCount(kHistogramName, 0);
+
+ struct TestCase {
+ CookieSourceSchemeName enum_value;
+ std::string scheme;
+ };
+
+ // Test the usual and a smattering of some other types including a kOther.
+ // It doesn't matter if we add this to the scheme registry or not because we
+ // don't actually need the whole url to parse, we just need GURL to pick up on
+ // the scheme correctly (which it does). What the rest of the cookie code does
+ // with the oddly formed GURL is out of scope of this test (i.e. we don't
+ // care).
+ const TestCase kTestCases[] = {
+ {CookieSourceSchemeName::kHttpsScheme, url::kHttpsScheme},
+ {CookieSourceSchemeName::kHttpScheme, url::kHttpScheme},
+ {CookieSourceSchemeName::kWssScheme, url::kWssScheme},
+ {CookieSourceSchemeName::kWsScheme, url::kWsScheme},
+ {CookieSourceSchemeName::kChromeExtensionScheme, "chrome-extension"},
+ {CookieSourceSchemeName::kFileScheme, url::kFileScheme},
+ {CookieSourceSchemeName::kQuicTransportScheme, url::kQuicTransportScheme},
+ {CookieSourceSchemeName::kOther, "abcd1234"}};
+
+ // Make sure all the schemes are considered cookieable.
+ std::vector<std::string> schemes;
+ for (auto test_case : kTestCases) {
+ schemes.push_back(test_case.scheme);
+ }
+ ResultSavingCookieCallback<bool> cookie_scheme_callback;
+ cm->SetCookieableSchemes(schemes, cookie_scheme_callback.MakeCallback());
+ cookie_scheme_callback.WaitUntilDone();
+ ASSERT_TRUE(cookie_scheme_callback.result());
+
+ const char kUrl[] = "://www.foo.com";
+ int count = 0;
+
+ // Test all the cases.
+ for (auto test_case : kTestCases) {
+ histograms.ExpectBucketCount(kHistogramName, test_case.enum_value, 0);
+
+ EXPECT_TRUE(SetCookie(cm.get(), GURL(test_case.scheme + kUrl), "A=B"));
+
+ histograms.ExpectBucketCount(kHistogramName, test_case.enum_value, 1);
+ histograms.ExpectTotalCount(kHistogramName, ++count);
+ }
+
+ // This metric is only for cookies that are actually set. Make sure the
+ // histogram doesn't increment for cookies that fail to set.
+
+ // Try to set an invalid cookie, for instance: a non-cookieable scheme will be
+ // rejected.
+ EXPECT_FALSE(SetCookie(cm.get(), GURL("invalidscheme://foo.com"), "A=B"));
+ histograms.ExpectTotalCount(kHistogramName, count);
+}
+
class FirstPartySetEnabledCookieMonsterTest : public CookieMonsterTest {
public:
FirstPartySetEnabledCookieMonsterTest()
diff --git a/chromium/net/cookies/cookie_store_unittest.h b/chromium/net/cookies/cookie_store_unittest.h
index 26857ee51b5..31f702c2d25 100644
--- a/chromium/net/cookies/cookie_store_unittest.h
+++ b/chromium/net/cookies/cookie_store_unittest.h
@@ -195,9 +195,11 @@ class CookieStoreTest : public testing::Test {
const GURL& url,
const std::string& cookie_line,
const CookieOptions& options,
- base::Optional<base::Time> server_time = base::nullopt) {
- auto cookie = CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
- server_time);
+ base::Optional<base::Time> server_time = base::nullopt,
+ base::Optional<base::Time> system_time = base::nullopt) {
+ auto cookie = CanonicalCookie::Create(
+ url, cookie_line, system_time.value_or(base::Time::Now()), server_time);
+
if (!cookie)
return false;
DCHECK(cs);
@@ -225,6 +227,19 @@ class CookieStoreTest : public testing::Test {
return callback.result().status.IsInclude();
}
+ bool SetCookieWithSystemTime(CookieStore* cs,
+ const GURL& url,
+ const std::string& cookie_line,
+ const base::Time& system_time) {
+ CookieOptions options;
+ if (!CookieStoreTestTraits::supports_http_only)
+ options.set_include_httponly();
+ options.set_same_site_cookie_context(
+ net::CookieOptions::SameSiteCookieContext::MakeInclusive());
+ return CreateAndSetCookie(cs, url, cookie_line, options, base::nullopt,
+ base::make_optional(system_time));
+ }
+
bool SetCookieWithServerTime(CookieStore* cs,
const GURL& url,
const std::string& cookie_line,
diff --git a/chromium/net/cookies/cookie_util.cc b/chromium/net/cookies/cookie_util.cc
index ddcccc2a531..16c3c5e8f95 100644
--- a/chromium/net/cookies/cookie_util.cc
+++ b/chromium/net/cookies/cookie_util.cc
@@ -94,17 +94,30 @@ bool SaturatedTimeFromUTCExploded(const base::Time::Exploded& exploded,
// schemeful_context, i.e. whether scheme should be considered when comparing
// two sites.
//
+// The bool in the return value is whether the ContextType return value was
+// affected by bugfix 1166211, used for CookieInclusionStatus warnings and
+// histogramming.
+// TODO(crbug.com/1166211): Remove when no longer needed.
+//
// See documentation of `ComputeSameSiteContextForRequest` for explanations of
// other parameters.
std::pair<ContextType, bool> ComputeSameSiteContext(
- const GURL& url,
+ const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const base::Optional<url::Origin>& initiator,
bool is_http,
bool is_main_frame_navigation,
bool compute_schemefully) {
+ DCHECK(!url_chain.empty());
+ const GURL& request_url = url_chain.back();
+ const auto is_same_site_with_site_for_cookies =
+ [&site_for_cookies, compute_schemefully](const GURL& url) {
+ return site_for_cookies.IsFirstPartyWithSchemefulMode(
+ url, compute_schemefully);
+ };
+
bool site_for_cookies_is_same_site =
- site_for_cookies.IsFirstPartyWithSchemefulMode(url, compute_schemefully);
+ is_same_site_with_site_for_cookies(request_url);
// If the request is a main frame navigation, site_for_cookies must either be
// null (for opaque origins, e.g., data: origins) or same-site with the
@@ -112,38 +125,50 @@ std::pair<ContextType, bool> ComputeSameSiteContext(
// ws/wss (these schemes are not navigable).
DCHECK(!is_main_frame_navigation || site_for_cookies_is_same_site ||
site_for_cookies.IsNull());
- DCHECK(!is_main_frame_navigation || !url.SchemeIsWSOrWSS());
-
- bool affected_by_bugfix_1166211 = false;
- if (site_for_cookies_is_same_site) {
- // Create a SiteForCookies object from the initiator so that we can reuse
- // IsFirstPartyWithSchemefulMode().
- if (!initiator ||
- SiteForCookies::FromOrigin(initiator.value())
- .IsFirstPartyWithSchemefulMode(url, compute_schemefully)) {
- return {ContextType::SAME_SITE_STRICT, false};
- }
+ DCHECK(!is_main_frame_navigation || !request_url.SchemeIsWSOrWSS());
+
+ if (!site_for_cookies_is_same_site)
+ return {ContextType::CROSS_SITE, false};
+
+ // Create a SiteForCookies object from the initiator so that we can reuse
+ // IsFirstPartyWithSchemefulMode().
+ bool same_site_initiator =
+ !initiator ||
+ SiteForCookies::FromOrigin(initiator.value())
+ .IsFirstPartyWithSchemefulMode(request_url, compute_schemefully);
+
+ // Check that the URLs in the redirect chain are all same-site with the
+ // site_for_cookies and hence (by transitivity) same-site with the request
+ // URL. (If the URL chain only has one member, it's the request_url and we've
+ // already checked it previously.)
+ bool same_site_redirect_chain =
+ url_chain.size() == 1u ||
+ base::ranges::all_of(url_chain, is_same_site_with_site_for_cookies);
+
+ if (same_site_initiator &&
+ (!base::FeatureList::IsEnabled(
+ features::kCookieSameSiteConsidersRedirectChain) ||
+ same_site_redirect_chain)) {
+ return {ContextType::SAME_SITE_STRICT, false};
+ }
- if (is_http) {
- base::UmaHistogramBoolean("Cookie.SameSiteContextAffectedByBugfix1166211",
- !is_main_frame_navigation);
- }
+ if (is_http) {
+ base::UmaHistogramBoolean("Cookie.SameSiteContextAffectedByBugfix1166211",
+ !is_main_frame_navigation);
+ }
- // Preserve old behavior if the bugfix is disabled.
- if (!base::FeatureList::IsEnabled(features::kSameSiteCookiesBugfix1166211))
- return {ContextType::SAME_SITE_LAX, false};
+ // Preserve old behavior if the bugfix is disabled.
+ if (!base::FeatureList::IsEnabled(features::kSameSiteCookiesBugfix1166211))
+ return {ContextType::SAME_SITE_LAX, false};
- if (!is_http || is_main_frame_navigation) {
- return {ContextType::SAME_SITE_LAX, false};
- } else if (is_http) {
- affected_by_bugfix_1166211 = true;
- }
- }
- return {ContextType::CROSS_SITE, affected_by_bugfix_1166211};
+ if (!is_http || is_main_frame_navigation)
+ return {ContextType::SAME_SITE_LAX, false};
+
+ return {ContextType::CROSS_SITE, true};
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSet(
- const GURL& url,
+ const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const base::Optional<url::Origin>& initiator,
bool is_http,
@@ -151,10 +176,10 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSet(
CookieOptions::SameSiteCookieContext same_site_context;
same_site_context.set_context(ComputeSameSiteContext(
- url, site_for_cookies, initiator, is_http, is_main_frame_navigation,
+ url_chain, site_for_cookies, initiator, is_http, is_main_frame_navigation,
false /* compute_schemefully */));
same_site_context.set_schemeful_context(ComputeSameSiteContext(
- url, site_for_cookies, initiator, is_http, is_main_frame_navigation,
+ url_chain, site_for_cookies, initiator, is_http, is_main_frame_navigation,
true /* compute_schemefully */));
// Setting any SameSite={Strict,Lax} cookie only requires a LAX context, so
@@ -510,7 +535,7 @@ std::string SerializeRequestCookieLine(
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForRequest(
const std::string& http_method,
- const GURL& url,
+ const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const base::Optional<url::Origin>& initiator,
bool is_main_frame_navigation,
@@ -547,10 +572,10 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForRequest(
CookieOptions::SameSiteCookieContext same_site_context;
same_site_context.set_context(ComputeSameSiteContext(
- url, site_for_cookies, initiator, true /* is_http */,
+ url_chain, site_for_cookies, initiator, true /* is_http */,
is_main_frame_navigation, false /* compute_schemefully */));
same_site_context.set_schemeful_context(ComputeSameSiteContext(
- url, site_for_cookies, initiator, true /* is_http */,
+ url_chain, site_for_cookies, initiator, true /* is_http */,
is_main_frame_navigation, true /* compute_schemefully */));
// If the method is safe, the context is Lax. Otherwise, make a note that
@@ -578,18 +603,20 @@ ComputeSameSiteContextForScriptGet(const GURL& url,
CookieOptions::SameSiteCookieContext same_site_context;
+ // We don't check the redirect chain for script access to cookies (only the
+ // URL itself).
same_site_context.set_context(ComputeSameSiteContext(
- url, site_for_cookies, initiator, false /* is_http */,
+ {url}, site_for_cookies, initiator, false /* is_http */,
false /* is_main_frame_navigation */, false /* compute_schemefully */));
same_site_context.set_schemeful_context(ComputeSameSiteContext(
- url, site_for_cookies, initiator, false /* is_http */,
+ {url}, site_for_cookies, initiator, false /* is_http */,
false /* is_main_frame_navigation */, true /* compute_schemefully */));
return same_site_context;
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForResponse(
- const GURL& url,
+ const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const base::Optional<url::Origin>& initiator,
bool is_main_frame_navigation,
@@ -597,17 +624,19 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForResponse(
if (force_ignore_site_for_cookies)
return CookieOptions::SameSiteCookieContext::MakeInclusiveForSet();
+ DCHECK(!url_chain.empty());
if (is_main_frame_navigation && !site_for_cookies.IsNull()) {
// If the request is a main frame navigation, site_for_cookies must either
// be null (for opaque origins, e.g., data: origins) or same-site with the
// request URL (both schemefully and schemelessly), and the URL cannot be
// ws/wss (these schemes are not navigable).
- DCHECK(site_for_cookies.IsFirstPartyWithSchemefulMode(url, true));
- DCHECK(!url.SchemeIsWSOrWSS());
+ DCHECK(
+ site_for_cookies.IsFirstPartyWithSchemefulMode(url_chain.back(), true));
+ DCHECK(!url_chain.back().SchemeIsWSOrWSS());
return CookieOptions::SameSiteCookieContext::MakeInclusiveForSet();
}
- return ComputeSameSiteContextForSet(url, site_for_cookies, initiator,
+ return ComputeSameSiteContextForSet(url_chain, site_for_cookies, initiator,
true /* is_http */,
is_main_frame_navigation);
}
@@ -621,10 +650,11 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForScriptSet(
// It doesn't matter what initiator origin we pass here. Either way, the
// context will be considered same-site iff the site_for_cookies is same-site
- // with the url.
+ // with the url. We don't check the redirect chain for script access to
+ // cookies (only the URL itself).
return ComputeSameSiteContextForSet(
- url, site_for_cookies, base::nullopt /* initiator */, false /* is_http */,
- false /* is_main_frame_navigation */);
+ {url}, site_for_cookies, base::nullopt /* initiator */,
+ false /* is_http */, false /* is_main_frame_navigation */);
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSubresource(
@@ -675,17 +705,23 @@ bool IsFirstPartySetsEnabled() {
// 2) `isolation_info.party_context` is null.
// 3) `cookie_access_delegate.IsContextSamePartyWithSite` returns false.
CookieOptions::SamePartyCookieContextType ComputeSamePartyContext(
- const net::SchemefulSite& request_site,
+ const SchemefulSite& request_site,
const IsolationInfo& isolation_info,
- const CookieAccessDelegate* cookie_access_delegate) {
+ const CookieAccessDelegate* cookie_access_delegate,
+ bool force_ignore_top_frame_party) {
if (!isolation_info.IsEmpty() && isolation_info.party_context().has_value() &&
cookie_access_delegate &&
cookie_access_delegate->IsContextSamePartyWithSite(
request_site,
- isolation_info.network_isolation_key().GetTopFrameSite().value(),
+ force_ignore_top_frame_party
+ ? base::nullopt
+ : base::make_optional(isolation_info.network_isolation_key()
+ .GetTopFrameSite()
+ .value()),
isolation_info.party_context().value())) {
return CookieOptions::SamePartyCookieContextType::kSameParty;
}
+
return CookieOptions::SamePartyCookieContextType::kCrossParty;
}
diff --git a/chromium/net/cookies/cookie_util.h b/chromium/net/cookies/cookie_util.h
index 4ffa877c4ff..cfb57b4bf93 100644
--- a/chromium/net/cookies/cookie_util.h
+++ b/chromium/net/cookies/cookie_util.h
@@ -140,11 +140,17 @@ NET_EXPORT void ParseRequestCookieLine(const std::string& header_value,
NET_EXPORT std::string SerializeRequestCookieLine(
const ParsedRequestCookies& parsed_cookies);
-// Determines which of the cookies for `url` can be accessed, with respect to
-// the SameSite attribute. This applies to looking up existing cookies for HTTP
-// requests. For looking up cookies for non-HTTP APIs (i.e., JavaScript), see
-// ComputeSameSiteContextForScriptGet. For setting new cookies, see
-// ComputeSameSiteContextForResponse and ComputeSameSiteContextForScriptSet.
+// Determines which of the cookies for the request URL can be accessed, with
+// respect to the SameSite attribute. This applies to looking up existing
+// cookies for HTTP requests. For looking up cookies for non-HTTP APIs (i.e.,
+// JavaScript), see ComputeSameSiteContextForScriptGet. For setting new cookies,
+// see ComputeSameSiteContextForResponse and ComputeSameSiteContextForScriptSet.
+//
+// `url_chain` is a non-empty vector of URLs, the last of which is the current
+// request URL. It represents the redirect chain of the current request. The
+// redirect chain is used to calculate whether there has been a cross-site
+// redirect. In order for a context to be deemed strictly same-site, there must
+// not have been any cross-site redirects.
//
// `site_for_cookies` is the currently navigated to site that should be
// considered "first-party" for cookies.
@@ -175,7 +181,7 @@ NET_EXPORT std::string SerializeRequestCookieLine(
// when the method is "safe" in the RFC7231 section 4.2.1 sense.
NET_EXPORT CookieOptions::SameSiteCookieContext
ComputeSameSiteContextForRequest(const std::string& http_method,
- const GURL& url,
+ const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const base::Optional<url::Origin>& initiator,
bool is_main_frame_navigation,
@@ -190,16 +196,20 @@ ComputeSameSiteContextForScriptGet(const GURL& url,
const base::Optional<url::Origin>& initiator,
bool force_ignore_site_for_cookies);
-// Determines which of the cookies for `url` can be set from a network response,
-// with respect to the SameSite attribute. This will only return CROSS_SITE or
-// SAME_SITE_LAX (cookie sets of SameSite=strict cookies are permitted in same
-// contexts that sets of SameSite=lax cookies are).
+// Determines which of the cookies for the request URL can be set from a network
+// response, with respect to the SameSite attribute. This will only return
+// CROSS_SITE or SAME_SITE_LAX (cookie sets of SameSite=strict cookies are
+// permitted in same contexts that sets of SameSite=lax cookies are).
+// `url_chain` is a non-empty vector of URLs, the last of which is the current
+// request URL. It represents the redirect chain of the current request. The
+// redirect chain is used to calculate whether there has been a cross-site
+// redirect.
// `is_main_frame_navigation` is whether the request was for a navigation that
// targets the main frame or top-level browsing context. Both SameSite=Lax and
// SameSite=Strict cookies may be set by any main frame navigation.
// If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_LAX.
NET_EXPORT CookieOptions::SameSiteCookieContext
-ComputeSameSiteContextForResponse(const GURL& url,
+ComputeSameSiteContextForResponse(const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const base::Optional<url::Origin>& initiator,
bool is_main_frame_navigation,
@@ -231,15 +241,19 @@ NET_EXPORT bool IsSchemefulSameSiteEnabled();
NET_EXPORT bool IsFirstPartySetsEnabled();
-// Compute SameParty context, determines which of the cookies for `request_url`
+// Compute SameParty context, determines which of the cookies for `request_site`
// can be accessed. Returns either kCrossParty or kSameParty. `isolation_info`
// must be fully populated. In Chrome, all requests with credentials enabled
// have a fully populated IsolationInfo. But that might not be true for other
-// embedders yet (including cast, WebView, etc). Also not sure about iOS.
+// embedders yet (including cast, WebView, etc). Also not sure about iOS. If
+// `force_ignore_top_frame_party` is true, the top frame from `isolation_info`
+// will be assumed to be same-party with `request_site`, regardless of what it
+// is.
NET_EXPORT CookieOptions::SamePartyCookieContextType ComputeSamePartyContext(
- const net::SchemefulSite& request_url,
+ const SchemefulSite& request_site,
const IsolationInfo& isolation_info,
- const CookieAccessDelegate* cookie_access_delegate);
+ const CookieAccessDelegate* cookie_access_delegate,
+ bool force_ignore_top_frame_party);
// Get the SameParty inclusion status. If the cookie is not SameParty, returns
// kNoSamePartyEnforcement; if the cookie is SameParty but does not have a
diff --git a/chromium/net/cookies/cookie_util_unittest.cc b/chromium/net/cookies/cookie_util_unittest.cc
index 6ab7ddfbc7c..c4ff622fc99 100644
--- a/chromium/net/cookies/cookie_util_unittest.cc
+++ b/chromium/net/cookies/cookie_util_unittest.cc
@@ -9,6 +9,7 @@
#include "base/callback.h"
#include "base/containers/contains.h"
#include "base/optional.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
@@ -351,20 +352,36 @@ MATCHER_P2(ContextTypeIsWithSchemefulMode, context_type, schemeful, "") {
return context_type == (schemeful ? arg.schemeful_context() : arg.context());
}
+std::string UrlChainToString(const std::vector<GURL>& url_chain) {
+ std::string s;
+ for (const GURL& url : url_chain) {
+ base::StrAppend(&s, {" ", url.spec()});
+ }
+ return s;
+}
+
// Tests for the various ComputeSameSiteContextFor*() functions. The first
// boolean test param is whether the results of the computations are evaluated
// schemefully. The second boolean test param is whether the fix for
-// crbug.com/1166211 is enabled.
+// crbug.com/1166211 is enabled. The third boolean param is whether SameSite
+// considers redirect chains.
class CookieUtilComputeSameSiteContextTest
- : public ::testing::TestWithParam<std::tuple<bool, bool>> {
+ : public ::testing::TestWithParam<std::tuple<bool, bool, bool>> {
public:
CookieUtilComputeSameSiteContextTest() {
- // No need to explicitly enable the feature because it is enabled by
- // default.
- if (!IsBugfix1166211Enabled()) {
- feature_list_.InitAndDisableFeature(
- features::kSameSiteCookiesBugfix1166211);
+ std::vector<base::Feature> enabled_features;
+ std::vector<base::Feature> disabled_features;
+ // No need to explicitly enable the Bugfix1166211 feature because it
+ // is enabled by default.
+ if (!IsBugfix1166211Enabled())
+ disabled_features.push_back(features::kSameSiteCookiesBugfix1166211);
+ // No need to explicitly disable the redirect chain feature because it
+ // is disabled by default.
+ if (DoesSameSiteConsiderRedirectChain()) {
+ enabled_features.push_back(
+ features::kCookieSameSiteConsidersRedirectChain);
}
+ feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
~CookieUtilComputeSameSiteContextTest() override = default;
@@ -375,13 +392,17 @@ class CookieUtilComputeSameSiteContextTest
bool IsBugfix1166211Enabled() const { return std::get<1>(GetParam()); }
+ bool DoesSameSiteConsiderRedirectChain() const {
+ return std::get<2>(GetParam());
+ }
+
// Returns the proper gtest matcher to use for the schemeless/schemeful mode.
auto ContextTypeIs(ContextType context_type) const {
return ContextTypeIsWithSchemefulMode(context_type, IsSchemeful());
}
- // The following methods return the sets of URLs/SiteForCookies/initiators
- // that are same-site or cross-site with respect to kSiteUrl.
+ // The following methods return the sets of URLs/SiteForCookies/initiators/URL
+ // chains that are same-site or cross-site with respect to kSiteUrl.
std::vector<GURL> GetAllUrls() const {
return {kSiteUrl,
@@ -409,6 +430,16 @@ class CookieUtilComputeSameSiteContextTest
return same_site_urls;
}
+ std::vector<GURL> GetCrossSiteUrls() const {
+ std::vector<GURL> cross_site_urls;
+ std::vector<GURL> same_site_urls = GetSameSiteUrls();
+ for (const GURL& url : GetAllUrls()) {
+ if (!base::Contains(same_site_urls, url))
+ cross_site_urls.push_back(url);
+ }
+ return cross_site_urls;
+ }
+
std::vector<SiteForCookies> GetAllSitesForCookies() const {
return {kNullSiteForCookies, kSiteForCookies, kSecureSiteForCookies,
kCrossSiteForCookies, kSecureCrossSiteForCookies};
@@ -467,6 +498,36 @@ class CookieUtilComputeSameSiteContextTest
return cross_site_initiators;
}
+ // Returns an assortment of redirect chains that end in `url` as the
+ // current request URL, and are completely same-site. `url` is expected to be
+ // same-site to kSiteUrl.
+ std::vector<std::vector<GURL>> GetSameSiteUrlChains(const GURL& url) const {
+ std::vector<std::vector<GURL>> same_site_url_chains;
+ for (const GURL& same_site_url : GetSameSiteUrls()) {
+ same_site_url_chains.push_back({same_site_url, url});
+ for (const GURL& other_same_site_url : GetSameSiteUrls()) {
+ same_site_url_chains.push_back(
+ {other_same_site_url, same_site_url, url});
+ }
+ }
+ return same_site_url_chains;
+ }
+
+ // Returns an assortment of redirect chains that end in `url` as the
+ // current request URL, and are cross-site. `url` is expected to be same-site
+ // to kSiteUrl.
+ std::vector<std::vector<GURL>> GetCrossSiteUrlChains(const GURL& url) const {
+ std::vector<std::vector<GURL>> cross_site_url_chains;
+ for (const GURL& cross_site_url : GetCrossSiteUrls()) {
+ cross_site_url_chains.push_back({cross_site_url, url});
+ for (const GURL& same_site_url : GetSameSiteUrls()) {
+ cross_site_url_chains.push_back({cross_site_url, same_site_url, url});
+ cross_site_url_chains.push_back({same_site_url, cross_site_url, url});
+ }
+ }
+ return cross_site_url_chains;
+ }
+
// Computes possible values of is_main_frame_navigation that are consistent
// with the DCHECKs.
bool CanBeMainFrameNavigation(const GURL& url,
@@ -545,13 +606,28 @@ TEST_P(CookieUtilComputeSameSiteContextTest, UrlAndSiteForCookiesCrossSite) {
for (bool is_main_frame_navigation :
IsMainFrameNavigationPossibleValues(url, site_for_cookies)) {
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
+ is_main_frame_navigation,
+ false /* force_ignore_site_for_cookies */),
+ ContextTypeIs(ContextType::CROSS_SITE));
+ EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
+ {url}, site_for_cookies, initiator,
is_main_frame_navigation,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::CROSS_SITE));
+ // If the current request URL is cross-site to the site-for-cookies,
+ // the request context is always cross-site even if the URL chain
+ // contains members that are same-site to the site-for-cookies.
+ EXPECT_THAT(
+ cookie_util::ComputeSameSiteContextForRequest(
+ method, {site_for_cookies.RepresentativeUrl(), url},
+ site_for_cookies, initiator, is_main_frame_navigation,
+ false /* force_ignore_site_for_cookies */),
+ ContextTypeIs(ContextType::CROSS_SITE));
EXPECT_THAT(
cookie_util::ComputeSameSiteContextForResponse(
- url, site_for_cookies, initiator, is_main_frame_navigation,
+ {site_for_cookies.RepresentativeUrl(), url},
+ site_for_cookies, initiator, is_main_frame_navigation,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::CROSS_SITE));
}
@@ -592,12 +668,12 @@ TEST_P(CookieUtilComputeSameSiteContextTest, SiteForCookiesNotSchemefullySame) {
// If the site-for-cookies isn't schemefully_same, this cannot be a
// main frame navigation.
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::CROSS_SITE));
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
- url, site_for_cookies, initiator,
+ {url}, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::CROSS_SITE));
@@ -615,7 +691,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, SiteForCookiesNotSchemefullySame) {
TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptGet) {
for (const GURL& url : GetSameSiteUrls()) {
// Same-site site-for-cookies.
- // (Cross-site cases covered above in UrlAndSiteForCookiesCrosSite test.)
+ // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
for (const SiteForCookies& site_for_cookies :
GetSameSiteSitesForCookies()) {
// Cross-site initiator -> it's same-site lax.
@@ -685,10 +761,11 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptGet_WebSocketSchemes) {
ContextTypeIs(ContextType::SAME_SITE_LAX));
}
+// Test cases where the URL chain has 1 member (i.e. no redirects).
TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
for (const GURL& url : GetSameSiteUrls()) {
// Same-site site-for-cookies.
- // (Cross-site cases covered above in UrlAndSiteForCookiesCrosSite test.)
+ // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
for (const SiteForCookies& site_for_cookies :
GetSameSiteSitesForCookies()) {
// Same-Site initiator -> it's same-site strict.
@@ -698,7 +775,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
for (bool is_main_frame_navigation :
IsMainFrameNavigationPossibleValues(url, site_for_cookies)) {
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
is_main_frame_navigation,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_STRICT));
@@ -714,7 +791,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
if (!CanBeMainFrameNavigation(url, site_for_cookies))
break;
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
true /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_LAX));
@@ -723,7 +800,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
if (!CanBeMainFrameNavigation(url, site_for_cookies))
break;
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
true /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_LAX_METHOD_UNSAFE));
@@ -735,7 +812,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
if (IsBugfix1166211Enabled()) {
for (const std::string& method : {"GET", "POST", "PUT", "HEAD"}) {
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::CROSS_SITE));
@@ -743,7 +820,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
} else {
for (const std::string& method : {"GET", "HEAD"}) {
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_LAX));
@@ -751,7 +828,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
for (const std::string& method : {"POST", "PUT"}) {
EXPECT_THAT(
cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_LAX_METHOD_UNSAFE));
@@ -774,13 +851,13 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_SchemefulDowngrade) {
EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForRequest(
- method, kSecureSiteUrl, kSiteForCookies, kSiteInitiator,
+ method, {kSecureSiteUrl}, kSiteForCookies, kSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForRequest(
- method, kSiteUrl, kSecureSiteForCookies, kSiteInitiator,
+ method, {kSiteUrl}, kSecureSiteForCookies, kSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
}
@@ -800,25 +877,25 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_SchemefulDowngrade) {
EXPECT_EQ(
SameSiteCookieContext(ContextType::SAME_SITE_STRICT, lax_if_main_frame),
cookie_util::ComputeSameSiteContextForRequest(
- "GET", kSecureSiteUrl, kSecureSiteForCookies, kSiteInitiator,
+ "GET", {kSecureSiteUrl}, kSecureSiteForCookies, kSiteInitiator,
is_main_frame_navigation,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(
SameSiteCookieContext(ContextType::SAME_SITE_STRICT, lax_if_main_frame),
cookie_util::ComputeSameSiteContextForRequest(
- "GET", kSiteUrl, kSiteForCookies, kSecureSiteInitiator,
+ "GET", {kSiteUrl}, kSiteForCookies, kSecureSiteInitiator,
is_main_frame_navigation,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
lax_unsafe_if_main_frame),
cookie_util::ComputeSameSiteContextForRequest(
- "POST", kSecureSiteUrl, kSecureSiteForCookies, kSiteInitiator,
- is_main_frame_navigation,
+ "POST", {kSecureSiteUrl}, kSecureSiteForCookies,
+ kSiteInitiator, is_main_frame_navigation,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
lax_unsafe_if_main_frame),
cookie_util::ComputeSameSiteContextForRequest(
- "POST", kSiteUrl, kSiteForCookies, kSecureSiteInitiator,
+ "POST", {kSiteUrl}, kSiteForCookies, kSecureSiteInitiator,
is_main_frame_navigation,
false /* force_ignore_site_for_cookies */));
}
@@ -834,24 +911,24 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_SchemefulDowngrade) {
: ContextType::SAME_SITE_LAX_METHOD_UNSAFE;
EXPECT_EQ(SameSiteCookieContext(incorrectly_lax, ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForRequest(
- "GET", kSiteUrl, kSecureSiteForCookies, kCrossSiteInitiator,
+ "GET", {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(SameSiteCookieContext(incorrectly_lax, ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForRequest(
- "GET", kSecureSiteUrl, kSiteForCookies, kCrossSiteInitiator,
+ "GET", {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(
SameSiteCookieContext(incorrectly_lax_unsafe, ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForRequest(
- "POST", kSiteUrl, kSecureSiteForCookies, kCrossSiteInitiator,
+ "POST", {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(
SameSiteCookieContext(incorrectly_lax_unsafe, ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForRequest(
- "POST", kSecureSiteUrl, kSiteForCookies, kCrossSiteInitiator,
+ "POST", {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
}
@@ -864,35 +941,159 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_WebSocketSchemes) {
: ContextType::SAME_SITE_LAX;
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- "GET", kWssUrl, kSecureSiteForCookies, kSecureSiteInitiator,
+ "GET", {kWssUrl}, kSecureSiteForCookies, kSecureSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_STRICT));
EXPECT_THAT(
cookie_util::ComputeSameSiteContextForRequest(
- "GET", kWssUrl, kSecureSiteForCookies, kSecureCrossSiteInitiator,
+ "GET", {kWssUrl}, kSecureSiteForCookies, kSecureCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(incorrectly_lax));
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- "GET", kWsUrl, kSiteForCookies, kSiteInitiator,
+ "GET", {kWsUrl}, kSiteForCookies, kSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_STRICT));
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- "GET", kWsUrl, kSiteForCookies, kCrossSiteInitiator,
+ "GET", {kWsUrl}, kSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(incorrectly_lax));
}
+// Test cases where the URL chain contains multiple members, where the last
+// member (current request URL) is same-site to kSiteUrl. (Everything is listed
+// as same-site or cross-site relative to kSiteUrl.)
+TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
+ ContextType incorrectly_lax = IsBugfix1166211Enabled()
+ ? ContextType::CROSS_SITE
+ : ContextType::SAME_SITE_LAX;
+ ContextType incorrectly_lax_unsafe =
+ IsBugfix1166211Enabled() ? ContextType::CROSS_SITE
+ : ContextType::SAME_SITE_LAX_METHOD_UNSAFE;
+ struct {
+ std::string method;
+ bool url_chain_is_same_site;
+ bool site_for_cookies_is_same_site;
+ bool initiator_is_same_site;
+ // These are the expected context types considering redirect chains:
+ ContextType expected_context_type; // for non-main-frame-nav requests.
+ ContextType expected_context_type_for_main_frame_navigation;
+ // These are the expected context types not considering redirect chains:
+ ContextType expected_context_type_without_chain;
+ ContextType expected_context_type_for_main_frame_navigation_without_chain;
+ } kTestCases[] = {
+ // If the url chain is same-site, then the result is the same with or
+ // without considering the redirect chain.
+ {"GET", true, true, true, ContextType::SAME_SITE_STRICT,
+ ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_STRICT,
+ ContextType::SAME_SITE_STRICT},
+ {"GET", true, true, false, incorrectly_lax, ContextType::SAME_SITE_LAX,
+ incorrectly_lax, ContextType::SAME_SITE_LAX},
+ {"GET", true, false, true, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE},
+ {"GET", true, false, false, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE},
+ // If the url chain is cross-site, then the result will differ depending
+ // on whether the redirect chain is considered, when the site-for-cookies
+ // and initiator are both same-site.
+ {"GET", false, true, true, incorrectly_lax, ContextType::SAME_SITE_LAX,
+ ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_STRICT},
+ {"GET", false, true, false, incorrectly_lax, ContextType::SAME_SITE_LAX,
+ incorrectly_lax, ContextType::SAME_SITE_LAX},
+ {"GET", false, false, true, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE},
+ {"GET", false, false, false, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE},
+ // If the url chain is same-site, then the result is the same with or
+ // without considering the redirect chain.
+ {"POST", true, true, true, ContextType::SAME_SITE_STRICT,
+ ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_STRICT,
+ ContextType::SAME_SITE_STRICT},
+ {"POST", true, true, false, incorrectly_lax_unsafe,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE, incorrectly_lax_unsafe,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE},
+ {"POST", true, false, true, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE},
+ {"POST", true, false, false, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE},
+ // If the url chain is cross-site, then the result will differ depending
+ // on whether the redirect chain is considered, when the site-for-cookies
+ // and initiator are both same-site.
+ {"POST", false, true, true, incorrectly_lax_unsafe,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE, ContextType::SAME_SITE_STRICT,
+ ContextType::SAME_SITE_STRICT},
+ {"POST", false, true, false, incorrectly_lax_unsafe,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE, incorrectly_lax_unsafe,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE},
+ {"POST", false, false, true, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE},
+ {"POST", false, false, false, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE},
+ };
+
+ for (const auto& test_case : kTestCases) {
+ std::vector<std::vector<GURL>> url_chains =
+ test_case.url_chain_is_same_site ? GetSameSiteUrlChains(kSiteUrl)
+ : GetCrossSiteUrlChains(kSiteUrl);
+ std::vector<SiteForCookies> sites_for_cookies =
+ test_case.site_for_cookies_is_same_site ? GetSameSiteSitesForCookies()
+ : GetCrossSiteSitesForCookies();
+ std::vector<base::Optional<url::Origin>> initiators =
+ test_case.initiator_is_same_site ? GetSameSiteInitiators()
+ : GetCrossSiteInitiators();
+ ContextType expected_context_type =
+ DoesSameSiteConsiderRedirectChain()
+ ? test_case.expected_context_type
+ : test_case.expected_context_type_without_chain;
+ ContextType expected_context_type_for_main_frame_navigation =
+ DoesSameSiteConsiderRedirectChain()
+ ? test_case.expected_context_type_for_main_frame_navigation
+ : test_case
+ .expected_context_type_for_main_frame_navigation_without_chain;
+ for (const std::vector<GURL>& url_chain : url_chains) {
+ for (const SiteForCookies& site_for_cookies : sites_for_cookies) {
+ for (const base::Optional<url::Origin>& initiator : initiators) {
+ EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
+ test_case.method, url_chain, site_for_cookies,
+ initiator, false /* is_main_frame_navigation */,
+ false /* force_ignore_site_for_cookies */),
+ ContextTypeIs(expected_context_type))
+ << UrlChainToString(url_chain) << " "
+ << site_for_cookies.ToDebugString() << " "
+ << (initiator ? initiator->Serialize() : "nullopt");
+ if (!CanBeMainFrameNavigation(url_chain.back(), site_for_cookies))
+ continue;
+ EXPECT_THAT(
+ cookie_util::ComputeSameSiteContextForRequest(
+ test_case.method, url_chain, site_for_cookies, initiator,
+ true /* is_main_frame_navigation */,
+ false /* force_ignore_site_for_cookies */),
+ ContextTypeIs(expected_context_type_for_main_frame_navigation))
+ << UrlChainToString(url_chain) << " "
+ << site_for_cookies.ToDebugString() << " "
+ << (initiator ? initiator->Serialize() : "nullopt");
+ }
+ }
+ }
+ }
+}
+
TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptSet) {
for (const GURL& url : GetSameSiteUrls()) {
for (const SiteForCookies& site_for_cookies :
GetSameSiteSitesForCookies()) {
// Same-site site-for-cookies -> it's same-site lax.
- // (Cross-site cases covered above in UrlAndSiteForCookiesCrosSite test.)
+ // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
EXPECT_THAT(
cookie_util::ComputeSameSiteContextForScriptSet(
url, site_for_cookies, false /* force_ignore_site_for_cookies */),
@@ -928,10 +1129,11 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForScriptSet_WebSocketSchemes) {
ContextTypeIs(ContextType::SAME_SITE_LAX));
}
+// Test cases where the URL chain has 1 member (i.e. no redirects).
TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse) {
for (const GURL& url : GetSameSiteUrls()) {
// Same-site site-for-cookies.
- // (Cross-site cases covered above in UrlAndSiteForCookiesCrosSite test.)
+ // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
for (const SiteForCookies& site_for_cookies :
GetSameSiteSitesForCookies()) {
// For main frame navigations, setting all SameSite cookies is allowed
@@ -940,7 +1142,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse) {
if (!CanBeMainFrameNavigation(url, site_for_cookies))
break;
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
- url, site_for_cookies, initiator,
+ {url}, site_for_cookies, initiator,
true /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_LAX));
@@ -952,7 +1154,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse) {
for (const base::Optional<url::Origin>& initiator :
GetSameSiteInitiators()) {
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
- url, site_for_cookies, initiator,
+ {url}, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_LAX));
@@ -963,7 +1165,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse) {
? ContextType::CROSS_SITE
: ContextType::SAME_SITE_LAX;
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
- url, site_for_cookies, initiator,
+ {url}, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(incorrectly_lax));
@@ -983,13 +1185,13 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_SchemefulDowngrade) {
EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_LAX,
ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForResponse(
- kSiteUrl, kSecureSiteForCookies, kSiteInitiator,
+ {kSiteUrl}, kSecureSiteForCookies, kSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(SameSiteCookieContext(ContextType::SAME_SITE_LAX,
ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForResponse(
- kSecureSiteUrl, kSiteForCookies, kSecureSiteInitiator,
+ {kSecureSiteUrl}, kSiteForCookies, kSecureSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
// With cross-site initiator:
@@ -998,12 +1200,12 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_SchemefulDowngrade) {
: ContextType::SAME_SITE_LAX;
EXPECT_EQ(SameSiteCookieContext(incorrectly_lax, ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForResponse(
- kSiteUrl, kSecureSiteForCookies, kCrossSiteInitiator,
+ {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(SameSiteCookieContext(incorrectly_lax, ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForResponse(
- kSecureSiteUrl, kSiteForCookies, kCrossSiteInitiator,
+ {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
@@ -1017,13 +1219,13 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_SchemefulDowngrade) {
EXPECT_EQ(
SameSiteCookieContext(ContextType::SAME_SITE_LAX, lax_if_main_frame),
cookie_util::ComputeSameSiteContextForResponse(
- kSiteUrl, kSiteForCookies, kSecureSiteInitiator,
+ {kSiteUrl}, kSiteForCookies, kSecureSiteInitiator,
is_main_frame_navigation,
false /* force_ignore_site_for_cookies */));
EXPECT_EQ(
SameSiteCookieContext(ContextType::SAME_SITE_LAX, lax_if_main_frame),
cookie_util::ComputeSameSiteContextForResponse(
- kSecureSiteUrl, kSecureSiteForCookies, kSiteInitiator,
+ {kSecureSiteUrl}, kSecureSiteForCookies, kSiteInitiator,
is_main_frame_navigation,
false /* force_ignore_site_for_cookies */));
}
@@ -1036,7 +1238,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_WebSocketSchemes) {
// Same-site initiators.
for (const base::Optional<url::Origin>& initiator : GetSameSiteInitiators()) {
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
- kWsUrl, kSiteForCookies, initiator,
+ {kWsUrl}, kSiteForCookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_LAX));
@@ -1048,17 +1250,104 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_WebSocketSchemes) {
? ContextType::CROSS_SITE
: ContextType::SAME_SITE_LAX;
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
- kWsUrl, kSiteForCookies, initiator,
+ {kWsUrl}, kSiteForCookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
ContextTypeIs(incorrectly_lax));
}
}
+// Test cases where the URL chain contains multiple members, where the last
+// member (current request URL) is same-site to kSiteUrl. (Everything is listed
+// as same-site or cross-site relative to kSiteUrl.)
+TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_Redirect) {
+ ContextType incorrectly_lax = IsBugfix1166211Enabled()
+ ? ContextType::CROSS_SITE
+ : ContextType::SAME_SITE_LAX;
+ struct {
+ bool url_chain_is_same_site;
+ bool site_for_cookies_is_same_site;
+ bool initiator_is_same_site;
+ // These are the expected context types considering redirect chains:
+ ContextType expected_context_type; // for non-main-frame-nav requests.
+ ContextType expected_context_type_for_main_frame_navigation;
+ // These are the expected context types not considering redirect chains:
+ ContextType expected_context_type_without_chain;
+ ContextType expected_context_type_for_main_frame_navigation_without_chain;
+ } kTestCases[] = {
+ // If the url chain is same-site, then the result is the same with or
+ // without considering the redirect chain.
+ {true, true, true, ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX,
+ ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX},
+ {true, true, false, incorrectly_lax, ContextType::SAME_SITE_LAX,
+ incorrectly_lax, ContextType::SAME_SITE_LAX},
+ {true, false, true, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE},
+ {true, false, false, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE},
+ // If the url chain is cross-site, then the result will differ depending
+ // on whether the redirect chain is considered, when the site-for-cookies
+ // and initiator are both same-site.
+ {false, true, true, incorrectly_lax, ContextType::SAME_SITE_LAX,
+ ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX},
+ {false, true, false, incorrectly_lax, ContextType::SAME_SITE_LAX,
+ incorrectly_lax, ContextType::SAME_SITE_LAX},
+ {false, false, true, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE},
+ {false, false, false, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
+ ContextType::CROSS_SITE, ContextType::CROSS_SITE},
+ };
+ for (const auto& test_case : kTestCases) {
+ std::vector<std::vector<GURL>> url_chains =
+ test_case.url_chain_is_same_site ? GetSameSiteUrlChains(kSiteUrl)
+ : GetCrossSiteUrlChains(kSiteUrl);
+ std::vector<SiteForCookies> sites_for_cookies =
+ test_case.site_for_cookies_is_same_site ? GetSameSiteSitesForCookies()
+ : GetCrossSiteSitesForCookies();
+ std::vector<base::Optional<url::Origin>> initiators =
+ test_case.initiator_is_same_site ? GetSameSiteInitiators()
+ : GetCrossSiteInitiators();
+ ContextType expected_context_type =
+ DoesSameSiteConsiderRedirectChain()
+ ? test_case.expected_context_type
+ : test_case.expected_context_type_without_chain;
+ ContextType expected_context_type_for_main_frame_navigation =
+ DoesSameSiteConsiderRedirectChain()
+ ? test_case.expected_context_type_for_main_frame_navigation
+ : test_case
+ .expected_context_type_for_main_frame_navigation_without_chain;
+ for (const std::vector<GURL>& url_chain : url_chains) {
+ for (const SiteForCookies& site_for_cookies : sites_for_cookies) {
+ for (const base::Optional<url::Origin>& initiator : initiators) {
+ EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
+ url_chain, site_for_cookies, initiator,
+ false /* is_main_frame_navigation */,
+ false /* force_ignore_site_for_cookies */),
+ ContextTypeIs(expected_context_type))
+ << UrlChainToString(url_chain) << " "
+ << site_for_cookies.ToDebugString() << " "
+ << (initiator ? initiator->Serialize() : "nullopt");
+ if (!CanBeMainFrameNavigation(url_chain.back(), site_for_cookies))
+ continue;
+ EXPECT_THAT(
+ cookie_util::ComputeSameSiteContextForResponse(
+ url_chain, site_for_cookies, initiator,
+ true /* is_main_frame_navigation */,
+ false /* force_ignore_site_for_cookies */),
+ ContextTypeIs(expected_context_type_for_main_frame_navigation))
+ << UrlChainToString(url_chain) << " "
+ << site_for_cookies.ToDebugString() << " "
+ << (initiator ? initiator->Serialize() : "nullopt");
+ }
+ }
+ }
+ }
+}
+
TEST_P(CookieUtilComputeSameSiteContextTest, ForSubresource) {
for (const GURL& url : GetSameSiteUrls()) {
// Same-site site-for-cookies.
- // (Cross-site cases covered above in UrlAndSiteForCookiesCrosSite test.)
+ // (Cross-site cases covered above in UrlAndSiteForCookiesCrossSite test.)
for (const SiteForCookies& site_for_cookies :
GetSameSiteSitesForCookies()) {
EXPECT_THAT(
@@ -1115,13 +1404,25 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForceIgnoreSiteForCookies) {
for (bool is_main_frame_navigation :
IsMainFrameNavigationPossibleValues(url, site_for_cookies)) {
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, url, site_for_cookies, initiator,
+ method, {url}, site_for_cookies, initiator,
is_main_frame_navigation,
true /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_STRICT));
+ EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
+ {url}, site_for_cookies, initiator,
+ is_main_frame_navigation,
+ true /* force_ignore_site_for_cookies */),
+ ContextTypeIs(ContextType::SAME_SITE_LAX));
+ EXPECT_THAT(
+ cookie_util::ComputeSameSiteContextForRequest(
+ method, {site_for_cookies.RepresentativeUrl(), url},
+ site_for_cookies, initiator, is_main_frame_navigation,
+ true /* force_ignore_site_for_cookies */),
+ ContextTypeIs(ContextType::SAME_SITE_STRICT));
EXPECT_THAT(
cookie_util::ComputeSameSiteContextForResponse(
- url, site_for_cookies, initiator, is_main_frame_navigation,
+ {site_for_cookies.RepresentativeUrl(), url},
+ site_for_cookies, initiator, is_main_frame_navigation,
true /* force_ignore_site_for_cookies */),
ContextTypeIs(ContextType::SAME_SITE_LAX));
}
@@ -1138,6 +1439,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForceIgnoreSiteForCookies) {
INSTANTIATE_TEST_SUITE_P(/* no label */,
CookieUtilComputeSameSiteContextTest,
::testing::Combine(::testing::Bool(),
+ ::testing::Bool(),
::testing::Bool()));
TEST(CookieUtilTest, AdaptCookieAccessResultToBool) {
diff --git a/chromium/net/cookies/parsed_cookie.cc b/chromium/net/cookies/parsed_cookie.cc
index f6c1cd4326f..5ef07e07213 100644
--- a/chromium/net/cookies/parsed_cookie.cc
+++ b/chromium/net/cookies/parsed_cookie.cc
@@ -122,12 +122,6 @@ bool IsValidCookieValue(const std::string& value) {
return true;
}
-// RFC 5234 states that control characters are considered to be:
-// CTL = %x00-1F / %x7F
-bool IsControlCharacter(unsigned char c) {
- return c <= 0x1F || c == 0x7F;
-}
-
} // namespace
namespace net {
@@ -352,7 +346,7 @@ bool ParsedCookie::IsValidCookieAttributeValue(const std::string& value) {
// The greatest common denominator of cookie attribute values is
// <any CHAR except CTLs or ";"> according to RFC 6265.
for (std::string::const_iterator i = value.begin(); i != value.end(); ++i) {
- if (IsControlCharacter(*i) || *i == ';')
+ if (HttpUtil::IsControlChar(*i) || *i == ';')
return false;
}
return true;
diff --git a/chromium/net/cookies/site_for_cookies.cc b/chromium/net/cookies/site_for_cookies.cc
index 71e58a04a81..977a0b7c7af 100644
--- a/chromium/net/cookies/site_for_cookies.cc
+++ b/chromium/net/cookies/site_for_cookies.cc
@@ -73,8 +73,11 @@ bool SiteForCookies::IsFirstPartyWithSchemefulMode(
}
bool SiteForCookies::IsEquivalent(const SiteForCookies& other) const {
- if (IsNull())
- return other.IsNull();
+ if (IsNull() || other.IsNull()) {
+ // We need to check if `other.IsNull()` explicitly in order to catch if
+ // `other.schemefully_same_` is false when "Schemeful Same-Site" is enabled.
+ return IsNull() && other.IsNull();
+ }
// In the case where the site has no registrable domain or host, the scheme
// cannot be ws(s) or http(s), so equality of sites implies actual equality of
diff --git a/chromium/net/cookies/site_for_cookies.h b/chromium/net/cookies/site_for_cookies.h
index 031e765770d..d0379b23522 100644
--- a/chromium/net/cookies/site_for_cookies.h
+++ b/chromium/net/cookies/site_for_cookies.h
@@ -19,17 +19,21 @@ namespace net {
// Represents which origins are to be considered same-site for a given
// context (e.g. frame). There may be none.
//
-// The currently implemented policy ("schemeless") is that two valid URLs would
-// be considered the same site if either:
-// 1) They both have non-empty and equal registrable domains or hostnames/IPs.
-// 2) They both have empty hostnames and equal schemes.
-//
-// With the SchemefulSameSite feature enabled the policy ("schemeful") is that
+// The currently implemented policy ("schemeful") is that
// two valid URLs would be considered same-site if either:
// 1) They both have compatible schemes along with non-empty and equal
// registrable domains or hostnames/IPs. Two schemes are compatible if they
// are either equal, or are both in {http, ws}, or are both in {https, wss}.
-// 2) They both have empty hostnames and exactly equal schemes.
+// E.x. "https://example.com" and "wss://example.com"
+// 2) They both have empty hostnames and exactly equal schemes. E.x. "file://"
+// and "file://"
+//
+// With the SchemefulSameSite feature disabled the policy ("schemeless") is that
+// two valid URLs would be considered the same site if either: 1) They both have
+// non-empty and equal registrable domains or hostnames/IPs. E.x. "example.com"
+// and "example.com" 2) They both have empty hostnames and equal schemes. E.x.
+// "file://" and "file://"
+//
//
// Invalid URLs are never same-site to anything.
class NET_EXPORT SiteForCookies {
@@ -59,8 +63,8 @@ class NET_EXPORT SiteForCookies {
// If the origin is opaque, returns SiteForCookies that matches nothing.
//
- // If it's not, returns one that matches URLs which are considered to be
- // same-party as URLs from `origin`.
+ // If it's not opaque, returns one that matches URLs which are considered to
+ // be same-party as URLs from `origin`.
static SiteForCookies FromOrigin(const url::Origin& origin);
// Equivalent to FromOrigin(url::Origin::Create(url)).
@@ -90,7 +94,9 @@ class NET_EXPORT SiteForCookies {
bool compute_schemefully) const;
// Returns true if `other.IsFirstParty()` is true for exactly the same URLs
- // as `this->IsFirstParty` (potentially none).
+ // as `this->IsFirstParty` (potentially none). Two SFCs are also considered
+ // equivalent if neither ever returns true for `IsFirstParty()`. I.e., both
+ // are null.
bool IsEquivalent(const SiteForCookies& other) const;
// Compares a "candidate" SFC, `this`, with an origin (represented as a
@@ -123,7 +129,7 @@ class NET_EXPORT SiteForCookies {
// Same-Site" is disabled.)
bool CompareWithFrameTreeSiteAndRevise(const SchemefulSite& other);
- // Overload which converts an Origin into a SchemefulSite and then calls
+ // Converts an Origin into a SchemefulSite and then calls
//`CompareWithFrameTreeSiteAndRevise(SchemefulSite)`
//
// If possible, prefer `CompareWithFrameTreeSiteAndRevise(SchemefulSite)`
@@ -151,7 +157,7 @@ class NET_EXPORT SiteForCookies {
}
// Used for serialization/deserialization. This value is irrelevant if
- // IsNull() is true.
+ // site().opaque() is true.
bool schemefully_same() const { return schemefully_same_; }
void SetSchemefullySameForTesting(bool schemefully_same) {
diff --git a/chromium/net/cookies/site_for_cookies_unittest.cc b/chromium/net/cookies/site_for_cookies_unittest.cc
index 546813386e0..69526f6de35 100644
--- a/chromium/net/cookies/site_for_cookies_unittest.cc
+++ b/chromium/net/cookies/site_for_cookies_unittest.cc
@@ -18,10 +18,10 @@
namespace net {
namespace {
-class SchemefulSiteForCookiesTest : public ::testing::Test {
+class SchemelessSiteForCookiesTest : public ::testing::Test {
public:
- SchemefulSiteForCookiesTest() {
- scope_feature_list_.InitAndEnableFeature(features::kSchemefulSameSite);
+ SchemelessSiteForCookiesTest() {
+ scope_feature_list_.InitAndDisableFeature(features::kSchemefulSameSite);
}
protected:
@@ -93,7 +93,7 @@ TEST(SiteForCookiesTest, Default) {
should_match_none.ToDebugString());
}
-TEST(SiteForCookiesTest, Basic) {
+TEST_F(SchemelessSiteForCookiesTest, Basic) {
std::vector<GURL> equivalent = {
GURL("https://example.com"),
GURL("http://sub1.example.com:42/something"),
@@ -108,8 +108,9 @@ TEST(SiteForCookiesTest, Basic) {
TestEquivalentAndDistinct(equivalent, distinct, "example.com");
}
-// Similar to SiteForCookiesTest_Basic with a focus on testing secure SFCs.
-TEST_F(SchemefulSiteForCookiesTest, BasicSecure) {
+// Similar to SchemelessSiteForCookiesTest_Basic with a focus on testing secure
+// SFCs.
+TEST(SiteForCookiesTest, BasicSecure) {
std::vector<GURL> equivalent = {GURL("https://example.com"),
GURL("wss://example.com"),
GURL("https://sub1.example.com:42/something"),
@@ -124,8 +125,9 @@ TEST_F(SchemefulSiteForCookiesTest, BasicSecure) {
TestEquivalentAndDistinct(equivalent, distinct, "example.com");
}
-// Similar to SiteForCookiesTest_Basic with a focus on testing insecure SFCs.
-TEST_F(SchemefulSiteForCookiesTest, BasicInsecure) {
+// Similar to SchemelessSiteForCookiesTest_Basic with a focus on testing
+// insecure SFCs.
+TEST(SiteForCookiesTest, BasicInsecure) {
std::vector<GURL> equivalent = {GURL("http://example.com"),
GURL("ws://example.com"),
GURL("http://sub1.example.com:42/something"),
@@ -149,7 +151,7 @@ TEST(SiteForCookiesTest, File) {
TestEquivalentAndDistinct(equivalent, distinct, "");
}
-TEST(SiteForCookiesTest, Extension) {
+TEST_F(SchemelessSiteForCookiesTest, Extension) {
url::ScopedSchemeRegistryForTests scoped_registry;
url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
std::vector<GURL> equivalent = {GURL("chrome-extension://abc/"),
@@ -163,9 +165,9 @@ TEST(SiteForCookiesTest, Extension) {
TestEquivalentAndDistinct(equivalent, distinct, "abc");
}
-// Similar to SiteForCookiesTest_Extension with a focus on ensuring that http(s)
-// schemes are distinct.
-TEST_F(SchemefulSiteForCookiesTest, Extension) {
+// Similar to SchemelessSiteForCookiesTest_Extension with a focus on ensuring
+// that http(s) schemes are distinct.
+TEST(SiteForCookiesTest, Extension) {
url::ScopedSchemeRegistryForTests scoped_registry;
url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
std::vector<GURL> equivalent = {
@@ -192,7 +194,7 @@ TEST(SiteForCookiesTest, NonStandard) {
TestEquivalentAndDistinct(equivalent, distinct, "");
}
-TEST(SiteForCookiesTest, Blob) {
+TEST_F(SchemelessSiteForCookiesTest, Blob) {
// This case isn't really well-specified and is inconsistent between
// different user agents; the behavior chosen here was to be more
// consistent between url and origin handling.
@@ -210,8 +212,8 @@ TEST(SiteForCookiesTest, Blob) {
SiteForCookies::FromUrl(GURL("http://www.example.org:631"))));
}
-// Similar to SiteForCookiesTest_Blob with a focus on a secure blob.
-TEST_F(SchemefulSiteForCookiesTest, SecureBlob) {
+// Similar to SchemelessSiteForCookiesTest_Blob with a focus on a secure blob.
+TEST(SiteForCookiesTest, SecureBlob) {
SiteForCookies from_blob = SiteForCookies::FromUrl(
GURL("blob:https://example.org/9115d58c-bcda-ff47-86e5-083e9a2153041"));
@@ -227,8 +229,9 @@ TEST_F(SchemefulSiteForCookiesTest, SecureBlob) {
SiteForCookies::FromUrl(GURL("http://www.example.org:631"))));
}
-// Similar to SiteForCookiesTest_Blob with a focus on an insecure blob.
-TEST_F(SchemefulSiteForCookiesTest, InsecureBlob) {
+// Similar to SchemelessSiteForCookiesTest_Blob with a focus on an insecure
+// blob.
+TEST(SiteForCookiesTest, InsecureBlob) {
SiteForCookies from_blob = SiteForCookies::FromUrl(
GURL("blob:http://example.org/9115d58c-bcda-ff47-86e5-083e9a2153041"));
@@ -245,7 +248,7 @@ TEST_F(SchemefulSiteForCookiesTest, InsecureBlob) {
SiteForCookies::FromUrl(GURL("https://www.example.org:631"))));
}
-TEST(SiteForCookiesTest, Wire) {
+TEST_F(SchemelessSiteForCookiesTest, Wire) {
SiteForCookies out;
// Empty one.
@@ -295,9 +298,9 @@ TEST(SiteForCookiesTest, Wire) {
out.ToDebugString());
}
-// Similar to SiteForCookiesTest_Wire except that schemefully_same has an
-// effect (makes IsNull() return true if schemefully_same is false).
-TEST_F(SchemefulSiteForCookiesTest, Wire) {
+// Similar to SchemelessSiteForCookiesTest_Wire except that schemefully_same has
+// an effect (makes IsNull() return true if schemefully_same is false).
+TEST(SiteForCookiesTest, Wire) {
SiteForCookies out;
// Empty one.
@@ -356,7 +359,7 @@ TEST_F(SchemefulSiteForCookiesTest, Wire) {
out.ToDebugString());
}
-TEST_F(SchemefulSiteForCookiesTest, SchemefulSite) {
+TEST(SiteForCookiesTest, SchemefulSite) {
const char* kTestCases[] = {"opaque.com",
"http://a.com",
"https://sub1.example.com:42/something",
@@ -499,6 +502,29 @@ TEST(SiteForCookiesTest, CompareWithFrameTreeSiteAndReviseOpaque) {
EXPECT_EQ(candidate4.site(), opaque_site1);
}
+TEST(SiteForCookiesTest, NotSchemefullySameEquivalent) {
+ SiteForCookies first =
+ SiteForCookies::FromUrl(GURL("https://www.example.com"));
+ SiteForCookies second =
+ SiteForCookies::FromUrl(GURL("https://www.example.com"));
+ // Smoke check that two SFCs should match when they're the same.
+ EXPECT_TRUE(first.IsEquivalent(second));
+ EXPECT_TRUE(second.IsEquivalent(first));
+
+ // Two SFC should not be equivalent to each other when one of their
+ // schemefully_same_ flags is false, even if they're otherwise the same, when
+ // Schemeful Same-Site is enabled.
+ second.SetSchemefullySameForTesting(false);
+ EXPECT_FALSE(first.IsEquivalent(second));
+ EXPECT_FALSE(second.IsEquivalent(first));
+
+ // However, they should match if both their schemefully_same_ flags are false.
+ // Because they're both considered null at that point.
+ first.SetSchemefullySameForTesting(false);
+ EXPECT_TRUE(first.IsEquivalent(second));
+ EXPECT_TRUE(second.IsEquivalent(first));
+}
+
} // namespace
TEST(SiteForCookiesTest, SameScheme) {
diff --git a/chromium/net/cookies/static_cookie_policy_unittest.cc b/chromium/net/cookies/static_cookie_policy_unittest.cc
index 958de262d90..3c57a57cc92 100644
--- a/chromium/net/cookies/static_cookie_policy_unittest.cc
+++ b/chromium/net/cookies/static_cookie_policy_unittest.cc
@@ -57,8 +57,9 @@ TEST_F(StaticCookiePolicyTest, BlockAllThirdPartyCookiesTest) {
SetPolicyType(StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES);
EXPECT_THAT(CanAccessCookies(url_google_, url_google_), IsOk());
- EXPECT_THAT(CanAccessCookies(url_google_, url_google_secure_), IsOk());
EXPECT_THAT(CanAccessCookies(url_google_, url_google_mail_), IsOk());
+ EXPECT_NE(OK, CanAccessCookies(url_google_, url_google_secure_));
+ EXPECT_NE(OK, CanAccessCookies(url_google_secure_, url_google_));
EXPECT_NE(OK, CanAccessCookies(url_google_, url_google_analytics_));
EXPECT_NE(OK, CanAccessCookies(url_google_, GURL()));
}
diff --git a/chromium/net/cookies/test_cookie_access_delegate.cc b/chromium/net/cookies/test_cookie_access_delegate.cc
index d1307806a60..d98eda75297 100644
--- a/chromium/net/cookies/test_cookie_access_delegate.cc
+++ b/chromium/net/cookies/test_cookie_access_delegate.cc
@@ -35,7 +35,7 @@ bool TestCookieAccessDelegate::ShouldIgnoreSameSiteRestrictions(
bool TestCookieAccessDelegate::IsContextSamePartyWithSite(
const net::SchemefulSite& site,
- const net::SchemefulSite& top_frame_site,
+ const base::Optional<net::SchemefulSite>& top_frame_site,
const std::set<net::SchemefulSite>& party_context) const {
return false;
}
diff --git a/chromium/net/cookies/test_cookie_access_delegate.h b/chromium/net/cookies/test_cookie_access_delegate.h
index 722f6f45948..8a9851dfd7b 100644
--- a/chromium/net/cookies/test_cookie_access_delegate.h
+++ b/chromium/net/cookies/test_cookie_access_delegate.h
@@ -30,7 +30,7 @@ class TestCookieAccessDelegate : public CookieAccessDelegate {
const SiteForCookies& site_for_cookies) const override;
bool IsContextSamePartyWithSite(
const net::SchemefulSite& site,
- const net::SchemefulSite& top_frame_site,
+ const base::Optional<net::SchemefulSite>& top_frame_site,
const std::set<net::SchemefulSite>& party_context) const override;
bool IsInNontrivialFirstPartySet(
const net::SchemefulSite& site) const override;