xref: /aosp_15_r20/external/cronet/net/cookies/cookie_util.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef NET_COOKIES_COOKIE_UTIL_H_
6 #define NET_COOKIES_COOKIE_UTIL_H_
7 
8 #include <optional>
9 #include <string>
10 #include <vector>
11 
12 #include "base/functional/callback_forward.h"
13 #include "base/time/time.h"
14 #include "net/base/net_export.h"
15 #include "net/cookies/canonical_cookie.h"
16 #include "net/cookies/cookie_access_result.h"
17 #include "net/cookies/cookie_constants.h"
18 #include "net/cookies/cookie_options.h"
19 #include "net/cookies/site_for_cookies.h"
20 #include "net/first_party_sets/first_party_set_metadata.h"
21 #include "net/first_party_sets/first_party_sets_cache_filter.h"
22 #include "url/origin.h"
23 
24 class GURL;
25 
26 namespace net {
27 
28 class IsolationInfo;
29 class SchemefulSite;
30 class CookieAccessDelegate;
31 class CookieInclusionStatus;
32 
33 namespace cookie_util {
34 
35 // Constants for use in VLOG
36 const int kVlogPerCookieMonster = 1;
37 const int kVlogSetCookies = 7;
38 const int kVlogGarbageCollection = 5;
39 
40 // This enum must match the numbering for StorageAccessResult in
41 // histograms/enums.xml. Do not reorder or remove items, only add new items
42 // at the end.
43 enum class StorageAccessResult {
44   ACCESS_BLOCKED = 0,
45   ACCESS_ALLOWED = 1,
46   ACCESS_ALLOWED_STORAGE_ACCESS_GRANT = 2,
47   OBSOLETE_ACCESS_ALLOWED_FORCED = 3 /*(DEPRECATED)*/,
48   ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT = 4,
49   ACCESS_ALLOWED_3PCD_TRIAL = 5,
50   ACCESS_ALLOWED_3PCD_METADATA_GRANT = 6,
51   ACCESS_ALLOWED_3PCD_HEURISTICS_GRANT = 7,
52   ACCESS_ALLOWED_CORS_EXCEPTION = 8,
53   ACCESS_ALLOWED_TOP_LEVEL_3PCD_TRIAL = 9,
54   kMaxValue = ACCESS_ALLOWED_TOP_LEVEL_3PCD_TRIAL,
55 };
56 
57 // Helper to fire telemetry indicating if a given request for storage was
58 // allowed or not by the provided |result|.
59 NET_EXPORT void FireStorageAccessHistogram(StorageAccessResult result);
60 
61 // Returns the effective TLD+1 for a given host. This only makes sense for http
62 // and https schemes. For other schemes, the host will be returned unchanged
63 // (minus any leading period).
64 NET_EXPORT std::string GetEffectiveDomain(const std::string& scheme,
65                                           const std::string& host);
66 
67 // Determine the actual cookie domain based on the domain string passed
68 // (if any) and the URL from which the cookie came.
69 // On success returns true, and sets cookie_domain to either a
70 //   -host cookie domain (ex: "google.com")
71 //   -domain cookie domain (ex: ".google.com")
72 // On success, DomainIsHostOnly(url.host()) is DCHECKed. The URL's host must not
73 // begin with a '.' character.
74 NET_EXPORT bool GetCookieDomainWithString(const GURL& url,
75                                           const std::string& domain_string,
76                                           CookieInclusionStatus& status,
77                                           std::string* result);
78 
79 // Returns true if a domain string represents a host-only cookie,
80 // i.e. it doesn't begin with a leading '.' character.
81 NET_EXPORT bool DomainIsHostOnly(const std::string& domain_string);
82 
83 // If |cookie_domain| is nonempty and starts with a "." character, this returns
84 // the substring of |cookie_domain| without the leading dot. (Note only one
85 // leading dot is stripped, if there are multiple.) Otherwise it returns
86 // |cookie_domain|. This is useful for converting from CanonicalCookie's
87 // representation of a cookie domain to the RFC's notion of a cookie's domain.
88 NET_EXPORT std::string CookieDomainAsHost(const std::string& cookie_domain);
89 
90 // Parses the string with the cookie expiration time (very forgivingly).
91 // Returns the "null" time on failure.
92 //
93 // If the expiration date is below or above the platform-specific range
94 // supported by Time::FromUTCExplodeded(), then this will return Time(1) or
95 // Time::Max(), respectively.
96 NET_EXPORT base::Time ParseCookieExpirationTime(const std::string& time_string);
97 
98 // Get a cookie's URL from it's domain, path, and source scheme.
99 // The first field can be the combined domain-and-host-only-flag (e.g. the
100 // string returned by CanonicalCookie::Domain()) as opposed to the domain
101 // attribute per RFC6265bis. The GURL is constructed after stripping off any
102 // leading dot.
103 // Note: the GURL returned by this method is not guaranteed to be valid.
104 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain,
105                                          const std::string& path,
106                                          const std::string& source_scheme);
107 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain,
108                                          const std::string& path,
109                                          bool is_https);
110 NET_EXPORT GURL CookieDomainAndPathToURL(const std::string& domain,
111                                          const std::string& path,
112                                          CookieSourceScheme source_scheme);
113 
114 // Convenience for converting a cookie origin (domain and https pair) to a URL.
115 NET_EXPORT GURL CookieOriginToURL(const std::string& domain, bool is_https);
116 
117 // Returns a URL that could have been the cookie's source.
118 // Not guaranteed to actually be the URL that set the cookie. Not guaranteed to
119 // be a valid GURL. Intended as a shim for SetCanonicalCookieAsync calls, where
120 // a source URL is required but only a source scheme may be available.
121 NET_EXPORT GURL SimulatedCookieSource(const CanonicalCookie& cookie,
122                                       const std::string& source_scheme);
123 
124 // Provisional evaluation of acceptability of setting secure cookies on
125 // `source_url` based only on the `source_url`'s scheme and whether it
126 // is a localhost URL.  If this returns kNonCryptographic, it may be upgraded to
127 // kTrustworthy by a CookieAccessDelegate when the cookie operation is being
128 // performed, as the delegate may have access to user settings like manually
129 // configured test domains which declare additional things trustworthy.
130 NET_EXPORT CookieAccessScheme ProvisionalAccessScheme(const GURL& source_url);
131 
132 // |domain| is the output of cookie.Domain() for some cookie. This returns true
133 // if a |domain| indicates that the cookie can be accessed by |host|.
134 // See comment on CanonicalCookie::IsDomainMatch().
135 NET_EXPORT bool IsDomainMatch(const std::string& domain,
136                               const std::string& host);
137 
138 // Returns true if the given |url_path| path-matches |cookie_path|
139 // as described in section 5.1.4 in RFC 6265. This returns true if |cookie_path|
140 // and |url_path| are identical, or if |url_path| is a subdirectory of
141 // |cookie_path|.
142 NET_EXPORT bool IsOnPath(const std::string& cookie_path,
143                          const std::string& url_path);
144 
145 // A ParsedRequestCookie consists of the key and value of the cookie.
146 using ParsedRequestCookie = std::pair<std::string, std::string>;
147 using ParsedRequestCookies = std::vector<ParsedRequestCookie>;
148 
149 // Assumes that |header_value| is the cookie header value of a HTTP Request
150 // following the cookie-string schema of RFC 6265, section 4.2.1, and returns
151 // cookie name/value pairs. If cookie values are presented in double quotes,
152 // these will appear in |parsed_cookies| as well. The cookie header can be
153 // written by non-Chromium consumers (such as extensions), so the header may not
154 // be well-formed.
155 NET_EXPORT void ParseRequestCookieLine(const std::string& header_value,
156                                        ParsedRequestCookies* parsed_cookies);
157 
158 // Writes all cookies of |parsed_cookies| into a HTTP Request header value
159 // that belongs to the "Cookie" header. The entries of |parsed_cookies| must
160 // already be appropriately escaped.
161 NET_EXPORT std::string SerializeRequestCookieLine(
162     const ParsedRequestCookies& parsed_cookies);
163 
164 // Determines which of the cookies for the request URL can be accessed, with
165 // respect to the SameSite attribute. This applies to looking up existing
166 // cookies for HTTP requests. For looking up cookies for non-HTTP APIs (i.e.,
167 // JavaScript), see ComputeSameSiteContextForScriptGet. For setting new cookies,
168 // see ComputeSameSiteContextForResponse and ComputeSameSiteContextForScriptSet.
169 //
170 // `url_chain` is a non-empty vector of URLs, the last of which is the current
171 // request URL. It represents the redirect chain of the current request. The
172 // redirect chain is used to calculate whether there has been a cross-site
173 // redirect. In order for a context to be deemed strictly same-site, there must
174 // not have been any cross-site redirects.
175 //
176 // `site_for_cookies` is the currently navigated to site that should be
177 // considered "first-party" for cookies.
178 //
179 // `initiator` is the origin ultimately responsible for getting the request
180 // issued. It may be different from `site_for_cookies`.
181 //
182 // std::nullopt for `initiator` denotes that the navigation was initiated by
183 // the user directly interacting with the browser UI, e.g. entering a URL
184 // or selecting a bookmark.
185 //
186 // `is_main_frame_navigation` is whether the request is for a navigation that
187 // targets the main frame or top-level browsing context. These requests may
188 // sometimes send SameSite=Lax cookies but not SameSite=Strict cookies.
189 //
190 // If `force_ignore_site_for_cookies` is specified, all SameSite cookies will be
191 // attached, i.e. this will return SAME_SITE_STRICT. This flag is set to true
192 // when the `site_for_cookies` is a chrome:// URL embedding a secure origin,
193 // among other scenarios.
194 // This is *not* set when the *initiator* is chrome-extension://,
195 // which is intentional, since it would be bad to let an extension arbitrarily
196 // redirect anywhere and bypass SameSite=Strict rules.
197 //
198 // See also documentation for corresponding methods on net::URLRequest.
199 //
200 // `http_method` is used to enforce the requirement that, in a context that's
201 // lax same-site but not strict same-site, SameSite=lax cookies be only sent
202 // when the method is "safe" in the RFC7231 section 4.2.1 sense.
203 NET_EXPORT CookieOptions::SameSiteCookieContext
204 ComputeSameSiteContextForRequest(const std::string& http_method,
205                                  const std::vector<GURL>& url_chain,
206                                  const SiteForCookies& site_for_cookies,
207                                  const std::optional<url::Origin>& initiator,
208                                  bool is_main_frame_navigation,
209                                  bool force_ignore_site_for_cookies);
210 
211 // As above, but applying for scripts. `initiator` here should be the initiator
212 // used when fetching the document.
213 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_STRICT.
214 NET_EXPORT CookieOptions::SameSiteCookieContext
215 ComputeSameSiteContextForScriptGet(const GURL& url,
216                                    const SiteForCookies& site_for_cookies,
217                                    const std::optional<url::Origin>& initiator,
218                                    bool force_ignore_site_for_cookies);
219 
220 // Determines which of the cookies for the request URL can be set from a network
221 // response, with respect to the SameSite attribute. This will only return
222 // CROSS_SITE or SAME_SITE_LAX (cookie sets of SameSite=strict cookies are
223 // permitted in same contexts that sets of SameSite=lax cookies are).
224 // `url_chain` is a non-empty vector of URLs, the last of which is the current
225 // request URL. It represents the redirect chain of the current request. The
226 // redirect chain is used to calculate whether there has been a cross-site
227 // redirect.
228 // `is_main_frame_navigation` is whether the request was for a navigation that
229 // targets the main frame or top-level browsing context. Both SameSite=Lax and
230 // SameSite=Strict cookies may be set by any main frame navigation.
231 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_LAX.
232 NET_EXPORT CookieOptions::SameSiteCookieContext
233 ComputeSameSiteContextForResponse(const std::vector<GURL>& url_chain,
234                                   const SiteForCookies& site_for_cookies,
235                                   const std::optional<url::Origin>& initiator,
236                                   bool is_main_frame_navigation,
237                                   bool force_ignore_site_for_cookies);
238 
239 // Determines which of the cookies for `url` can be set from a script context,
240 // with respect to the SameSite attribute. This will only return CROSS_SITE or
241 // SAME_SITE_LAX (cookie sets of SameSite=strict cookies are permitted in same
242 // contexts that sets of SameSite=lax cookies are).
243 // If `force_ignore_site_for_cookies` is true, this returns SAME_SITE_LAX.
244 NET_EXPORT CookieOptions::SameSiteCookieContext
245 ComputeSameSiteContextForScriptSet(const GURL& url,
246                                    const SiteForCookies& site_for_cookies,
247                                    bool force_ignore_site_for_cookies);
248 
249 // Determines which of the cookies for |url| can be accessed when fetching a
250 // subresources. This is either CROSS_SITE or SAME_SITE_STRICT,
251 // since the initiator for a subresource is the frame loading it.
252 NET_EXPORT CookieOptions::SameSiteCookieContext
253 // If |force_ignore_site_for_cookies| is true, this returns SAME_SITE_STRICT.
254 ComputeSameSiteContextForSubresource(const GURL& url,
255                                      const SiteForCookies& site_for_cookies,
256                                      bool force_ignore_site_for_cookies);
257 
258 NET_EXPORT bool IsPortBoundCookiesEnabled();
259 
260 NET_EXPORT bool IsSchemeBoundCookiesEnabled();
261 
262 // Returns true if either portion of OBC is enabled.
263 NET_EXPORT bool IsOriginBoundCookiesPartiallyEnabled();
264 
265 NET_EXPORT bool IsTimeLimitedInsecureCookiesEnabled();
266 
267 // Returns whether the respective feature is enabled.
268 NET_EXPORT bool IsSchemefulSameSiteEnabled();
269 
270 // Computes the First-Party Sets metadata and cache match information.
271 // `isolation_info` must be fully populated.
272 //
273 // The result may be returned synchronously, or `callback` may be invoked
274 // asynchronously with the result. The callback will be invoked iff the return
275 // value is nullopt; i.e. a result will be provided via return value or
276 // callback, but not both, and not neither.
277 [[nodiscard]] NET_EXPORT std::optional<
278     std::pair<FirstPartySetMetadata, FirstPartySetsCacheFilter::MatchInfo>>
279 ComputeFirstPartySetMetadataMaybeAsync(
280     const SchemefulSite& request_site,
281     const IsolationInfo& isolation_info,
282     const CookieAccessDelegate* cookie_access_delegate,
283     base::OnceCallback<void(FirstPartySetMetadata,
284                             FirstPartySetsCacheFilter::MatchInfo)> callback);
285 
286 // Converts a string representing the http request method to its enum
287 // representation.
288 NET_EXPORT CookieOptions::SameSiteCookieContext::ContextMetadata::HttpMethod
289 HttpMethodStringToEnum(const std::string& in);
290 
291 // Takes a CookieAccessResult and returns a bool, returning true if the
292 // CookieInclusionStatus in CookieAccessResult was set to "include", else
293 // returning false.
294 //
295 // Can be used with SetCanonicalCookie when you don't need to know why a cookie
296 // was blocked, only whether it was blocked.
297 NET_EXPORT bool IsCookieAccessResultInclude(
298     CookieAccessResult cookie_access_result);
299 
300 // Turn a CookieAccessResultList into a CookieList by stripping out access
301 // results (for callers who only care about cookies).
302 NET_EXPORT CookieList
303 StripAccessResults(const CookieAccessResultList& cookie_access_result_list);
304 
305 // Records port related metrics from Omnibox navigations.
306 NET_EXPORT void RecordCookiePortOmniboxHistograms(const GURL& url);
307 
308 // Checks invariants that should be upheld w.r.t. the included and excluded
309 // cookies. Namely: the included cookies should be elements of
310 // `included_cookies`; excluded cookies should be elements of
311 // `excluded_cookies`; and included cookies should be in the correct sorted
312 // order.
313 NET_EXPORT void DCheckIncludedAndExcludedCookieLists(
314     const CookieAccessResultList& included_cookies,
315     const CookieAccessResultList& excluded_cookies);
316 
317 // Returns the default third-party cookie blocking setting, which is false
318 // unless you enable ForceThirdPartyCookieBlocking with the command line switch
319 // --test-third-party-cookie-phaseout.
320 NET_EXPORT bool IsForceThirdPartyCookieBlockingEnabled();
321 
322 }  // namespace cookie_util
323 
324 }  // namespace net
325 
326 #endif  // NET_COOKIES_COOKIE_UTIL_H_
327