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