#include "net/cookies/cookie_util.h"
#include <array>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <string_view>
#include <utility>
#include "base/check.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/types/optional_ref.h"
#include "base/types/optional_util.h"
#include "build/build_config.h"
#include "net/base/features.h"
#include "net/base/isolation_info.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/schemeful_site.h"
#include "net/base/url_util.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_access_delegate.h"
#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/cookies/parsed_cookie.h"
#include "net/first_party_sets/first_party_set_metadata.h"
#include "net/first_party_sets/first_party_sets_cache_filter.h"
#include "net/http/http_util.h"
#include "net/storage_access_api/status.h"
#include "url/gurl.h"
#include "url/url_constants.h"
namespace net::cookie_util {
namespace {
using ContextType = CookieOptions::SameSiteCookieContext::ContextType;
using ContextMetadata = CookieOptions::SameSiteCookieContext::ContextMetadata;
base::Time MinNonNullTime() {
return base::Time::FromInternalValue(1);
}
std::optional<base::Time> SaturatedTimeFromUTCExploded(
const base::Time::Exploded& exploded) {
base::Time out;
if (base::Time::FromUTCExploded(exploded, &out)) {
return out.is_null() ? MinNonNullTime() : out;
}
if (!exploded.HasValidValues()) {
return std::nullopt;
}
if (exploded.year > base::Time::kExplodedMaxYear) {
return base::Time::Max();
}
if (exploded.year < base::Time::kExplodedMinYear) {
return MinNonNullTime();
}
return std::nullopt;
}
bool HasValidSecurePrefixAttributes(const GURL& url, bool secure) {
return secure &&
ProvisionalAccessScheme(url) != CookieAccessScheme::kNonCryptographic;
}
bool HasValidHostPrefixAttributes(const GURL& url,
bool secure,
std::string_view domain,
std::string_view path) {
if (!HasValidSecurePrefixAttributes(url, secure) || path != "/") {
return false;
}
return domain.empty() || (url.HostIsIPAddress() && url.GetHost() == domain);
}
bool HasValidHttpPrefixAttributes(const GURL& url,
bool secure,
bool http_only) {
return HasValidSecurePrefixAttributes(url, secure) && http_only;
}
struct ComputeSameSiteContextResult {
ContextType context_type = ContextType::CROSS_SITE;
ContextMetadata metadata;
};
CookieOptions::SameSiteCookieContext MakeSameSiteCookieContext(
const ComputeSameSiteContextResult& result,
const ComputeSameSiteContextResult& schemeful_result) {
return CookieOptions::SameSiteCookieContext(
result.context_type, schemeful_result.context_type, result.metadata,
schemeful_result.metadata);
}
ContextMetadata::ContextRedirectTypeBug1221316
ComputeContextRedirectTypeBug1221316(bool url_chain_is_length_one,
bool same_site_initiator,
bool site_for_cookies_is_same_site,
bool same_site_redirect_chain) {
if (url_chain_is_length_one)
return ContextMetadata::ContextRedirectTypeBug1221316::kNoRedirect;
if (!same_site_initiator || !site_for_cookies_is_same_site)
return ContextMetadata::ContextRedirectTypeBug1221316::kCrossSiteRedirect;
if (!same_site_redirect_chain) {
return ContextMetadata::ContextRedirectTypeBug1221316::
kPartialSameSiteRedirect;
}
return ContextMetadata::ContextRedirectTypeBug1221316::kAllSameSiteRedirect;
}
ComputeSameSiteContextResult ComputeSameSiteContext(
const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const std::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 =
is_same_site_with_site_for_cookies(request_url);
DCHECK(!is_main_frame_navigation || site_for_cookies_is_same_site ||
site_for_cookies.IsNull());
DCHECK(!is_main_frame_navigation || !request_url.SchemeIsWSOrWSS());
ComputeSameSiteContextResult result;
bool same_site_initiator =
!initiator ||
SiteForCookies::FromOrigin(initiator.value())
.IsFirstPartyWithSchemefulMode(request_url, compute_schemefully);
bool same_site_redirect_chain =
url_chain.size() == 1u ||
std::ranges::all_of(url_chain, is_same_site_with_site_for_cookies);
result.metadata.redirect_type_bug_1221316 =
ComputeContextRedirectTypeBug1221316(
url_chain.size() == 1u, same_site_initiator,
site_for_cookies_is_same_site, same_site_redirect_chain);
if (!site_for_cookies_is_same_site)
return result;
bool cross_site_redirect_downgraded_from_strict = false;
bool use_strict = false;
if (same_site_initiator) {
if (same_site_redirect_chain) {
result.context_type = ContextType::SAME_SITE_STRICT;
return result;
}
cross_site_redirect_downgraded_from_strict = true;
use_strict = !base::FeatureList::IsEnabled(
features::kCookieSameSiteConsidersRedirectChain);
}
if (!is_http || is_main_frame_navigation) {
if (cross_site_redirect_downgraded_from_strict) {
result.metadata.cross_site_redirect_downgrade =
ContextMetadata::ContextDowngradeType::kStrictToLax;
}
result.context_type =
use_strict ? ContextType::SAME_SITE_STRICT : ContextType::SAME_SITE_LAX;
return result;
}
if (cross_site_redirect_downgraded_from_strict) {
result.metadata.cross_site_redirect_downgrade =
ContextMetadata::ContextDowngradeType::kStrictToCross;
}
result.context_type =
use_strict ? ContextType::SAME_SITE_STRICT : ContextType::CROSS_SITE;
return result;
}
void NormalizeStrictToLaxForSet(ComputeSameSiteContextResult& result) {
if (result.context_type == ContextType::SAME_SITE_STRICT)
result.context_type = ContextType::SAME_SITE_LAX;
switch (result.metadata.cross_site_redirect_downgrade) {
case ContextMetadata::ContextDowngradeType::kStrictToLax:
result.metadata.cross_site_redirect_downgrade =
ContextMetadata::ContextDowngradeType::kNoDowngrade;
break;
case ContextMetadata::ContextDowngradeType::kStrictToCross:
result.metadata.cross_site_redirect_downgrade =
ContextMetadata::ContextDowngradeType::kLaxToCross;
break;
default:
break;
}
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSet(
const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const std::optional<url::Origin>& initiator,
bool is_http,
bool is_main_frame_navigation) {
CookieOptions::SameSiteCookieContext same_site_context;
ComputeSameSiteContextResult result = ComputeSameSiteContext(
url_chain, site_for_cookies, initiator, is_http, is_main_frame_navigation,
false );
ComputeSameSiteContextResult schemeful_result = ComputeSameSiteContext(
url_chain, site_for_cookies, initiator, is_http, is_main_frame_navigation,
true );
NormalizeStrictToLaxForSet(result);
NormalizeStrictToLaxForSet(schemeful_result);
return MakeSameSiteCookieContext(result, schemeful_result);
}
bool CookieWithAccessResultSorter(const CookieWithAccessResult& a,
const CookieWithAccessResult& b) {
return CookieMonster::CookieSorter(&a.cookie, &b.cookie);
}
}
void FireStorageAccessHistogram(StorageAccessResult result) {
if (base::ShouldRecordSubsampledMetric(0.01)) {
UMA_HISTOGRAM_ENUMERATION("API.StorageAccess.AllowedRequests4.Subsampled",
result);
}
}
bool DomainIsHostOnly(const std::string& domain_string) {
return (domain_string.empty() || domain_string[0] != '.');
}
std::string CookieDomainAsHost(const std::string& cookie_domain) {
if (DomainIsHostOnly(cookie_domain))
return cookie_domain;
return cookie_domain.substr(1);
}
std::string GetEffectiveDomain(const std::string& scheme,
const std::string& host) {
if (scheme == "http" || scheme == "https" || scheme == "ws" ||
scheme == "wss") {
return registry_controlled_domains::GetDomainAndRegistry(
host,
registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
}
return CookieDomainAsHost(host);
}
std::optional<std::string> GetCookieDomainWithString(
const GURL& url,
std::string_view domain_string,
CookieInclusionStatus& status) {
if (!base::IsStringASCII(domain_string)) {
if (base::FeatureList::IsEnabled(features::kCookieDomainRejectNonASCII)) {
status.AddExclusionReason(
CookieInclusionStatus::ExclusionReason::EXCLUDE_DOMAIN_NON_ASCII);
return std::nullopt;
}
status.AddWarningReason(
CookieInclusionStatus::WarningReason::WARN_DOMAIN_NON_ASCII);
}
const std::string url_host(url.GetHost());
if (url_host.ends_with("..")) {
return std::nullopt;
}
const bool is_host_ip = url.HostIsIPAddress();
const bool domain_matches_host =
base::EqualsCaseInsensitiveASCII(url_host, domain_string) ||
base::EqualsCaseInsensitiveASCII("." + url_host, domain_string);
if (domain_string.empty() || (is_host_ip && domain_matches_host)) {
std::string result;
if (url.IsStandard()) {
result = url_host;
} else {
url::CanonHostInfo ignored;
result = CanonicalizeHost(url_host, &ignored);
if (!result.empty() && result[0] == '.') {
return std::nullopt;
}
if (result.empty() && !url_host.empty()) {
return std::nullopt;
}
}
DCHECK(DomainIsHostOnly(result));
return result;
} else if (is_host_ip) {
return std::nullopt;
}
if (base::Contains(domain_string, '%')) {
return std::nullopt;
}
url::CanonHostInfo ignored;
std::string cookie_domain(CanonicalizeHost(domain_string, &ignored));
if (cookie_domain.empty()) {
return std::nullopt;
}
if (cookie_domain[0] != '.') {
cookie_domain = "." + cookie_domain;
}
const std::string url_scheme(url.GetScheme());
const std::string url_domain_and_registry(
GetEffectiveDomain(url_scheme, url_host));
if (url_domain_and_registry.empty()) {
std::string normalized_domain_string = base::ToLowerASCII(
domain_string[0] == '.' ? domain_string.substr(1) : domain_string);
if (url_host == normalized_domain_string) {
DCHECK(DomainIsHostOnly(normalized_domain_string));
return normalized_domain_string;
}
return std::nullopt;
}
const std::string cookie_domain_and_registry(
GetEffectiveDomain(url_scheme, cookie_domain));
if (url_domain_and_registry != cookie_domain_and_registry) {
return std::nullopt;
}
const bool is_suffix = (url_host.length() < cookie_domain.length()) ?
(cookie_domain != ("." + url_host)) :
(url_host.compare(url_host.length() - cookie_domain.length(),
cookie_domain.length(), cookie_domain) != 0);
if (is_suffix) {
return std::nullopt;
}
return cookie_domain;
}
base::Time ParseCookieExpirationTime(std::string_view time_string) {
static constexpr auto kMonths = std::to_array<std::string_view>({
"jan",
"feb",
"mar",
"apr",
"may",
"jun",
"jul",
"aug",
"sep",
"oct",
"nov",
"dec",
});
static const char kDelimiters[] = "\t !\"#$%&'()*+,-./;<=>?@[\\]^_`{|}~";
base::Time::Exploded exploded = {0};
base::StringViewTokenizer tokenizer(time_string, kDelimiters);
bool found_day_of_month = false;
bool found_month = false;
bool found_time = false;
bool found_year = false;
while (tokenizer.GetNext()) {
std::string_view token = tokenizer.token();
DCHECK(!token.empty());
bool numerical = base::IsAsciiDigit(token[0]);
if (!numerical) {
if (!found_month) {
for (size_t i = 0; i < std::size(kMonths); ++i) {
if (base::StartsWith(token, kMonths[i],
base::CompareCase::INSENSITIVE_ASCII)) {
exploded.month = static_cast<int>(i) + 1;
found_month = true;
break;
}
}
} else {
}
} else if (token.find(':') != std::string::npos) {
std::string token_str(token);
if (!found_time &&
#ifdef COMPILER_MSVC
UNSAFE_TODO(sscanf_s(
#else
UNSAFE_TODO(sscanf(
#endif
token_str.c_str(), "%2u:%2u:%2u", &exploded.hour,
&exploded.minute, &exploded.second)) == 3) {
found_time = true;
} else {
}
} else {
if (!found_day_of_month && token.length() <= 2) {
std::string token_str(token);
exploded.day_of_month = atoi(token_str.c_str());
found_day_of_month = true;
} else if (!found_year && token.length() <= 5) {
std::string token_str(token);
exploded.year = atoi(token_str.c_str());
found_year = true;
} else {
}
}
}
if (!found_day_of_month || !found_month || !found_time || !found_year) {
return base::Time();
}
if (exploded.year >= 70 && exploded.year <= 99)
exploded.year += 1900;
if (exploded.year >= 0 && exploded.year <= 69)
exploded.year += 2000;
return SaturatedTimeFromUTCExploded(exploded).value_or(base::Time());
}
std::string CanonPathWithString(const GURL& url, std::string_view path_string) {
if (!path_string.empty() && path_string[0] == '/') {
return std::string(path_string);
}
const std::string& url_path = url.GetPath();
size_t idx = url_path.find_last_of('/');
if (idx == 0 || idx == std::string::npos) {
return std::string("/");
}
return url_path.substr(0, idx);
}
GURL CookieDomainAndPathToURL(const std::string& domain,
const std::string& path,
const std::string& source_scheme) {
std::string domain_no_dot = CookieDomainAsHost(domain);
if (domain_no_dot.empty() || source_scheme.empty())
return GURL();
return GURL(base::StrCat(
{source_scheme, url::kStandardSchemeSeparator, domain_no_dot, path}));
}
GURL CookieDomainAndPathToURL(const std::string& domain,
const std::string& path,
bool is_https) {
return CookieDomainAndPathToURL(
domain, path,
std::string(is_https ? url::kHttpsScheme : url::kHttpScheme));
}
GURL CookieDomainAndPathToURL(const std::string& domain,
const std::string& path,
CookieSourceScheme source_scheme) {
return CookieDomainAndPathToURL(domain, path,
source_scheme == CookieSourceScheme::kSecure);
}
GURL CookieOriginToURL(const std::string& domain, bool is_https) {
return CookieDomainAndPathToURL(domain, "/", is_https);
}
GURL SimulatedCookieSource(const CanonicalCookie& cookie,
const std::string& source_scheme) {
return CookieDomainAndPathToURL(cookie.Domain(), cookie.Path(),
source_scheme);
}
CookieAccessScheme ProvisionalAccessScheme(const GURL& source_url) {
return source_url.SchemeIsCryptographic()
? CookieAccessScheme::kCryptographic
: IsLocalhost(source_url) ? CookieAccessScheme::kTrustworthy
: CookieAccessScheme::kNonCryptographic;
}
bool IsDomainMatch(const std::string_view domain, const std::string_view host) {
if (host == domain)
return true;
if (domain.empty() || domain[0] != '.')
return false;
if (domain.compare(1, std::string::npos, host) == 0)
return true;
return (host.length() > domain.length() &&
host.compare(host.length() - domain.length(), domain.length(),
domain) == 0);
}
bool IsOnPath(const std::string_view cookie_path, const std::string_view url_path) {
if (cookie_path.empty()) {
return false;
}
if (!url_path.starts_with(cookie_path)) {
return false;
}
if (cookie_path.length() != url_path.length() && cookie_path.back() != '/' &&
url_path[cookie_path.length()] != '/') {
return false;
}
return true;
}
CookiePrefix GetCookiePrefix(const std::string& name) {
constexpr std::string_view kSecurePrefix("__Secure-");
constexpr std::string_view kHostPrefix("__Host-");
constexpr std::string_view kHttpPrefix("__Http-");
constexpr std::string_view kHostHttpPrefix("__Host-Http-");
if (base::StartsWith(name, kSecurePrefix,
base::CompareCase::INSENSITIVE_ASCII)) {
return COOKIE_PREFIX_SECURE;
}
if (base::StartsWith(name, kHttpPrefix,
base::CompareCase::INSENSITIVE_ASCII) &&
base::FeatureList::IsEnabled(features::kPrefixCookieHttp)) {
return COOKIE_PREFIX_HTTP;
}
if (base::StartsWith(name, kHostHttpPrefix,
base::CompareCase::INSENSITIVE_ASCII) &&
base::FeatureList::IsEnabled(features::kPrefixCookieHostHttp)) {
return COOKIE_PREFIX_HOSTHTTP;
}
if (base::StartsWith(name, kHostPrefix,
base::CompareCase::INSENSITIVE_ASCII)) {
return COOKIE_PREFIX_HOST;
}
return COOKIE_PREFIX_NONE;
}
bool IsCookiePrefixValid(CookiePrefix prefix,
const GURL& url,
const ParsedCookie& parsed_cookie) {
return IsCookiePrefixValid(
prefix, url, parsed_cookie.IsSecure(), parsed_cookie.IsHttpOnly(),
parsed_cookie.Domain().value_or(""), parsed_cookie.Path().value_or(""));
}
bool IsCookiePrefixValid(CookiePrefix prefix,
const GURL& url,
bool secure,
bool http_only,
std::string_view domain,
std::string_view path) {
if (prefix == COOKIE_PREFIX_SECURE) {
return HasValidSecurePrefixAttributes(url, secure);
}
if (prefix == COOKIE_PREFIX_HOST) {
return HasValidHostPrefixAttributes(url, secure, domain, path);
}
if (prefix == COOKIE_PREFIX_HTTP) {
return HasValidHttpPrefixAttributes(url, secure, http_only);
}
if (prefix == COOKIE_PREFIX_HOSTHTTP) {
return HasValidHttpPrefixAttributes(url, secure, http_only) &&
HasValidHostPrefixAttributes(url, secure, domain, path);
}
return true;
}
bool IsCookiePartitionedValid(const GURL& url,
const ParsedCookie& parsed_cookie,
bool partition_has_nonce) {
return IsCookiePartitionedValid(
url, parsed_cookie.IsSecure(),
parsed_cookie.IsPartitioned(), partition_has_nonce);
}
bool IsCookiePartitionedValid(const GURL& url,
bool secure,
bool is_partitioned,
bool partition_has_nonce) {
if (!is_partitioned) {
return true;
}
if (partition_has_nonce) {
return true;
}
CookieAccessScheme scheme = cookie_util::ProvisionalAccessScheme(url);
bool result = (scheme != CookieAccessScheme::kNonCryptographic) && secure;
DLOG_IF(WARNING, !result) << "Cookie has invalid Partitioned attribute";
return result;
}
void ParseRequestCookieLine(const std::string& header_value,
ParsedRequestCookies* parsed_cookies) {
std::string::const_iterator i = header_value.begin();
while (i != header_value.end()) {
while (i != header_value.end() && *i == ' ') ++i;
if (i == header_value.end()) return;
std::string::const_iterator cookie_name_beginning = i;
while (i != header_value.end() && *i != '=') ++i;
auto cookie_name = std::string_view(cookie_name_beginning, i);
std::string_view cookie_value;
if (i != header_value.end() && i + 1 != header_value.end()) {
++i;
std::string::const_iterator cookie_value_beginning = i;
if (*i == '"') {
++i;
while (i != header_value.end() && *i != '"') ++i;
if (i == header_value.end()) return;
++i;
cookie_value = std::string_view(cookie_value_beginning, i);
} else {
while (i != header_value.end() && *i != ';') ++i;
cookie_value = std::string_view(cookie_value_beginning, i);
}
}
parsed_cookies->emplace_back(std::string(cookie_name),
std::string(cookie_value));
if (i != header_value.end()) ++i;
}
}
std::string SerializeRequestCookieLine(
const ParsedRequestCookies& parsed_cookies) {
std::string buffer;
for (const auto& parsed_cookie : parsed_cookies) {
if (!buffer.empty())
buffer.append("; ");
buffer.append(parsed_cookie.first.begin(), parsed_cookie.first.end());
buffer.push_back('=');
buffer.append(parsed_cookie.second.begin(), parsed_cookie.second.end());
}
return buffer;
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForRequest(
const std::string& http_method,
const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const std::optional<url::Origin>& initiator,
bool is_main_frame_navigation,
bool force_ignore_site_for_cookies,
bool ignore_unsafe_method_for_same_site_lax) {
if (force_ignore_site_for_cookies)
return CookieOptions::SameSiteCookieContext::MakeInclusive();
ComputeSameSiteContextResult result = ComputeSameSiteContext(
url_chain, site_for_cookies, initiator, true ,
is_main_frame_navigation, false );
ComputeSameSiteContextResult schemeful_result = ComputeSameSiteContext(
url_chain, site_for_cookies, initiator, true ,
is_main_frame_navigation, true );
if (!ignore_unsafe_method_for_same_site_lax &&
!net::HttpUtil::IsMethodSafe(http_method)) {
if (result.context_type == ContextType::SAME_SITE_LAX) {
result.context_type = ContextType::SAME_SITE_LAX_METHOD_UNSAFE;
}
if (schemeful_result.context_type == ContextType::SAME_SITE_LAX) {
schemeful_result.context_type = ContextType::SAME_SITE_LAX_METHOD_UNSAFE;
}
}
return MakeSameSiteCookieContext(result, schemeful_result);
}
NET_EXPORT CookieOptions::SameSiteCookieContext
ComputeSameSiteContextForScriptGet(const GURL& url,
const SiteForCookies& site_for_cookies,
const std::optional<url::Origin>& initiator,
bool force_ignore_site_for_cookies) {
if (force_ignore_site_for_cookies)
return CookieOptions::SameSiteCookieContext::MakeInclusive();
ComputeSameSiteContextResult result = ComputeSameSiteContext(
{url}, site_for_cookies, initiator, false ,
false , false );
ComputeSameSiteContextResult schemeful_result = ComputeSameSiteContext(
{url}, site_for_cookies, initiator, false ,
false , true );
return MakeSameSiteCookieContext(result, schemeful_result);
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForResponse(
const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const std::optional<url::Origin>& initiator,
bool is_main_frame_navigation,
bool force_ignore_site_for_cookies) {
if (force_ignore_site_for_cookies)
return CookieOptions::SameSiteCookieContext::MakeInclusiveForSet();
DCHECK(!url_chain.empty());
if (is_main_frame_navigation && !site_for_cookies.IsNull()) {
DCHECK(
site_for_cookies.IsFirstPartyWithSchemefulMode(url_chain.back(), true));
DCHECK(!url_chain.back().SchemeIsWSOrWSS());
CookieOptions::SameSiteCookieContext result =
CookieOptions::SameSiteCookieContext::MakeInclusiveForSet();
const GURL& request_url = url_chain.back();
for (bool compute_schemefully : {false, true}) {
bool same_site_initiator =
!initiator ||
SiteForCookies::FromOrigin(initiator.value())
.IsFirstPartyWithSchemefulMode(request_url, compute_schemefully);
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 same_site_redirect_chain =
url_chain.size() == 1u ||
std::ranges::all_of(url_chain, is_same_site_with_site_for_cookies);
CookieOptions::SameSiteCookieContext::ContextMetadata& result_metadata =
compute_schemefully ? result.schemeful_metadata() : result.metadata();
result_metadata.redirect_type_bug_1221316 =
ComputeContextRedirectTypeBug1221316(
url_chain.size() == 1u, same_site_initiator,
true ,
same_site_redirect_chain);
}
return result;
}
return ComputeSameSiteContextForSet(url_chain, site_for_cookies, initiator,
true ,
is_main_frame_navigation);
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForScriptSet(
const GURL& url,
const SiteForCookies& site_for_cookies,
bool force_ignore_site_for_cookies) {
if (force_ignore_site_for_cookies)
return CookieOptions::SameSiteCookieContext::MakeInclusiveForSet();
return ComputeSameSiteContextForSet(
{url}, site_for_cookies, std::nullopt ,
false , false );
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSubresource(
const GURL& url,
const SiteForCookies& site_for_cookies,
bool force_ignore_site_for_cookies) {
if (force_ignore_site_for_cookies)
return CookieOptions::SameSiteCookieContext::MakeInclusive();
if (!site_for_cookies.IsFirstPartyWithSchemefulMode(url, false)) {
return CookieOptions::SameSiteCookieContext(ContextType::CROSS_SITE,
ContextType::CROSS_SITE);
}
if (!site_for_cookies.IsFirstPartyWithSchemefulMode(url, true)) {
return CookieOptions::SameSiteCookieContext(ContextType::SAME_SITE_STRICT,
ContextType::CROSS_SITE);
}
return CookieOptions::SameSiteCookieContext::MakeInclusive();
}
bool IsPortBoundCookiesEnabled() {
return base::FeatureList::IsEnabled(features::kEnablePortBoundCookies);
}
bool IsSchemeBoundCookiesEnabled() {
return base::FeatureList::IsEnabled(features::kEnableSchemeBoundCookies);
}
bool IsOriginBoundCookiesPartiallyEnabled() {
return IsPortBoundCookiesEnabled() || IsSchemeBoundCookiesEnabled();
}
bool IsTimeLimitedInsecureCookiesEnabled() {
return IsSchemeBoundCookiesEnabled() &&
base::FeatureList::IsEnabled(features::kTimeLimitedInsecureCookies);
}
std::optional<
std::pair<FirstPartySetMetadata, FirstPartySetsCacheFilter::MatchInfo>>
ComputeFirstPartySetMetadataMaybeAsync(
const SchemefulSite& request_site,
const IsolationInfo& isolation_info,
const CookieAccessDelegate* cookie_access_delegate,
base::OnceCallback<void(FirstPartySetMetadata,
FirstPartySetsCacheFilter::MatchInfo)> callback) {
if (cookie_access_delegate) {
return cookie_access_delegate->ComputeFirstPartySetMetadataMaybeAsync(
request_site,
base::OptionalToPtr(
isolation_info.network_isolation_key().GetTopFrameSite()),
std::move(callback));
}
return std::pair(FirstPartySetMetadata(),
FirstPartySetsCacheFilter::MatchInfo());
}
CookieOptions::SameSiteCookieContext::ContextMetadata::HttpMethod
HttpMethodStringToEnum(const std::string& in) {
using HttpMethod =
CookieOptions::SameSiteCookieContext::ContextMetadata::HttpMethod;
if (in == "GET")
return HttpMethod::kGet;
if (in == "HEAD")
return HttpMethod::kHead;
if (in == "POST")
return HttpMethod::kPost;
if (in == "PUT")
return HttpMethod::KPut;
if (in == "DELETE")
return HttpMethod::kDelete;
if (in == "CONNECT")
return HttpMethod::kConnect;
if (in == "OPTIONS")
return HttpMethod::kOptions;
if (in == "TRACE")
return HttpMethod::kTrace;
if (in == "PATCH")
return HttpMethod::kPatch;
return HttpMethod::kUnknown;
}
bool IsCookieAccessResultInclude(CookieAccessResult cookie_access_result) {
return cookie_access_result.status.IsInclude();
}
CookieList StripAccessResults(
const CookieAccessResultList& cookie_access_results_list) {
CookieList cookies;
for (const CookieWithAccessResult& cookie_with_access_result :
cookie_access_results_list) {
cookies.push_back(cookie_with_access_result.cookie);
}
return cookies;
}
NET_EXPORT void RecordCookiePortOmniboxHistograms(const GURL& url) {
int port = url.EffectiveIntPort();
if (port == url::PORT_UNSPECIFIED)
return;
if (IsLocalhost(url)) {
UMA_HISTOGRAM_ENUMERATION("Cookie.Port.OmniboxURLNavigation.Localhost",
ReducePortRangeForCookieHistogram(port));
} else {
UMA_HISTOGRAM_ENUMERATION("Cookie.Port.OmniboxURLNavigation.RemoteHost",
ReducePortRangeForCookieHistogram(port));
}
}
NET_EXPORT void DCheckIncludedAndExcludedCookieLists(
const CookieAccessResultList& included_cookies,
const CookieAccessResultList& excluded_cookies) {
DCHECK(std::ranges::all_of(included_cookies,
[](const net::CookieWithAccessResult& cookie) {
return cookie.access_result.status.IsInclude();
}));
DCHECK(std::ranges::none_of(excluded_cookies,
[](const net::CookieWithAccessResult& cookie) {
return cookie.access_result.status.IsInclude();
}));
DCHECK(
std::ranges::is_sorted(included_cookies, CookieWithAccessResultSorter));
}
NET_EXPORT bool IsForceThirdPartyCookieBlockingEnabled() {
return base::FeatureList::IsEnabled(
features::kForceThirdPartyCookieBlocking) &&
base::FeatureList::IsEnabled(features::kThirdPartyStoragePartitioning);
}
bool ShouldAddInitialStorageAccessApiOverride(
const GURL& url,
StorageAccessApiStatus api_status,
base::optional_ref<const url::Origin> request_initiator) {
return api_status == StorageAccessApiStatus::kAccessViaAPI &&
request_initiator && request_initiator->IsSameOriginWith(url);
}
}