xref: /aosp_15_r20/external/cronet/net/cookies/cookie_base.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2024 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_base.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include "base/containers/contains.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
10*6777b538SAndroid Build Coastguard Worker #include "net/base/features.h"
11*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_inclusion_status.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_util.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker namespace net {
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker // Captures Strict -> Lax context downgrade with Strict cookie
IsBreakingStrictToLaxDowngrade(CookieOptions::SameSiteCookieContext::ContextType context,CookieOptions::SameSiteCookieContext::ContextType schemeful_context,CookieEffectiveSameSite effective_same_site,bool is_cookie_being_set)19*6777b538SAndroid Build Coastguard Worker bool IsBreakingStrictToLaxDowngrade(
20*6777b538SAndroid Build Coastguard Worker     CookieOptions::SameSiteCookieContext::ContextType context,
21*6777b538SAndroid Build Coastguard Worker     CookieOptions::SameSiteCookieContext::ContextType schemeful_context,
22*6777b538SAndroid Build Coastguard Worker     CookieEffectiveSameSite effective_same_site,
23*6777b538SAndroid Build Coastguard Worker     bool is_cookie_being_set) {
24*6777b538SAndroid Build Coastguard Worker   if (context ==
25*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT &&
26*6777b538SAndroid Build Coastguard Worker       schemeful_context ==
27*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX &&
28*6777b538SAndroid Build Coastguard Worker       effective_same_site == CookieEffectiveSameSite::STRICT_MODE) {
29*6777b538SAndroid Build Coastguard Worker     // This downgrade only applies when a SameSite=Strict cookie is being sent.
30*6777b538SAndroid Build Coastguard Worker     // A Strict -> Lax downgrade will not affect a Strict cookie which is being
31*6777b538SAndroid Build Coastguard Worker     // set because it will be set in either context.
32*6777b538SAndroid Build Coastguard Worker     return !is_cookie_being_set;
33*6777b538SAndroid Build Coastguard Worker   }
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker   return false;
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker 
38*6777b538SAndroid Build Coastguard Worker // Captures Strict -> Cross-site context downgrade with {Strict, Lax} cookie
39*6777b538SAndroid Build Coastguard Worker // Captures Strict -> Lax Unsafe context downgrade with {Strict, Lax} cookie.
40*6777b538SAndroid Build Coastguard Worker // This is treated as a cross-site downgrade due to the Lax Unsafe context
41*6777b538SAndroid Build Coastguard Worker // behaving like cross-site.
IsBreakingStrictToCrossDowngrade(CookieOptions::SameSiteCookieContext::ContextType context,CookieOptions::SameSiteCookieContext::ContextType schemeful_context,CookieEffectiveSameSite effective_same_site)42*6777b538SAndroid Build Coastguard Worker bool IsBreakingStrictToCrossDowngrade(
43*6777b538SAndroid Build Coastguard Worker     CookieOptions::SameSiteCookieContext::ContextType context,
44*6777b538SAndroid Build Coastguard Worker     CookieOptions::SameSiteCookieContext::ContextType schemeful_context,
45*6777b538SAndroid Build Coastguard Worker     CookieEffectiveSameSite effective_same_site) {
46*6777b538SAndroid Build Coastguard Worker   bool breaking_schemeful_context =
47*6777b538SAndroid Build Coastguard Worker       schemeful_context ==
48*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE ||
49*6777b538SAndroid Build Coastguard Worker       schemeful_context == CookieOptions::SameSiteCookieContext::ContextType::
50*6777b538SAndroid Build Coastguard Worker                                SAME_SITE_LAX_METHOD_UNSAFE;
51*6777b538SAndroid Build Coastguard Worker 
52*6777b538SAndroid Build Coastguard Worker   bool strict_lax_enforcement =
53*6777b538SAndroid Build Coastguard Worker       effective_same_site == CookieEffectiveSameSite::STRICT_MODE ||
54*6777b538SAndroid Build Coastguard Worker       effective_same_site == CookieEffectiveSameSite::LAX_MODE ||
55*6777b538SAndroid Build Coastguard Worker       // Treat LAX_MODE_ALLOW_UNSAFE the same as LAX_MODE for the purposes of
56*6777b538SAndroid Build Coastguard Worker       // our SameSite enforcement check.
57*6777b538SAndroid Build Coastguard Worker       effective_same_site == CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE;
58*6777b538SAndroid Build Coastguard Worker 
59*6777b538SAndroid Build Coastguard Worker   if (context ==
60*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT &&
61*6777b538SAndroid Build Coastguard Worker       breaking_schemeful_context && strict_lax_enforcement) {
62*6777b538SAndroid Build Coastguard Worker     return true;
63*6777b538SAndroid Build Coastguard Worker   }
64*6777b538SAndroid Build Coastguard Worker 
65*6777b538SAndroid Build Coastguard Worker   return false;
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker 
68*6777b538SAndroid Build Coastguard Worker // Captures Lax -> Cross context downgrade with {Strict, Lax} cookies.
69*6777b538SAndroid Build Coastguard Worker // Ignores Lax Unsafe context.
IsBreakingLaxToCrossDowngrade(CookieOptions::SameSiteCookieContext::ContextType context,CookieOptions::SameSiteCookieContext::ContextType schemeful_context,CookieEffectiveSameSite effective_same_site,bool is_cookie_being_set)70*6777b538SAndroid Build Coastguard Worker bool IsBreakingLaxToCrossDowngrade(
71*6777b538SAndroid Build Coastguard Worker     CookieOptions::SameSiteCookieContext::ContextType context,
72*6777b538SAndroid Build Coastguard Worker     CookieOptions::SameSiteCookieContext::ContextType schemeful_context,
73*6777b538SAndroid Build Coastguard Worker     CookieEffectiveSameSite effective_same_site,
74*6777b538SAndroid Build Coastguard Worker     bool is_cookie_being_set) {
75*6777b538SAndroid Build Coastguard Worker   bool lax_enforcement =
76*6777b538SAndroid Build Coastguard Worker       effective_same_site == CookieEffectiveSameSite::LAX_MODE ||
77*6777b538SAndroid Build Coastguard Worker       // Treat LAX_MODE_ALLOW_UNSAFE the same as LAX_MODE for the purposes of
78*6777b538SAndroid Build Coastguard Worker       // our SameSite enforcement check.
79*6777b538SAndroid Build Coastguard Worker       effective_same_site == CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE;
80*6777b538SAndroid Build Coastguard Worker 
81*6777b538SAndroid Build Coastguard Worker   if (context ==
82*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX &&
83*6777b538SAndroid Build Coastguard Worker       schemeful_context ==
84*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE) {
85*6777b538SAndroid Build Coastguard Worker     // For SameSite=Strict cookies this downgrade only applies when it is being
86*6777b538SAndroid Build Coastguard Worker     // set. A Lax -> Cross downgrade will not affect a Strict cookie which is
87*6777b538SAndroid Build Coastguard Worker     // being sent because it wouldn't be sent in either context.
88*6777b538SAndroid Build Coastguard Worker     return effective_same_site == CookieEffectiveSameSite::STRICT_MODE
89*6777b538SAndroid Build Coastguard Worker                ? is_cookie_being_set
90*6777b538SAndroid Build Coastguard Worker                : lax_enforcement;
91*6777b538SAndroid Build Coastguard Worker   }
92*6777b538SAndroid Build Coastguard Worker 
93*6777b538SAndroid Build Coastguard Worker   return false;
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker 
ApplySameSiteCookieWarningToStatus(CookieSameSite samesite,CookieEffectiveSameSite effective_samesite,bool is_secure,const CookieOptions::SameSiteCookieContext & same_site_context,CookieInclusionStatus * status,bool is_cookie_being_set)96*6777b538SAndroid Build Coastguard Worker void ApplySameSiteCookieWarningToStatus(
97*6777b538SAndroid Build Coastguard Worker     CookieSameSite samesite,
98*6777b538SAndroid Build Coastguard Worker     CookieEffectiveSameSite effective_samesite,
99*6777b538SAndroid Build Coastguard Worker     bool is_secure,
100*6777b538SAndroid Build Coastguard Worker     const CookieOptions::SameSiteCookieContext& same_site_context,
101*6777b538SAndroid Build Coastguard Worker     CookieInclusionStatus* status,
102*6777b538SAndroid Build Coastguard Worker     bool is_cookie_being_set) {
103*6777b538SAndroid Build Coastguard Worker   if (samesite == CookieSameSite::UNSPECIFIED &&
104*6777b538SAndroid Build Coastguard Worker       same_site_context.GetContextForCookieInclusion() <
105*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX) {
106*6777b538SAndroid Build Coastguard Worker     status->AddWarningReason(
107*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
108*6777b538SAndroid Build Coastguard Worker   }
109*6777b538SAndroid Build Coastguard Worker   if (effective_samesite == CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE &&
110*6777b538SAndroid Build Coastguard Worker       same_site_context.GetContextForCookieInclusion() ==
111*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::
112*6777b538SAndroid Build Coastguard Worker               SAME_SITE_LAX_METHOD_UNSAFE) {
113*6777b538SAndroid Build Coastguard Worker     // This warning is more specific so remove the previous, more general,
114*6777b538SAndroid Build Coastguard Worker     // warning.
115*6777b538SAndroid Build Coastguard Worker     status->RemoveWarningReason(
116*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
117*6777b538SAndroid Build Coastguard Worker     status->AddWarningReason(
118*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
119*6777b538SAndroid Build Coastguard Worker   }
120*6777b538SAndroid Build Coastguard Worker   if (samesite == CookieSameSite::NO_RESTRICTION && !is_secure) {
121*6777b538SAndroid Build Coastguard Worker     status->AddWarningReason(
122*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE);
123*6777b538SAndroid Build Coastguard Worker   }
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // Add a warning if the cookie would be accessible in
126*6777b538SAndroid Build Coastguard Worker   // |same_site_context|::context but not in
127*6777b538SAndroid Build Coastguard Worker   // |same_site_context|::schemeful_context.
128*6777b538SAndroid Build Coastguard Worker   if (IsBreakingStrictToLaxDowngrade(same_site_context.context(),
129*6777b538SAndroid Build Coastguard Worker                                      same_site_context.schemeful_context(),
130*6777b538SAndroid Build Coastguard Worker                                      effective_samesite, is_cookie_being_set)) {
131*6777b538SAndroid Build Coastguard Worker     status->AddWarningReason(
132*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE);
133*6777b538SAndroid Build Coastguard Worker   } else if (IsBreakingStrictToCrossDowngrade(
134*6777b538SAndroid Build Coastguard Worker                  same_site_context.context(),
135*6777b538SAndroid Build Coastguard Worker                  same_site_context.schemeful_context(), effective_samesite)) {
136*6777b538SAndroid Build Coastguard Worker     // Which warning to apply depends on the SameSite value.
137*6777b538SAndroid Build Coastguard Worker     if (effective_samesite == CookieEffectiveSameSite::STRICT_MODE) {
138*6777b538SAndroid Build Coastguard Worker       status->AddWarningReason(
139*6777b538SAndroid Build Coastguard Worker           CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE);
140*6777b538SAndroid Build Coastguard Worker     } else {
141*6777b538SAndroid Build Coastguard Worker       // LAX_MODE or LAX_MODE_ALLOW_UNSAFE.
142*6777b538SAndroid Build Coastguard Worker       status->AddWarningReason(
143*6777b538SAndroid Build Coastguard Worker           CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE);
144*6777b538SAndroid Build Coastguard Worker     }
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   } else if (IsBreakingLaxToCrossDowngrade(
147*6777b538SAndroid Build Coastguard Worker                  same_site_context.context(),
148*6777b538SAndroid Build Coastguard Worker                  same_site_context.schemeful_context(), effective_samesite,
149*6777b538SAndroid Build Coastguard Worker                  is_cookie_being_set)) {
150*6777b538SAndroid Build Coastguard Worker     // Which warning to apply depends on the SameSite value.
151*6777b538SAndroid Build Coastguard Worker     if (effective_samesite == CookieEffectiveSameSite::STRICT_MODE) {
152*6777b538SAndroid Build Coastguard Worker       status->AddWarningReason(
153*6777b538SAndroid Build Coastguard Worker           CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE);
154*6777b538SAndroid Build Coastguard Worker     } else {
155*6777b538SAndroid Build Coastguard Worker       // LAX_MODE or LAX_MODE_ALLOW_UNSAFE.
156*6777b538SAndroid Build Coastguard Worker       // This warning applies to both set/send.
157*6777b538SAndroid Build Coastguard Worker       status->AddWarningReason(
158*6777b538SAndroid Build Coastguard Worker           CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE);
159*6777b538SAndroid Build Coastguard Worker     }
160*6777b538SAndroid Build Coastguard Worker   }
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker   // Apply warning for whether inclusion was changed by considering redirects
163*6777b538SAndroid Build Coastguard Worker   // for the SameSite context calculation. This does not look at the actual
164*6777b538SAndroid Build Coastguard Worker   // inclusion or exclusion, but only at whether the inclusion differs between
165*6777b538SAndroid Build Coastguard Worker   // considering redirects and not.
166*6777b538SAndroid Build Coastguard Worker   using ContextDowngradeType = CookieOptions::SameSiteCookieContext::
167*6777b538SAndroid Build Coastguard Worker       ContextMetadata::ContextDowngradeType;
168*6777b538SAndroid Build Coastguard Worker   const auto& metadata = same_site_context.GetMetadataForCurrentSchemefulMode();
169*6777b538SAndroid Build Coastguard Worker   bool apply_cross_site_redirect_downgrade_warning = false;
170*6777b538SAndroid Build Coastguard Worker   switch (effective_samesite) {
171*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::STRICT_MODE:
172*6777b538SAndroid Build Coastguard Worker       // Strict contexts are all normalized to lax for cookie writes, so a
173*6777b538SAndroid Build Coastguard Worker       // strict-to-{lax,cross} downgrade cannot occur for response cookies.
174*6777b538SAndroid Build Coastguard Worker       apply_cross_site_redirect_downgrade_warning =
175*6777b538SAndroid Build Coastguard Worker           is_cookie_being_set ? metadata.cross_site_redirect_downgrade ==
176*6777b538SAndroid Build Coastguard Worker                                     ContextDowngradeType::kLaxToCross
177*6777b538SAndroid Build Coastguard Worker                               : (metadata.cross_site_redirect_downgrade ==
178*6777b538SAndroid Build Coastguard Worker                                      ContextDowngradeType::kStrictToLax ||
179*6777b538SAndroid Build Coastguard Worker                                  metadata.cross_site_redirect_downgrade ==
180*6777b538SAndroid Build Coastguard Worker                                      ContextDowngradeType::kStrictToCross);
181*6777b538SAndroid Build Coastguard Worker       break;
182*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::LAX_MODE:
183*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
184*6777b538SAndroid Build Coastguard Worker       // Note that a lax-to-cross downgrade can only happen for response
185*6777b538SAndroid Build Coastguard Worker       // cookies, because a laxly same-site context only happens for a safe
186*6777b538SAndroid Build Coastguard Worker       // top-level cross-site request, which cannot be downgraded due to a
187*6777b538SAndroid Build Coastguard Worker       // cross-site redirect to a non-top-level or unsafe cross-site request.
188*6777b538SAndroid Build Coastguard Worker       apply_cross_site_redirect_downgrade_warning =
189*6777b538SAndroid Build Coastguard Worker           metadata.cross_site_redirect_downgrade ==
190*6777b538SAndroid Build Coastguard Worker           (is_cookie_being_set ? ContextDowngradeType::kLaxToCross
191*6777b538SAndroid Build Coastguard Worker                                : ContextDowngradeType::kStrictToCross);
192*6777b538SAndroid Build Coastguard Worker       break;
193*6777b538SAndroid Build Coastguard Worker     default:
194*6777b538SAndroid Build Coastguard Worker       break;
195*6777b538SAndroid Build Coastguard Worker   }
196*6777b538SAndroid Build Coastguard Worker   if (apply_cross_site_redirect_downgrade_warning) {
197*6777b538SAndroid Build Coastguard Worker     status->AddWarningReason(
198*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::
199*6777b538SAndroid Build Coastguard Worker             WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION);
200*6777b538SAndroid Build Coastguard Worker   }
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker   // If there are reasons to exclude the cookie other than SameSite, don't warn
203*6777b538SAndroid Build Coastguard Worker   // about the cookie at all.
204*6777b538SAndroid Build Coastguard Worker   status->MaybeClearSameSiteWarning();
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker 
207*6777b538SAndroid Build Coastguard Worker }  // namespace
208*6777b538SAndroid Build Coastguard Worker 
IncludeForRequestURL(const GURL & url,const CookieOptions & options,const CookieAccessParams & params) const209*6777b538SAndroid Build Coastguard Worker CookieAccessResult CookieBase::IncludeForRequestURL(
210*6777b538SAndroid Build Coastguard Worker     const GURL& url,
211*6777b538SAndroid Build Coastguard Worker     const CookieOptions& options,
212*6777b538SAndroid Build Coastguard Worker     const CookieAccessParams& params) const {
213*6777b538SAndroid Build Coastguard Worker   CookieInclusionStatus status;
214*6777b538SAndroid Build Coastguard Worker   // Filter out HttpOnly cookies, per options.
215*6777b538SAndroid Build Coastguard Worker   if (options.exclude_httponly() && IsHttpOnly()) {
216*6777b538SAndroid Build Coastguard Worker     status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_HTTP_ONLY);
217*6777b538SAndroid Build Coastguard Worker   }
218*6777b538SAndroid Build Coastguard Worker   // Secure cookies should not be included in requests for URLs with an
219*6777b538SAndroid Build Coastguard Worker   // insecure scheme, unless it is a localhost url, or the CookieAccessDelegate
220*6777b538SAndroid Build Coastguard Worker   // otherwise denotes them as trustworthy
221*6777b538SAndroid Build Coastguard Worker   // (`delegate_treats_url_as_trustworthy`).
222*6777b538SAndroid Build Coastguard Worker   bool is_allowed_to_access_secure_cookies = false;
223*6777b538SAndroid Build Coastguard Worker   CookieAccessScheme cookie_access_scheme =
224*6777b538SAndroid Build Coastguard Worker       cookie_util::ProvisionalAccessScheme(url);
225*6777b538SAndroid Build Coastguard Worker   if (cookie_access_scheme == CookieAccessScheme::kNonCryptographic &&
226*6777b538SAndroid Build Coastguard Worker       params.delegate_treats_url_as_trustworthy) {
227*6777b538SAndroid Build Coastguard Worker     cookie_access_scheme = CookieAccessScheme::kTrustworthy;
228*6777b538SAndroid Build Coastguard Worker   }
229*6777b538SAndroid Build Coastguard Worker   switch (cookie_access_scheme) {
230*6777b538SAndroid Build Coastguard Worker     case CookieAccessScheme::kNonCryptographic:
231*6777b538SAndroid Build Coastguard Worker       if (SecureAttribute()) {
232*6777b538SAndroid Build Coastguard Worker         status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
233*6777b538SAndroid Build Coastguard Worker       }
234*6777b538SAndroid Build Coastguard Worker       break;
235*6777b538SAndroid Build Coastguard Worker     case CookieAccessScheme::kTrustworthy:
236*6777b538SAndroid Build Coastguard Worker       is_allowed_to_access_secure_cookies = true;
237*6777b538SAndroid Build Coastguard Worker       if (SecureAttribute() ||
238*6777b538SAndroid Build Coastguard Worker           (cookie_util::IsSchemeBoundCookiesEnabled() &&
239*6777b538SAndroid Build Coastguard Worker            source_scheme_ == CookieSourceScheme::kSecure)) {
240*6777b538SAndroid Build Coastguard Worker         status.AddWarningReason(
241*6777b538SAndroid Build Coastguard Worker             CookieInclusionStatus::
242*6777b538SAndroid Build Coastguard Worker                 WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC);
243*6777b538SAndroid Build Coastguard Worker       }
244*6777b538SAndroid Build Coastguard Worker       break;
245*6777b538SAndroid Build Coastguard Worker     case CookieAccessScheme::kCryptographic:
246*6777b538SAndroid Build Coastguard Worker       is_allowed_to_access_secure_cookies = true;
247*6777b538SAndroid Build Coastguard Worker       break;
248*6777b538SAndroid Build Coastguard Worker   }
249*6777b538SAndroid Build Coastguard Worker 
250*6777b538SAndroid Build Coastguard Worker   // For the following two sections we're checking to see if a cookie's
251*6777b538SAndroid Build Coastguard Worker   // `source_scheme_` and `source_port_` match that of the url's. In most cases
252*6777b538SAndroid Build Coastguard Worker   // this is a direct comparison but it does get a bit more complicated when
253*6777b538SAndroid Build Coastguard Worker   // trustworthy origins are taken into accounts. Note that here, a kTrustworthy
254*6777b538SAndroid Build Coastguard Worker   // url must have a non-secure scheme (http) because otherwise it'd be a
255*6777b538SAndroid Build Coastguard Worker   // kCryptographic url.
256*6777b538SAndroid Build Coastguard Worker   //
257*6777b538SAndroid Build Coastguard Worker   // Trustworthy origins are allowed to both secure and non-secure cookies. This
258*6777b538SAndroid Build Coastguard Worker   // means that we'll match source_scheme_ for both their usual kNonSecure as
259*6777b538SAndroid Build Coastguard Worker   // well as KSecure. For source_port_ we'll match per usual as well as any 443
260*6777b538SAndroid Build Coastguard Worker   // ports, since those are the default values for secure cookies and we still
261*6777b538SAndroid Build Coastguard Worker   // want to be able to access them.
262*6777b538SAndroid Build Coastguard Worker 
263*6777b538SAndroid Build Coastguard Worker   // A cookie with a source scheme of kSecure shouldn't be accessible by
264*6777b538SAndroid Build Coastguard Worker   // kNonCryptographic urls. But we can skip adding a status if the cookie is
265*6777b538SAndroid Build Coastguard Worker   // already blocked due to the `Secure` attribute.
266*6777b538SAndroid Build Coastguard Worker   if (source_scheme_ == CookieSourceScheme::kSecure &&
267*6777b538SAndroid Build Coastguard Worker       cookie_access_scheme == CookieAccessScheme::kNonCryptographic &&
268*6777b538SAndroid Build Coastguard Worker       !status.HasExclusionReason(CookieInclusionStatus::EXCLUDE_SECURE_ONLY)) {
269*6777b538SAndroid Build Coastguard Worker     if (cookie_util::IsSchemeBoundCookiesEnabled()) {
270*6777b538SAndroid Build Coastguard Worker       status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_SCHEME_MISMATCH);
271*6777b538SAndroid Build Coastguard Worker     } else {
272*6777b538SAndroid Build Coastguard Worker       status.AddWarningReason(CookieInclusionStatus::WARN_SCHEME_MISMATCH);
273*6777b538SAndroid Build Coastguard Worker     }
274*6777b538SAndroid Build Coastguard Worker   }
275*6777b538SAndroid Build Coastguard Worker   // A cookie with a source scheme of kNonSecure shouldn't be accessible by
276*6777b538SAndroid Build Coastguard Worker   // kCryptographic urls.
277*6777b538SAndroid Build Coastguard Worker   else if (source_scheme_ == CookieSourceScheme::kNonSecure &&
278*6777b538SAndroid Build Coastguard Worker            cookie_access_scheme == CookieAccessScheme::kCryptographic) {
279*6777b538SAndroid Build Coastguard Worker     if (cookie_util::IsSchemeBoundCookiesEnabled()) {
280*6777b538SAndroid Build Coastguard Worker       status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_SCHEME_MISMATCH);
281*6777b538SAndroid Build Coastguard Worker     } else {
282*6777b538SAndroid Build Coastguard Worker       status.AddWarningReason(CookieInclusionStatus::WARN_SCHEME_MISMATCH);
283*6777b538SAndroid Build Coastguard Worker     }
284*6777b538SAndroid Build Coastguard Worker   }
285*6777b538SAndroid Build Coastguard Worker   // Else, the cookie has a source scheme of kUnset or the access scheme is
286*6777b538SAndroid Build Coastguard Worker   // kTrustworthy. Neither of which will block the cookie.
287*6777b538SAndroid Build Coastguard Worker 
288*6777b538SAndroid Build Coastguard Worker   int url_port = url.EffectiveIntPort();
289*6777b538SAndroid Build Coastguard Worker   CHECK(url_port != url::PORT_INVALID);
290*6777b538SAndroid Build Coastguard Worker   // The cookie's source port either must match the url's port, be
291*6777b538SAndroid Build Coastguard Worker   // PORT_UNSPECIFIED, or the cookie must be a domain cookie.
292*6777b538SAndroid Build Coastguard Worker   bool port_matches = url_port == source_port_ ||
293*6777b538SAndroid Build Coastguard Worker                       source_port_ == url::PORT_UNSPECIFIED || IsDomainCookie();
294*6777b538SAndroid Build Coastguard Worker 
295*6777b538SAndroid Build Coastguard Worker   // Or if the url is trustworthy, we'll also match 443 (in order to get secure
296*6777b538SAndroid Build Coastguard Worker   // cookies).
297*6777b538SAndroid Build Coastguard Worker   bool trustworthy_and_443 =
298*6777b538SAndroid Build Coastguard Worker       cookie_access_scheme == CookieAccessScheme::kTrustworthy &&
299*6777b538SAndroid Build Coastguard Worker       source_port_ == 443;
300*6777b538SAndroid Build Coastguard Worker   if (!port_matches && !trustworthy_and_443) {
301*6777b538SAndroid Build Coastguard Worker     if (cookie_util::IsPortBoundCookiesEnabled()) {
302*6777b538SAndroid Build Coastguard Worker       status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_PORT_MISMATCH);
303*6777b538SAndroid Build Coastguard Worker     } else {
304*6777b538SAndroid Build Coastguard Worker       status.AddWarningReason(CookieInclusionStatus::WARN_PORT_MISMATCH);
305*6777b538SAndroid Build Coastguard Worker     }
306*6777b538SAndroid Build Coastguard Worker   }
307*6777b538SAndroid Build Coastguard Worker 
308*6777b538SAndroid Build Coastguard Worker   // Don't include cookies for requests that don't apply to the cookie domain.
309*6777b538SAndroid Build Coastguard Worker   if (!IsDomainMatch(url.host())) {
310*6777b538SAndroid Build Coastguard Worker     status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH);
311*6777b538SAndroid Build Coastguard Worker   }
312*6777b538SAndroid Build Coastguard Worker   // Don't include cookies for requests with a url path that does not path
313*6777b538SAndroid Build Coastguard Worker   // match the cookie-path.
314*6777b538SAndroid Build Coastguard Worker   if (!IsOnPath(url.path())) {
315*6777b538SAndroid Build Coastguard Worker     status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_NOT_ON_PATH);
316*6777b538SAndroid Build Coastguard Worker   }
317*6777b538SAndroid Build Coastguard Worker 
318*6777b538SAndroid Build Coastguard Worker   // For LEGACY cookies we should always return the schemeless context,
319*6777b538SAndroid Build Coastguard Worker   // otherwise let GetContextForCookieInclusion() decide.
320*6777b538SAndroid Build Coastguard Worker   const CookieOptions::SameSiteCookieContext::ContextType
321*6777b538SAndroid Build Coastguard Worker       cookie_inclusion_context =
322*6777b538SAndroid Build Coastguard Worker           params.access_semantics == CookieAccessSemantics::LEGACY
323*6777b538SAndroid Build Coastguard Worker               ? options.same_site_cookie_context().context()
324*6777b538SAndroid Build Coastguard Worker               : options.same_site_cookie_context()
325*6777b538SAndroid Build Coastguard Worker                     .GetContextForCookieInclusion();
326*6777b538SAndroid Build Coastguard Worker 
327*6777b538SAndroid Build Coastguard Worker   // Don't include same-site cookies for cross-site requests.
328*6777b538SAndroid Build Coastguard Worker   CookieEffectiveSameSite effective_same_site =
329*6777b538SAndroid Build Coastguard Worker       GetEffectiveSameSite(params.access_semantics);
330*6777b538SAndroid Build Coastguard Worker   DCHECK(effective_same_site != CookieEffectiveSameSite::UNDEFINED);
331*6777b538SAndroid Build Coastguard Worker 
332*6777b538SAndroid Build Coastguard Worker   switch (effective_same_site) {
333*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::STRICT_MODE:
334*6777b538SAndroid Build Coastguard Worker       if (cookie_inclusion_context <
335*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT) {
336*6777b538SAndroid Build Coastguard Worker         status.AddExclusionReason(
337*6777b538SAndroid Build Coastguard Worker             CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT);
338*6777b538SAndroid Build Coastguard Worker       }
339*6777b538SAndroid Build Coastguard Worker       break;
340*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::LAX_MODE:
341*6777b538SAndroid Build Coastguard Worker       if (cookie_inclusion_context <
342*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX) {
343*6777b538SAndroid Build Coastguard Worker         status.AddExclusionReason(
344*6777b538SAndroid Build Coastguard Worker             (SameSite() == CookieSameSite::UNSPECIFIED)
345*6777b538SAndroid Build Coastguard Worker                 ? CookieInclusionStatus::
346*6777b538SAndroid Build Coastguard Worker                       EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX
347*6777b538SAndroid Build Coastguard Worker                 : CookieInclusionStatus::EXCLUDE_SAMESITE_LAX);
348*6777b538SAndroid Build Coastguard Worker       }
349*6777b538SAndroid Build Coastguard Worker       break;
350*6777b538SAndroid Build Coastguard Worker     // TODO(crbug.com/990439): Add a browsertest for this behavior.
351*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
352*6777b538SAndroid Build Coastguard Worker       DCHECK(SameSite() == CookieSameSite::UNSPECIFIED);
353*6777b538SAndroid Build Coastguard Worker       if (cookie_inclusion_context <
354*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::
355*6777b538SAndroid Build Coastguard Worker               SAME_SITE_LAX_METHOD_UNSAFE) {
356*6777b538SAndroid Build Coastguard Worker         // TODO(chlily): Do we need a separate CookieInclusionStatus for this?
357*6777b538SAndroid Build Coastguard Worker         status.AddExclusionReason(
358*6777b538SAndroid Build Coastguard Worker             CookieInclusionStatus::EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX);
359*6777b538SAndroid Build Coastguard Worker       }
360*6777b538SAndroid Build Coastguard Worker       break;
361*6777b538SAndroid Build Coastguard Worker     default:
362*6777b538SAndroid Build Coastguard Worker       break;
363*6777b538SAndroid Build Coastguard Worker   }
364*6777b538SAndroid Build Coastguard Worker 
365*6777b538SAndroid Build Coastguard Worker   // Unless legacy access semantics are in effect, SameSite=None cookies without
366*6777b538SAndroid Build Coastguard Worker   // the Secure attribute should be ignored. This can apply to cookies which
367*6777b538SAndroid Build Coastguard Worker   // were created before "SameSite=None requires Secure" was enabled (as
368*6777b538SAndroid Build Coastguard Worker   // SameSite=None insecure cookies cannot be set while the options are on).
369*6777b538SAndroid Build Coastguard Worker   if (params.access_semantics != CookieAccessSemantics::LEGACY &&
370*6777b538SAndroid Build Coastguard Worker       SameSite() == CookieSameSite::NO_RESTRICTION && !SecureAttribute()) {
371*6777b538SAndroid Build Coastguard Worker     status.AddExclusionReason(
372*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE);
373*6777b538SAndroid Build Coastguard Worker   }
374*6777b538SAndroid Build Coastguard Worker 
375*6777b538SAndroid Build Coastguard Worker   ApplySameSiteCookieWarningToStatus(SameSite(), effective_same_site,
376*6777b538SAndroid Build Coastguard Worker                                      SecureAttribute(),
377*6777b538SAndroid Build Coastguard Worker                                      options.same_site_cookie_context(),
378*6777b538SAndroid Build Coastguard Worker                                      &status, false /* is_cookie_being_set */);
379*6777b538SAndroid Build Coastguard Worker 
380*6777b538SAndroid Build Coastguard Worker   CookieAccessResult result{effective_same_site, status,
381*6777b538SAndroid Build Coastguard Worker                             params.access_semantics,
382*6777b538SAndroid Build Coastguard Worker                             is_allowed_to_access_secure_cookies};
383*6777b538SAndroid Build Coastguard Worker 
384*6777b538SAndroid Build Coastguard Worker   PostIncludeForRequestURL(result, options, cookie_inclusion_context);
385*6777b538SAndroid Build Coastguard Worker 
386*6777b538SAndroid Build Coastguard Worker   return result;
387*6777b538SAndroid Build Coastguard Worker }
388*6777b538SAndroid Build Coastguard Worker 
IsSetPermittedInContext(const GURL & source_url,const CookieOptions & options,const CookieAccessParams & params,const std::vector<std::string> & cookieable_schemes,const std::optional<CookieAccessResult> & cookie_access_result) const389*6777b538SAndroid Build Coastguard Worker CookieAccessResult CookieBase::IsSetPermittedInContext(
390*6777b538SAndroid Build Coastguard Worker     const GURL& source_url,
391*6777b538SAndroid Build Coastguard Worker     const CookieOptions& options,
392*6777b538SAndroid Build Coastguard Worker     const CookieAccessParams& params,
393*6777b538SAndroid Build Coastguard Worker     const std::vector<std::string>& cookieable_schemes,
394*6777b538SAndroid Build Coastguard Worker     const std::optional<CookieAccessResult>& cookie_access_result) const {
395*6777b538SAndroid Build Coastguard Worker   CookieAccessResult access_result;
396*6777b538SAndroid Build Coastguard Worker   if (cookie_access_result) {
397*6777b538SAndroid Build Coastguard Worker     access_result = *cookie_access_result;
398*6777b538SAndroid Build Coastguard Worker   }
399*6777b538SAndroid Build Coastguard Worker 
400*6777b538SAndroid Build Coastguard Worker   if (!base::Contains(cookieable_schemes, source_url.scheme())) {
401*6777b538SAndroid Build Coastguard Worker     access_result.status.AddExclusionReason(
402*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME);
403*6777b538SAndroid Build Coastguard Worker   }
404*6777b538SAndroid Build Coastguard Worker 
405*6777b538SAndroid Build Coastguard Worker   CookieAccessScheme access_scheme =
406*6777b538SAndroid Build Coastguard Worker       cookie_util::ProvisionalAccessScheme(source_url);
407*6777b538SAndroid Build Coastguard Worker   if (access_scheme == CookieAccessScheme::kNonCryptographic &&
408*6777b538SAndroid Build Coastguard Worker       params.delegate_treats_url_as_trustworthy) {
409*6777b538SAndroid Build Coastguard Worker     access_scheme = CookieAccessScheme::kTrustworthy;
410*6777b538SAndroid Build Coastguard Worker   }
411*6777b538SAndroid Build Coastguard Worker 
412*6777b538SAndroid Build Coastguard Worker   switch (access_scheme) {
413*6777b538SAndroid Build Coastguard Worker     case CookieAccessScheme::kNonCryptographic:
414*6777b538SAndroid Build Coastguard Worker       access_result.is_allowed_to_access_secure_cookies = false;
415*6777b538SAndroid Build Coastguard Worker       if (SecureAttribute()) {
416*6777b538SAndroid Build Coastguard Worker         access_result.status.AddExclusionReason(
417*6777b538SAndroid Build Coastguard Worker             CookieInclusionStatus::EXCLUDE_SECURE_ONLY);
418*6777b538SAndroid Build Coastguard Worker       }
419*6777b538SAndroid Build Coastguard Worker       break;
420*6777b538SAndroid Build Coastguard Worker 
421*6777b538SAndroid Build Coastguard Worker     case CookieAccessScheme::kCryptographic:
422*6777b538SAndroid Build Coastguard Worker       // All cool!
423*6777b538SAndroid Build Coastguard Worker       access_result.is_allowed_to_access_secure_cookies = true;
424*6777b538SAndroid Build Coastguard Worker       break;
425*6777b538SAndroid Build Coastguard Worker 
426*6777b538SAndroid Build Coastguard Worker     case CookieAccessScheme::kTrustworthy:
427*6777b538SAndroid Build Coastguard Worker       access_result.is_allowed_to_access_secure_cookies = true;
428*6777b538SAndroid Build Coastguard Worker       if (SecureAttribute()) {
429*6777b538SAndroid Build Coastguard Worker         // OK, but want people aware of this.
430*6777b538SAndroid Build Coastguard Worker         // Note, we also want to apply this warning to cookies whose source
431*6777b538SAndroid Build Coastguard Worker         // scheme is kSecure but are set by non-cryptographic (but trustworthy)
432*6777b538SAndroid Build Coastguard Worker         // urls. Helpfully, since those cookies only get a kSecure source scheme
433*6777b538SAndroid Build Coastguard Worker         // when they also specify "Secure" this if statement will already apply
434*6777b538SAndroid Build Coastguard Worker         // to them.
435*6777b538SAndroid Build Coastguard Worker         access_result.status.AddWarningReason(
436*6777b538SAndroid Build Coastguard Worker             CookieInclusionStatus::
437*6777b538SAndroid Build Coastguard Worker                 WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC);
438*6777b538SAndroid Build Coastguard Worker       }
439*6777b538SAndroid Build Coastguard Worker       break;
440*6777b538SAndroid Build Coastguard Worker   }
441*6777b538SAndroid Build Coastguard Worker 
442*6777b538SAndroid Build Coastguard Worker   access_result.access_semantics = params.access_semantics;
443*6777b538SAndroid Build Coastguard Worker   if (options.exclude_httponly() && IsHttpOnly()) {
444*6777b538SAndroid Build Coastguard Worker     DVLOG(net::cookie_util::kVlogSetCookies)
445*6777b538SAndroid Build Coastguard Worker         << "HttpOnly cookie not permitted in script context.";
446*6777b538SAndroid Build Coastguard Worker     access_result.status.AddExclusionReason(
447*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::EXCLUDE_HTTP_ONLY);
448*6777b538SAndroid Build Coastguard Worker   }
449*6777b538SAndroid Build Coastguard Worker 
450*6777b538SAndroid Build Coastguard Worker   // Unless legacy access semantics are in effect, SameSite=None cookies without
451*6777b538SAndroid Build Coastguard Worker   // the Secure attribute will be rejected.
452*6777b538SAndroid Build Coastguard Worker   if (params.access_semantics != CookieAccessSemantics::LEGACY &&
453*6777b538SAndroid Build Coastguard Worker       SameSite() == CookieSameSite::NO_RESTRICTION && !SecureAttribute()) {
454*6777b538SAndroid Build Coastguard Worker     DVLOG(net::cookie_util::kVlogSetCookies)
455*6777b538SAndroid Build Coastguard Worker         << "SetCookie() rejecting insecure cookie with SameSite=None.";
456*6777b538SAndroid Build Coastguard Worker     access_result.status.AddExclusionReason(
457*6777b538SAndroid Build Coastguard Worker         CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE);
458*6777b538SAndroid Build Coastguard Worker   }
459*6777b538SAndroid Build Coastguard Worker 
460*6777b538SAndroid Build Coastguard Worker   // For LEGACY cookies we should always return the schemeless context,
461*6777b538SAndroid Build Coastguard Worker   // otherwise let GetContextForCookieInclusion() decide.
462*6777b538SAndroid Build Coastguard Worker   CookieOptions::SameSiteCookieContext::ContextType cookie_inclusion_context =
463*6777b538SAndroid Build Coastguard Worker       params.access_semantics == CookieAccessSemantics::LEGACY
464*6777b538SAndroid Build Coastguard Worker           ? options.same_site_cookie_context().context()
465*6777b538SAndroid Build Coastguard Worker           : options.same_site_cookie_context().GetContextForCookieInclusion();
466*6777b538SAndroid Build Coastguard Worker 
467*6777b538SAndroid Build Coastguard Worker   access_result.effective_same_site =
468*6777b538SAndroid Build Coastguard Worker       GetEffectiveSameSite(params.access_semantics);
469*6777b538SAndroid Build Coastguard Worker   DCHECK(access_result.effective_same_site !=
470*6777b538SAndroid Build Coastguard Worker          CookieEffectiveSameSite::UNDEFINED);
471*6777b538SAndroid Build Coastguard Worker   switch (access_result.effective_same_site) {
472*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::STRICT_MODE:
473*6777b538SAndroid Build Coastguard Worker       // This intentionally checks for `< SAME_SITE_LAX`, as we allow
474*6777b538SAndroid Build Coastguard Worker       // `SameSite=Strict` cookies to be set for top-level navigations that
475*6777b538SAndroid Build Coastguard Worker       // qualify for receipt of `SameSite=Lax` cookies.
476*6777b538SAndroid Build Coastguard Worker       if (cookie_inclusion_context <
477*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX) {
478*6777b538SAndroid Build Coastguard Worker         DVLOG(net::cookie_util::kVlogSetCookies)
479*6777b538SAndroid Build Coastguard Worker             << "Trying to set a `SameSite=Strict` cookie from a "
480*6777b538SAndroid Build Coastguard Worker                "cross-site URL.";
481*6777b538SAndroid Build Coastguard Worker         access_result.status.AddExclusionReason(
482*6777b538SAndroid Build Coastguard Worker             CookieInclusionStatus::EXCLUDE_SAMESITE_STRICT);
483*6777b538SAndroid Build Coastguard Worker       }
484*6777b538SAndroid Build Coastguard Worker       break;
485*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::LAX_MODE:
486*6777b538SAndroid Build Coastguard Worker     case CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
487*6777b538SAndroid Build Coastguard Worker       if (cookie_inclusion_context <
488*6777b538SAndroid Build Coastguard Worker           CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX) {
489*6777b538SAndroid Build Coastguard Worker         if (SameSite() == CookieSameSite::UNSPECIFIED) {
490*6777b538SAndroid Build Coastguard Worker           DVLOG(net::cookie_util::kVlogSetCookies)
491*6777b538SAndroid Build Coastguard Worker               << "Cookies with no known SameSite attribute being treated as "
492*6777b538SAndroid Build Coastguard Worker                  "lax; attempt to set from a cross-site URL denied.";
493*6777b538SAndroid Build Coastguard Worker           access_result.status.AddExclusionReason(
494*6777b538SAndroid Build Coastguard Worker               CookieInclusionStatus::
495*6777b538SAndroid Build Coastguard Worker                   EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX);
496*6777b538SAndroid Build Coastguard Worker         } else {
497*6777b538SAndroid Build Coastguard Worker           DVLOG(net::cookie_util::kVlogSetCookies)
498*6777b538SAndroid Build Coastguard Worker               << "Trying to set a `SameSite=Lax` cookie from a cross-site URL.";
499*6777b538SAndroid Build Coastguard Worker           access_result.status.AddExclusionReason(
500*6777b538SAndroid Build Coastguard Worker               CookieInclusionStatus::EXCLUDE_SAMESITE_LAX);
501*6777b538SAndroid Build Coastguard Worker         }
502*6777b538SAndroid Build Coastguard Worker       }
503*6777b538SAndroid Build Coastguard Worker       break;
504*6777b538SAndroid Build Coastguard Worker     default:
505*6777b538SAndroid Build Coastguard Worker       break;
506*6777b538SAndroid Build Coastguard Worker   }
507*6777b538SAndroid Build Coastguard Worker 
508*6777b538SAndroid Build Coastguard Worker   ApplySameSiteCookieWarningToStatus(
509*6777b538SAndroid Build Coastguard Worker       SameSite(), access_result.effective_same_site, SecureAttribute(),
510*6777b538SAndroid Build Coastguard Worker       options.same_site_cookie_context(), &access_result.status,
511*6777b538SAndroid Build Coastguard Worker       true /* is_cookie_being_set */);
512*6777b538SAndroid Build Coastguard Worker 
513*6777b538SAndroid Build Coastguard Worker   PostIsSetPermittedInContext(access_result, options);
514*6777b538SAndroid Build Coastguard Worker 
515*6777b538SAndroid Build Coastguard Worker   return access_result;
516*6777b538SAndroid Build Coastguard Worker }
517*6777b538SAndroid Build Coastguard Worker 
IsOnPath(const std::string & url_path) const518*6777b538SAndroid Build Coastguard Worker bool CookieBase::IsOnPath(const std::string& url_path) const {
519*6777b538SAndroid Build Coastguard Worker   return cookie_util::IsOnPath(path_, url_path);
520*6777b538SAndroid Build Coastguard Worker }
521*6777b538SAndroid Build Coastguard Worker 
IsDomainMatch(const std::string & host) const522*6777b538SAndroid Build Coastguard Worker bool CookieBase::IsDomainMatch(const std::string& host) const {
523*6777b538SAndroid Build Coastguard Worker   return cookie_util::IsDomainMatch(domain_, host);
524*6777b538SAndroid Build Coastguard Worker }
525*6777b538SAndroid Build Coastguard Worker 
IsSecure() const526*6777b538SAndroid Build Coastguard Worker bool CookieBase::IsSecure() const {
527*6777b538SAndroid Build Coastguard Worker   return SecureAttribute() || (cookie_util::IsSchemeBoundCookiesEnabled() &&
528*6777b538SAndroid Build Coastguard Worker                                source_scheme_ == CookieSourceScheme::kSecure);
529*6777b538SAndroid Build Coastguard Worker }
530*6777b538SAndroid Build Coastguard Worker 
IsFirstPartyPartitioned() const531*6777b538SAndroid Build Coastguard Worker bool CookieBase::IsFirstPartyPartitioned() const {
532*6777b538SAndroid Build Coastguard Worker   return IsPartitioned() && !CookiePartitionKey::HasNonce(partition_key_) &&
533*6777b538SAndroid Build Coastguard Worker          SchemefulSite(GURL(
534*6777b538SAndroid Build Coastguard Worker              base::StrCat({url::kHttpsScheme, url::kStandardSchemeSeparator,
535*6777b538SAndroid Build Coastguard Worker                            DomainWithoutDot()}))) == partition_key_->site();
536*6777b538SAndroid Build Coastguard Worker }
537*6777b538SAndroid Build Coastguard Worker 
IsThirdPartyPartitioned() const538*6777b538SAndroid Build Coastguard Worker bool CookieBase::IsThirdPartyPartitioned() const {
539*6777b538SAndroid Build Coastguard Worker   return IsPartitioned() && !IsFirstPartyPartitioned();
540*6777b538SAndroid Build Coastguard Worker }
541*6777b538SAndroid Build Coastguard Worker 
DomainWithoutDot() const542*6777b538SAndroid Build Coastguard Worker std::string CookieBase::DomainWithoutDot() const {
543*6777b538SAndroid Build Coastguard Worker   return cookie_util::CookieDomainAsHost(domain_);
544*6777b538SAndroid Build Coastguard Worker }
545*6777b538SAndroid Build Coastguard Worker 
UniqueKey() const546*6777b538SAndroid Build Coastguard Worker CookieBase::UniqueCookieKey CookieBase::UniqueKey() const {
547*6777b538SAndroid Build Coastguard Worker   std::optional<CookieSourceScheme> source_scheme =
548*6777b538SAndroid Build Coastguard Worker       cookie_util::IsSchemeBoundCookiesEnabled()
549*6777b538SAndroid Build Coastguard Worker           ? std::make_optional(source_scheme_)
550*6777b538SAndroid Build Coastguard Worker           : std::nullopt;
551*6777b538SAndroid Build Coastguard Worker   std::optional<int> source_port = cookie_util::IsPortBoundCookiesEnabled()
552*6777b538SAndroid Build Coastguard Worker                                        ? std::make_optional(source_port_)
553*6777b538SAndroid Build Coastguard Worker                                        : std::nullopt;
554*6777b538SAndroid Build Coastguard Worker 
555*6777b538SAndroid Build Coastguard Worker   return std::make_tuple(partition_key_, name_, domain_, path_, source_scheme,
556*6777b538SAndroid Build Coastguard Worker                          source_port);
557*6777b538SAndroid Build Coastguard Worker }
558*6777b538SAndroid Build Coastguard Worker 
UniqueDomainKey() const559*6777b538SAndroid Build Coastguard Worker CookieBase::UniqueDomainCookieKey CookieBase::UniqueDomainKey() const {
560*6777b538SAndroid Build Coastguard Worker   std::optional<CookieSourceScheme> source_scheme =
561*6777b538SAndroid Build Coastguard Worker       cookie_util::IsSchemeBoundCookiesEnabled()
562*6777b538SAndroid Build Coastguard Worker           ? std::make_optional(source_scheme_)
563*6777b538SAndroid Build Coastguard Worker           : std::nullopt;
564*6777b538SAndroid Build Coastguard Worker 
565*6777b538SAndroid Build Coastguard Worker   return std::make_tuple(partition_key_, name_, domain_, path_, source_scheme);
566*6777b538SAndroid Build Coastguard Worker }
567*6777b538SAndroid Build Coastguard Worker 
SetSourcePort(int port)568*6777b538SAndroid Build Coastguard Worker void CookieBase::SetSourcePort(int port) {
569*6777b538SAndroid Build Coastguard Worker   source_port_ = ValidateAndAdjustSourcePort(port);
570*6777b538SAndroid Build Coastguard Worker }
571*6777b538SAndroid Build Coastguard Worker 
572*6777b538SAndroid Build Coastguard Worker CookieBase::CookieBase() = default;
573*6777b538SAndroid Build Coastguard Worker 
574*6777b538SAndroid Build Coastguard Worker CookieBase::CookieBase(const CookieBase& other) = default;
575*6777b538SAndroid Build Coastguard Worker 
576*6777b538SAndroid Build Coastguard Worker CookieBase::CookieBase(CookieBase&& other) = default;
577*6777b538SAndroid Build Coastguard Worker 
578*6777b538SAndroid Build Coastguard Worker CookieBase& CookieBase::operator=(const CookieBase& other) = default;
579*6777b538SAndroid Build Coastguard Worker 
580*6777b538SAndroid Build Coastguard Worker CookieBase& CookieBase::operator=(CookieBase&& other) = default;
581*6777b538SAndroid Build Coastguard Worker 
582*6777b538SAndroid Build Coastguard Worker CookieBase::~CookieBase() = default;
583*6777b538SAndroid Build Coastguard Worker 
CookieBase(std::string name,std::string domain,std::string path,base::Time creation,bool secure,bool httponly,CookieSameSite same_site,std::optional<CookiePartitionKey> partition_key,CookieSourceScheme source_scheme,int source_port)584*6777b538SAndroid Build Coastguard Worker CookieBase::CookieBase(std::string name,
585*6777b538SAndroid Build Coastguard Worker                        std::string domain,
586*6777b538SAndroid Build Coastguard Worker                        std::string path,
587*6777b538SAndroid Build Coastguard Worker                        base::Time creation,
588*6777b538SAndroid Build Coastguard Worker                        bool secure,
589*6777b538SAndroid Build Coastguard Worker                        bool httponly,
590*6777b538SAndroid Build Coastguard Worker                        CookieSameSite same_site,
591*6777b538SAndroid Build Coastguard Worker                        std::optional<CookiePartitionKey> partition_key,
592*6777b538SAndroid Build Coastguard Worker                        CookieSourceScheme source_scheme,
593*6777b538SAndroid Build Coastguard Worker                        int source_port)
594*6777b538SAndroid Build Coastguard Worker     : name_(std::move(name)),
595*6777b538SAndroid Build Coastguard Worker       domain_(std::move(domain)),
596*6777b538SAndroid Build Coastguard Worker       path_(std::move(path)),
597*6777b538SAndroid Build Coastguard Worker       creation_date_(creation),
598*6777b538SAndroid Build Coastguard Worker       secure_(secure),
599*6777b538SAndroid Build Coastguard Worker       httponly_(httponly),
600*6777b538SAndroid Build Coastguard Worker       same_site_(same_site),
601*6777b538SAndroid Build Coastguard Worker       partition_key_(std::move(partition_key)),
602*6777b538SAndroid Build Coastguard Worker       source_scheme_(source_scheme),
603*6777b538SAndroid Build Coastguard Worker       source_port_(source_port) {}
604*6777b538SAndroid Build Coastguard Worker 
GetEffectiveSameSite(CookieAccessSemantics access_semantics) const605*6777b538SAndroid Build Coastguard Worker CookieEffectiveSameSite CookieBase::GetEffectiveSameSite(
606*6777b538SAndroid Build Coastguard Worker     CookieAccessSemantics access_semantics) const {
607*6777b538SAndroid Build Coastguard Worker   base::TimeDelta lax_allow_unsafe_threshold_age =
608*6777b538SAndroid Build Coastguard Worker       base::FeatureList::IsEnabled(
609*6777b538SAndroid Build Coastguard Worker           features::kSameSiteDefaultChecksMethodRigorously)
610*6777b538SAndroid Build Coastguard Worker           ? base::TimeDelta::Min()
611*6777b538SAndroid Build Coastguard Worker           : (base::FeatureList::IsEnabled(
612*6777b538SAndroid Build Coastguard Worker                  features::kShortLaxAllowUnsafeThreshold)
613*6777b538SAndroid Build Coastguard Worker                  ? kShortLaxAllowUnsafeMaxAge
614*6777b538SAndroid Build Coastguard Worker                  : kLaxAllowUnsafeMaxAge);
615*6777b538SAndroid Build Coastguard Worker 
616*6777b538SAndroid Build Coastguard Worker   switch (SameSite()) {
617*6777b538SAndroid Build Coastguard Worker     // If a cookie does not have a SameSite attribute, the effective SameSite
618*6777b538SAndroid Build Coastguard Worker     // mode depends on the access semantics and whether the cookie is
619*6777b538SAndroid Build Coastguard Worker     // recently-created.
620*6777b538SAndroid Build Coastguard Worker     case CookieSameSite::UNSPECIFIED:
621*6777b538SAndroid Build Coastguard Worker       return (access_semantics == CookieAccessSemantics::LEGACY)
622*6777b538SAndroid Build Coastguard Worker                  ? CookieEffectiveSameSite::NO_RESTRICTION
623*6777b538SAndroid Build Coastguard Worker                  : (IsRecentlyCreated(lax_allow_unsafe_threshold_age)
624*6777b538SAndroid Build Coastguard Worker                         ? CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE
625*6777b538SAndroid Build Coastguard Worker                         : CookieEffectiveSameSite::LAX_MODE);
626*6777b538SAndroid Build Coastguard Worker     case CookieSameSite::NO_RESTRICTION:
627*6777b538SAndroid Build Coastguard Worker       return CookieEffectiveSameSite::NO_RESTRICTION;
628*6777b538SAndroid Build Coastguard Worker     case CookieSameSite::LAX_MODE:
629*6777b538SAndroid Build Coastguard Worker       return CookieEffectiveSameSite::LAX_MODE;
630*6777b538SAndroid Build Coastguard Worker     case CookieSameSite::STRICT_MODE:
631*6777b538SAndroid Build Coastguard Worker       return CookieEffectiveSameSite::STRICT_MODE;
632*6777b538SAndroid Build Coastguard Worker   }
633*6777b538SAndroid Build Coastguard Worker }
634*6777b538SAndroid Build Coastguard Worker 
IsRecentlyCreated(base::TimeDelta age_threshold) const635*6777b538SAndroid Build Coastguard Worker bool CookieBase::IsRecentlyCreated(base::TimeDelta age_threshold) const {
636*6777b538SAndroid Build Coastguard Worker   return (base::Time::Now() - creation_date_) <= age_threshold;
637*6777b538SAndroid Build Coastguard Worker }
638*6777b538SAndroid Build Coastguard Worker 
639*6777b538SAndroid Build Coastguard Worker // static
ValidateAndAdjustSourcePort(int port)640*6777b538SAndroid Build Coastguard Worker int CookieBase::ValidateAndAdjustSourcePort(int port) {
641*6777b538SAndroid Build Coastguard Worker   if ((port >= 0 && port <= 65535) || port == url::PORT_UNSPECIFIED) {
642*6777b538SAndroid Build Coastguard Worker     // 0 would be really weird as it has a special meaning, but it's still
643*6777b538SAndroid Build Coastguard Worker     // technically a valid tcp/ip port so we're going to accept it here.
644*6777b538SAndroid Build Coastguard Worker     return port;
645*6777b538SAndroid Build Coastguard Worker   }
646*6777b538SAndroid Build Coastguard Worker   return url::PORT_INVALID;
647*6777b538SAndroid Build Coastguard Worker }
648*6777b538SAndroid Build Coastguard Worker 
649*6777b538SAndroid Build Coastguard Worker }  // namespace net
650