CookieInclusionStatus: Support warnings and multiple exclusion reasons
Previously CookieInclusionStatus was just an enum with one value for
inclusion and a number of other values for exclusion due to different
reasons.
This changes CookieInclusionStatus to hold multiple exclusion reasons,
with inclusion represented as a lack of any exclusion reasons. This is
implemented as a bit vector with each exclusion reason represented as
a single bit.
This also adds warnings to CookieInclusionStatus, which indicate when
warnings should be emitted about a cookie (regardless of inclusion or
exclusion). This removes the need for the previous hack which indicated
warnings by making a duplicate of the cookie with a different
CookieInclusionStatus.
Bug: 993843
Change-Id: I8f4f76ea5c7225cd01342786b20f9e0b05f582c3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1756157
Commit-Queue: Lily Chen <[email protected]>
Reviewed-by: Sylvain Defresne <[email protected]>
Reviewed-by: Victor Costan <[email protected]>
Reviewed-by: Boris Sazonov <[email protected]>
Reviewed-by: Toni Baržić <[email protected]>
Reviewed-by: Christian Dullweber <[email protected]>
Reviewed-by: Kyle Horimoto <[email protected]>
Reviewed-by: Wez <[email protected]>
Reviewed-by: Maks Orlovich <[email protected]>
Reviewed-by: Karan Bhatia <[email protected]>
Reviewed-by: Balazs Engedy <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Reviewed-by: John Abd-El-Malek <[email protected]>
Reviewed-by: Andrey Kosyakov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#691902}
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 3f81a43..da86e5f 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -416,9 +416,9 @@
ProcessStrictTransportSecurityHeader();
ProcessExpectCTHeader();
- // Clear |cs_status_list_| after any processing in case
+ // Clear |set_cookie_status_list_| after any processing in case
// SaveCookiesAndNotifyHeadersComplete is called again.
- request_->set_maybe_stored_cookies(std::move(cs_status_list_));
+ request_->set_maybe_stored_cookies(std::move(set_cookie_status_list_));
// The HTTP transaction may be restarted several times for the purposes
// of sending authorization information. Each time it restarts, we get
@@ -642,20 +642,20 @@
const CookieStatusList& cookies_with_status_list,
const CookieStatusList& excluded_list) {
DCHECK(request_->maybe_sent_cookies().empty());
- CookieStatusList maybe_sent_cookies = excluded_list;
- // TODO(crbug.com/993843): Pass in meaningful statuses, then actually use the
- // statuses passed in.
+ // TODO(chlily): This is just for passing to CanGetCookies(), however the
+ // CookieList parameter of CanGetCookies(), which eventually gets passed to
+ // the NetworkDelegate, never actually gets used anywhere except in tests. The
+ // parameter should be removed.
CookieList cookie_list =
net::cookie_util::StripStatuses(cookies_with_status_list);
- net::CanonicalCookie::CookieInclusionStatus status_for_cookie_list =
- CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES;
- if (!cookie_list.empty() && CanGetCookies(cookie_list)) {
- status_for_cookie_list = CanonicalCookie::CookieInclusionStatus::INCLUDE;
+ bool can_get_cookies = CanGetCookies(cookie_list);
+ if (!cookies_with_status_list.empty() && can_get_cookies) {
LogCookieUMA(cookie_list, *request_, request_info_);
- std::string cookie_line = CanonicalCookie::BuildCookieLine(cookie_list);
+ std::string cookie_line =
+ CanonicalCookie::BuildCookieLine(cookies_with_status_list);
UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
cookie_line);
@@ -664,30 +664,28 @@
request_info_.privacy_mode = PRIVACY_MODE_DISABLED;
}
- // Report status for things in |cookie_list| after the delegate got a chance
- // to block them.
- for (const auto& cookie : cookie_list)
- maybe_sent_cookies.push_back({cookie, status_for_cookie_list});
-
- // Copy any cookies that would not be sent under SameSiteByDefaultCookies
- // and/or CookiesWithoutSameSiteMustBeSecure with an informative status into
- // the |maybe_sent_cookies| list so that we can display appropriate console
- // warning messages about them. I.e. they are still included in the Cookie
- // header, but they are *also* copied into |maybe_sent_cookies| with the
- // CookieInclusionStatus that *would* apply. This special-casing will go away
- // once SameSiteByDefaultCookies and CookiesWithoutSameSiteMustBeSecure are on
- // by default, as the affected cookies will just be excluded in the first
- // place.
- for (const CanonicalCookie& cookie : cookie_list) {
- CanonicalCookie::CookieInclusionStatus
- include_but_maybe_would_exclude_status =
- cookie_util::CookieWouldBeExcludedDueToSameSite(cookie, options);
- if (include_but_maybe_would_exclude_status !=
- CanonicalCookie::CookieInclusionStatus::INCLUDE) {
- maybe_sent_cookies.push_back(
- {cookie, include_but_maybe_would_exclude_status});
+ // Report status for things in |excluded_list| and |cookies_with_status_list|
+ // after the delegate got a chance to block them.
+ CookieStatusList maybe_sent_cookies = excluded_list;
+ // CanGetCookies only looks at the fields of the URLRequest, not the cookies
+ // it is passed, so if CanGetCookies(cookie_list) is false, then
+ // CanGetCookies(excluded_list) would also be false, so tag also the
+ // excluded cookies as having been blocked by user preferences.
+ if (!can_get_cookies) {
+ for (CookieStatusList::iterator it = maybe_sent_cookies.begin();
+ it != maybe_sent_cookies.end(); ++it) {
+ it->status.AddExclusionReason(
+ CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
}
}
+ for (const auto& cookie_with_status : cookies_with_status_list) {
+ CanonicalCookie::CookieInclusionStatus status = cookie_with_status.status;
+ if (!can_get_cookies) {
+ status.AddExclusionReason(
+ CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+ }
+ maybe_sent_cookies.push_back({cookie_with_status.cookie, status});
+ }
request_->set_maybe_sent_cookies(std::move(maybe_sent_cookies));
@@ -695,7 +693,7 @@
}
void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
- DCHECK(cs_status_list_.empty());
+ DCHECK(set_cookie_status_list_.empty());
DCHECK_EQ(0, num_cookie_lines_left_);
// End of the call started in OnStartCompleted.
@@ -753,29 +751,26 @@
request_->url(), cookie_string, base::Time::Now(), server_time,
&returned_status);
- if (returned_status != CanonicalCookie::CookieInclusionStatus::INCLUDE) {
- OnSetCookieResult(options, base::nullopt, std::move(cookie_string),
+ base::Optional<CanonicalCookie> cookie_to_return = base::nullopt;
+ if (returned_status.IsInclude()) {
+ DCHECK(cookie);
+ // Make a copy of the cookie if we successfully made one.
+ cookie_to_return = *cookie;
+ }
+ if (cookie && !CanSetCookie(*cookie, &options)) {
+ returned_status.AddExclusionReason(
+ CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+ }
+ if (!returned_status.IsInclude()) {
+ OnSetCookieResult(options, cookie_to_return, std::move(cookie_string),
returned_status);
continue;
}
- DCHECK(cookie);
-
- if (!CanSetCookie(*cookie, &options)) {
- OnSetCookieResult(
- options, base::make_optional<CanonicalCookie>(*cookie),
- std::move(cookie_string),
- CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
- continue;
- }
-
- // Make a copy for the make_optional.
- CanonicalCookie cookie_copy = *cookie;
request_->context()->cookie_store()->SetCanonicalCookieAsync(
std::move(cookie), request_->url().scheme(), options,
base::BindOnce(&URLRequestHttpJob::OnSetCookieResult,
- weak_factory_.GetWeakPtr(), options,
- base::make_optional<CanonicalCookie>(cookie_copy),
+ weak_factory_.GetWeakPtr(), options, cookie_to_return,
cookie_string));
}
// Removing the 1 that |num_cookie_lines_left| started with, signifing that
@@ -791,34 +786,14 @@
base::Optional<CanonicalCookie> cookie,
std::string cookie_string,
CanonicalCookie::CookieInclusionStatus status) {
- cs_status_list_.emplace_back(std::move(cookie), std::move(cookie_string),
- status);
-
- if (status == CanonicalCookie::CookieInclusionStatus::INCLUDE) {
- DCHECK(cookie.has_value());
- // Copy any cookies that would not be sent under SameSiteByDefaultCookies
- // and/or CookiesWithoutSameSiteMustBeSecure into |cs_status_list_| with a
- // descriptive status so that we can display appropriate console warning
- // messages about them. I.e. they are still set, but they are *also* copied
- // into |cs_status_list_| with the CookieInclusionStatus that *would* apply.
- // This special-casing will go away once SameSiteByDefaultCookies and
- // CookiesWithoutSameSiteMustBeSecure are on by default, as the affected
- // cookies will just be excluded in the first place.
- CanonicalCookie::CookieInclusionStatus
- include_but_maybe_would_exclude_status =
- cookie_util::CookieWouldBeExcludedDueToSameSite(cookie.value(),
- options);
- if (include_but_maybe_would_exclude_status !=
- CanonicalCookie::CookieInclusionStatus::INCLUDE) {
- cs_status_list_.emplace_back(std::move(cookie), std::move(cookie_string),
- include_but_maybe_would_exclude_status);
- }
- }
+ set_cookie_status_list_.emplace_back(std::move(cookie),
+ std::move(cookie_string), status);
num_cookie_lines_left_--;
- // If all the cookie lines have been handled, |cs_status_list_| now reflects
- // the result of all Set-Cookie lines, and the request can be continued.
+ // If all the cookie lines have been handled, |set_cookie_status_list_| now
+ // reflects the result of all Set-Cookie lines, and the request can be
+ // continued.
if (num_cookie_lines_left_ == 0)
NotifyHeadersComplete();
}