630 lines
28 KiB
C++
630 lines
28 KiB
C++
// Copyright 2012 The Chromium Authors
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef NET_COOKIES_CANONICAL_COOKIE_H_
|
|
#define NET_COOKIES_CANONICAL_COOKIE_H_
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
#include "base/feature_list.h"
|
|
#include "base/gtest_prod_util.h"
|
|
#include "base/strings/string_piece.h"
|
|
#include "base/time/time.h"
|
|
#include "base/types/pass_key.h"
|
|
#include "net/base/features.h"
|
|
#include "net/base/net_export.h"
|
|
#include "net/cookies/cookie_access_result.h"
|
|
#include "net/cookies/cookie_constants.h"
|
|
#include "net/cookies/cookie_inclusion_status.h"
|
|
#include "net/cookies/cookie_options.h"
|
|
#include "net/cookies/cookie_partition_key.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
#include "url/third_party/mozilla/url_parse.h"
|
|
|
|
class GURL;
|
|
|
|
namespace net {
|
|
|
|
class ParsedCookie;
|
|
class CanonicalCookie;
|
|
|
|
struct CookieWithAccessResult;
|
|
struct CookieAndLineWithAccessResult;
|
|
|
|
using CookieList = std::vector<CanonicalCookie>;
|
|
using CookieAndLineAccessResultList =
|
|
std::vector<CookieAndLineWithAccessResult>;
|
|
using CookieAccessResultList = std::vector<CookieWithAccessResult>;
|
|
|
|
struct NET_EXPORT CookieAccessParams {
|
|
CookieAccessParams() = delete;
|
|
CookieAccessParams(CookieAccessSemantics access_semantics,
|
|
bool delegate_treats_url_as_trustworthy,
|
|
CookieSamePartyStatus same_party_status);
|
|
|
|
// |access_semantics| is the access mode of the cookie access check.
|
|
CookieAccessSemantics access_semantics = CookieAccessSemantics::UNKNOWN;
|
|
// |delegate_treats_url_as_trustworthy| should be true iff the
|
|
// CookieAccessDelegate has authorized access to secure cookies from URLs
|
|
// which might not otherwise be able to do so.
|
|
bool delegate_treats_url_as_trustworthy = false;
|
|
// |same_party_status| indicates whether, and how, SameParty restrictions
|
|
// should be enforced.
|
|
CookieSamePartyStatus same_party_status =
|
|
CookieSamePartyStatus::kNoSamePartyEnforcement;
|
|
};
|
|
|
|
class NET_EXPORT CanonicalCookie {
|
|
public:
|
|
using UniqueCookieKey = std::tuple<absl::optional<CookiePartitionKey>,
|
|
std::string,
|
|
std::string,
|
|
std::string>;
|
|
|
|
CanonicalCookie();
|
|
CanonicalCookie(const CanonicalCookie& other);
|
|
CanonicalCookie(CanonicalCookie&& other);
|
|
CanonicalCookie& operator=(const CanonicalCookie& other);
|
|
CanonicalCookie& operator=(CanonicalCookie&& other);
|
|
~CanonicalCookie();
|
|
|
|
// This constructor does not validate or canonicalize their inputs;
|
|
// the resulting CanonicalCookies should not be relied on to be canonical
|
|
// unless the caller has done appropriate validation and canonicalization
|
|
// themselves.
|
|
// NOTE: Prefer using CreateSanitizedCookie() over directly using this
|
|
// constructor.
|
|
CanonicalCookie(base::PassKey<CanonicalCookie>,
|
|
std::string name,
|
|
std::string value,
|
|
std::string domain,
|
|
std::string path,
|
|
base::Time creation,
|
|
base::Time expiration,
|
|
base::Time last_access,
|
|
base::Time last_update,
|
|
bool secure,
|
|
bool httponly,
|
|
CookieSameSite same_site,
|
|
CookiePriority priority,
|
|
bool same_party,
|
|
absl::optional<CookiePartitionKey> partition_key,
|
|
CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset,
|
|
int source_port = url::PORT_UNSPECIFIED);
|
|
|
|
// Creates a new |CanonicalCookie| from the |cookie_line| and the
|
|
// |creation_time|. Canonicalizes inputs. May return nullptr if
|
|
// an attribute value is invalid. |url| must be valid. |creation_time| may
|
|
// not be null. Sets optional |status| to the relevant CookieInclusionStatus
|
|
// if provided. |server_time| indicates what the server sending us the Cookie
|
|
// thought the current time was when the cookie was produced. This is used to
|
|
// adjust for clock skew between server and host.
|
|
//
|
|
// SameSite and HttpOnly related parameters are not checked here,
|
|
// so creation of CanonicalCookies with e.g. SameSite=Strict from a cross-site
|
|
// context is allowed. Create() also does not check whether |url| has a secure
|
|
// scheme if attempting to create a Secure cookie. The Secure, SameSite, and
|
|
// HttpOnly related parameters should be checked when setting the cookie in
|
|
// the CookieStore.
|
|
//
|
|
// The partition_key argument only needs to be present if the cookie line
|
|
// contains the Partitioned attribute. If the cookie line will never contain
|
|
// that attribute, you should use absl::nullopt to indicate you intend to
|
|
// always create an unpartitioned cookie. If partition_key has a value but the
|
|
// cookie line does not contain the Partitioned attribute, the resulting
|
|
// cookie will be unpartitioned. If the partition_key is null, then the cookie
|
|
// will be unpartitioned even when the cookie line has the Partitioned
|
|
// attribute.
|
|
//
|
|
// If a cookie is returned, |cookie->IsCanonical()| will be true.
|
|
static std::unique_ptr<CanonicalCookie> Create(
|
|
const GURL& url,
|
|
const std::string& cookie_line,
|
|
const base::Time& creation_time,
|
|
absl::optional<base::Time> server_time,
|
|
absl::optional<CookiePartitionKey> cookie_partition_key,
|
|
CookieInclusionStatus* status = nullptr);
|
|
|
|
// Create a canonical cookie based on sanitizing the passed inputs in the
|
|
// context of the passed URL. Returns a null unique pointer if the inputs
|
|
// cannot be sanitized. If `status` is provided it will have any relevant
|
|
// CookieInclusionStatus rejection reasons set. If a cookie is created,
|
|
// `cookie->IsCanonical()` will be true.
|
|
static std::unique_ptr<CanonicalCookie> CreateSanitizedCookie(
|
|
const GURL& url,
|
|
const std::string& name,
|
|
const std::string& value,
|
|
const std::string& domain,
|
|
const std::string& path,
|
|
base::Time creation_time,
|
|
base::Time expiration_time,
|
|
base::Time last_access_time,
|
|
bool secure,
|
|
bool http_only,
|
|
CookieSameSite same_site,
|
|
CookiePriority priority,
|
|
bool same_party,
|
|
absl::optional<CookiePartitionKey> partition_key,
|
|
CookieInclusionStatus* status = nullptr);
|
|
|
|
// FromStorage is a factory method which is meant for creating a new
|
|
// CanonicalCookie using properties of a previously existing cookie
|
|
// that was already ingested into the cookie store.
|
|
// This should NOT be used to create a new CanonicalCookie that was not
|
|
// already in the store.
|
|
// Returns nullptr if the resulting cookie is not canonical,
|
|
// i.e. cc->IsCanonical() returns false.
|
|
static std::unique_ptr<CanonicalCookie> FromStorage(
|
|
std::string name,
|
|
std::string value,
|
|
std::string domain,
|
|
std::string path,
|
|
base::Time creation,
|
|
base::Time expiration,
|
|
base::Time last_access,
|
|
base::Time last_update,
|
|
bool secure,
|
|
bool httponly,
|
|
CookieSameSite same_site,
|
|
CookiePriority priority,
|
|
bool same_party,
|
|
absl::optional<CookiePartitionKey> partition_key,
|
|
CookieSourceScheme source_scheme,
|
|
int source_port);
|
|
|
|
// Create a CanonicalCookie that is not guaranteed to actually be Canonical
|
|
// for tests. This factory should NOT be used in production.
|
|
static std::unique_ptr<CanonicalCookie> CreateUnsafeCookieForTesting(
|
|
const std::string& name,
|
|
const std::string& value,
|
|
const std::string& domain,
|
|
const std::string& path,
|
|
const base::Time& creation,
|
|
const base::Time& expiration,
|
|
const base::Time& last_access,
|
|
const base::Time& last_update,
|
|
bool secure,
|
|
bool httponly,
|
|
CookieSameSite same_site,
|
|
CookiePriority priority,
|
|
bool same_party,
|
|
absl::optional<CookiePartitionKey> partition_key = absl::nullopt,
|
|
CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset,
|
|
int source_port = url::PORT_UNSPECIFIED);
|
|
|
|
bool operator<(const CanonicalCookie& other) const {
|
|
// Use the cookie properties that uniquely identify a cookie to determine
|
|
// ordering.
|
|
return UniqueKey() < other.UniqueKey();
|
|
}
|
|
|
|
const std::string& Name() const { return name_; }
|
|
const std::string& Value() const { return value_; }
|
|
// We represent the cookie's host-only-flag as the absence of a leading dot in
|
|
// Domain(). See IsDomainCookie() and IsHostCookie() below.
|
|
// If you want the "cookie's domain" as described in RFC 6265bis, use
|
|
// DomainWithoutDot().
|
|
const std::string& Domain() const { return domain_; }
|
|
const std::string& Path() const { return path_; }
|
|
const base::Time& CreationDate() const { return creation_date_; }
|
|
const base::Time& ExpiryDate() const { return expiry_date_; }
|
|
const base::Time& LastAccessDate() const { return last_access_date_; }
|
|
const base::Time& LastUpdateDate() const { return last_update_date_; }
|
|
bool IsPersistent() const { return !expiry_date_.is_null(); }
|
|
bool IsSecure() const { return secure_; }
|
|
bool IsHttpOnly() const { return httponly_; }
|
|
CookieSameSite SameSite() const { return same_site_; }
|
|
CookiePriority Priority() const { return priority_; }
|
|
bool IsSameParty() const { return same_party_; }
|
|
bool IsPartitioned() const { return partition_key_.has_value(); }
|
|
const absl::optional<CookiePartitionKey>& PartitionKey() const {
|
|
return partition_key_;
|
|
}
|
|
|
|
// Returns an enum indicating the scheme of the origin that
|
|
// set this cookie. This is not part of the cookie spec but is being used to
|
|
// collect metrics for a potential change to the cookie spec
|
|
// (https://tools.ietf.org/html/draft-west-cookie-incrementalism-01#section-3.4)
|
|
CookieSourceScheme SourceScheme() const { return source_scheme_; }
|
|
// Returns the port of the origin that originally set this cookie (the
|
|
// source port). This is not part of the cookie spec but is being used to
|
|
// collect metrics for a potential change to the cookie spec.
|
|
int SourcePort() const { return source_port_; }
|
|
bool IsDomainCookie() const {
|
|
return !domain_.empty() && domain_[0] == '.'; }
|
|
bool IsHostCookie() const { return !IsDomainCookie(); }
|
|
|
|
// Returns the cookie's domain, with the leading dot removed, if present.
|
|
// This corresponds to the "cookie's domain" as described in RFC 6265bis.
|
|
std::string DomainWithoutDot() const;
|
|
|
|
bool IsExpired(const base::Time& current) const {
|
|
return !expiry_date_.is_null() && current >= expiry_date_;
|
|
}
|
|
|
|
// Are the cookies considered equivalent in the eyes of RFC 2965.
|
|
// The RFC says that name must match (case-sensitive), domain must
|
|
// match (case insensitive), and path must match (case sensitive).
|
|
// For the case insensitive domain compare, we rely on the domain
|
|
// having been canonicalized (in
|
|
// GetCookieDomainWithString->CanonicalizeHost).
|
|
// If partitioned cookies are enabled, then we check the cookies have the same
|
|
// partition key in addition to the checks in RFC 2965.
|
|
bool IsEquivalent(const CanonicalCookie& ecc) const {
|
|
// It seems like it would make sense to take secure, httponly, and samesite
|
|
// into account, but the RFC doesn't specify this.
|
|
// NOTE: Keep this logic in-sync with TrimDuplicateCookiesForKey().
|
|
return UniqueKey() == ecc.UniqueKey();
|
|
}
|
|
|
|
// Returns a key such that two cookies with the same UniqueKey() are
|
|
// guaranteed to be equivalent in the sense of IsEquivalent().
|
|
// The `partition_key_` field will always be nullopt when partitioned cookies
|
|
// are not enabled.
|
|
UniqueCookieKey UniqueKey() const {
|
|
return std::make_tuple(partition_key_, name_, domain_, path_);
|
|
}
|
|
|
|
// Checks a looser set of equivalency rules than 'IsEquivalent()' in order
|
|
// to support the stricter 'Secure' behaviors specified in Step 12 of
|
|
// https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#section-5.4
|
|
// which originated from the proposal in
|
|
// https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone#section-3
|
|
//
|
|
// Returns 'true' if this cookie's name matches |secure_cookie|, and this
|
|
// cookie is a domain-match for |secure_cookie| (or vice versa), and
|
|
// |secure_cookie|'s path is "on" this cookie's path (as per 'IsOnPath()').
|
|
// If partitioned cookies are enabled, it also checks that the cookie has
|
|
// the same partition key as |secure_cookie|.
|
|
//
|
|
// Note that while the domain-match cuts both ways (e.g. 'example.com'
|
|
// matches 'www.example.com' in either direction), the path-match is
|
|
// unidirectional (e.g. '/login/en' matches '/login' and '/', but
|
|
// '/login' and '/' do not match '/login/en').
|
|
//
|
|
// Conceptually:
|
|
// If new_cookie.IsEquivalentForSecureCookieMatching(secure_cookie) is true,
|
|
// this means that new_cookie would "shadow" secure_cookie: they would would
|
|
// be indistinguishable when serialized into a Cookie header. This is
|
|
// important because, if an attacker is attempting to set new_cookie, it
|
|
// should not be allowed to mislead the server into using new_cookie's value
|
|
// instead of secure_cookie's.
|
|
//
|
|
// The reason for the asymmetric path comparison ("cookie1=bad; path=/a/b"
|
|
// from an insecure source is not allowed if "cookie1=good; secure; path=/a"
|
|
// exists, but "cookie2=bad; path=/a" from an insecure source is allowed if
|
|
// "cookie2=good; secure; path=/a/b" exists) is because cookies in the Cookie
|
|
// header are serialized with longer path first. (See CookieSorter in
|
|
// cookie_monster.cc.) That is, they would be serialized as "Cookie:
|
|
// cookie1=bad; cookie1=good" in one case, and "Cookie: cookie2=good;
|
|
// cookie2=bad" in the other case. The first scenario is not allowed because
|
|
// the attacker injects the bad value, whereas the second scenario is ok
|
|
// because the good value is still listed first.
|
|
bool IsEquivalentForSecureCookieMatching(
|
|
const CanonicalCookie& secure_cookie) const;
|
|
|
|
// Returns true if the |other| cookie's data members (instance variables)
|
|
// match, for comparing cookies in colletions.
|
|
bool HasEquivalentDataMembers(const CanonicalCookie& other) const {
|
|
return creation_date_ == other.creation_date_ &&
|
|
last_access_date_ == other.last_access_date_ &&
|
|
expiry_date_ == other.expiry_date_ && secure_ == other.secure_ &&
|
|
httponly_ == other.httponly_ && same_site_ == other.same_site_ &&
|
|
priority_ == other.priority_ && same_party_ == other.same_party_ &&
|
|
partition_key_ == other.partition_key_ && name_ == other.name_ &&
|
|
value_ == other.value_ && domain_ == other.domain_ &&
|
|
path_ == other.path_ && last_update_date_ == other.last_update_date_;
|
|
}
|
|
|
|
void SetSourceScheme(CookieSourceScheme source_scheme) {
|
|
source_scheme_ = source_scheme;
|
|
}
|
|
|
|
// Set the source port value. Performs a range check and sets the port to
|
|
// url::PORT_INVALID if value isn't in [0,65535] or url::PORT_UNSPECIFIED.
|
|
void SetSourcePort(int port);
|
|
|
|
void SetLastAccessDate(const base::Time& date) {
|
|
last_access_date_ = date;
|
|
}
|
|
void SetCreationDate(const base::Time& date) { creation_date_ = date; }
|
|
|
|
// Returns true if the given |url_path| path-matches this cookie's cookie-path
|
|
// as described in section 5.1.4 in RFC 6265. This returns true if |path_| and
|
|
// |url_path| are identical, or if |url_path| is a subdirectory of |path_|.
|
|
bool IsOnPath(const std::string& url_path) const;
|
|
|
|
// This returns true if this cookie's |domain_| indicates that it can be
|
|
// accessed by |host|.
|
|
//
|
|
// In the case where |domain_| has no leading dot, this is a host cookie and
|
|
// will only domain match if |host| is identical to |domain_|.
|
|
//
|
|
// In the case where |domain_| has a leading dot, this is a domain cookie. It
|
|
// will match |host| if |domain_| is a suffix of |host|, or if |domain_| is
|
|
// exactly equal to |host| plus a leading dot.
|
|
//
|
|
// Note that this isn't quite the same as the "domain-match" algorithm in RFC
|
|
// 6265bis, since our implementation uses the presence of a leading dot in the
|
|
// |domain_| string in place of the spec's host-only-flag. That is, if
|
|
// |domain_| has no leading dot, then we only consider it matching if |host|
|
|
// is identical (which reflects the intended behavior when the cookie has a
|
|
// host-only-flag), whereas the RFC also treats them as domain-matching if
|
|
// |domain_| is a subdomain of |host|.
|
|
bool IsDomainMatch(const std::string& host) const;
|
|
|
|
// Returns if the cookie should be included (and if not, why) for the given
|
|
// request |url| using the CookieInclusionStatus enum. HTTP only cookies can
|
|
// be filter by using appropriate cookie |options|.
|
|
//
|
|
// PLEASE NOTE that this method does not check whether a cookie is expired or
|
|
// not!
|
|
CookieAccessResult IncludeForRequestURL(
|
|
const GURL& url,
|
|
const CookieOptions& options,
|
|
const CookieAccessParams& params) const;
|
|
|
|
// Returns if the cookie with given attributes can be set in context described
|
|
// by |options| and |params|, and if no, describes why.
|
|
//
|
|
// |cookie_access_result| is an optional input status, to allow for status
|
|
// chaining from callers. It helps callers provide the status of a
|
|
// canonical cookie that may have warnings associated with it.
|
|
CookieAccessResult IsSetPermittedInContext(
|
|
const GURL& source_url,
|
|
const CookieOptions& options,
|
|
const CookieAccessParams& params,
|
|
const std::vector<std::string>& cookieable_schemes,
|
|
const absl::optional<CookieAccessResult>& cookie_access_result =
|
|
absl::nullopt) const;
|
|
|
|
std::string DebugString() const;
|
|
|
|
// Returns the canonical path based on the specified url and path attribute
|
|
// value. Note that this method does not enforce character set or size
|
|
// checks on `path_string`.
|
|
static std::string CanonPathWithString(const GURL& url,
|
|
const std::string& path_string);
|
|
|
|
// Returns a "null" time if expiration was unspecified or invalid.
|
|
static base::Time ParseExpiration(const ParsedCookie& pc,
|
|
const base::Time& current,
|
|
const base::Time& server_time);
|
|
|
|
// Per rfc6265bis the maximum expiry date is no further than 400 days in the
|
|
// future. Clamping only occurs when kClampCookieExpiryTo400Days is enabled.
|
|
static base::Time ValidateAndAdjustExpiryDate(
|
|
const base::Time& expiry_date,
|
|
const base::Time& creation_date);
|
|
|
|
// Cookie ordering methods.
|
|
|
|
// Returns true if the cookie is less than |other|, considering only name,
|
|
// domain and path. In particular, two equivalent cookies (see IsEquivalent())
|
|
// are identical for PartialCompare().
|
|
bool PartialCompare(const CanonicalCookie& other) const;
|
|
|
|
// Return whether this object is a valid CanonicalCookie(). Invalid
|
|
// cookies may be constructed by the detailed constructor.
|
|
// A cookie is considered canonical if-and-only-if:
|
|
// * It can be created by CanonicalCookie::Create, or
|
|
// * It is identical to a cookie created by CanonicalCookie::Create except
|
|
// that the creation time is null, or
|
|
// * It can be derived from a cookie created by CanonicalCookie::Create by
|
|
// entry into and retrieval from a cookie store (specifically, this means
|
|
// by the setting of an creation time in place of a null creation time, and
|
|
// the setting of a last access time).
|
|
// An additional requirement on a CanonicalCookie is that if the last
|
|
// access time is non-null, the creation time must also be non-null and
|
|
// greater than the last access time.
|
|
bool IsCanonical() const;
|
|
|
|
// Return whether this object is a valid CanonicalCookie() when retrieving the
|
|
// cookie from the persistent store. Cookie that exist in the persistent store
|
|
// may have been created before more recent changes to the definition of
|
|
// "canonical". To ease the transition to the new definitions, and to prevent
|
|
// users from having their cookies deleted, this function supports the older
|
|
// definition of canonical. This function is intended to be temporary because
|
|
// as the number of older cookies (which are non-compliant with the newer
|
|
// definition of canonical) decay toward zero it can eventually be replaced
|
|
// by `IsCanonical()` to enforce the newer definition of canonical.
|
|
//
|
|
// A cookie is considered canonical by this function if-and-only-if:
|
|
// * It is considered canonical by IsCanonical()
|
|
// * TODO(crbug.com/1244172): Add exceptions once IsCanonical() starts
|
|
// enforcing them.
|
|
bool IsCanonicalForFromStorage() const;
|
|
|
|
// Returns whether the effective SameSite mode is SameSite=None (i.e. no
|
|
// SameSite restrictions).
|
|
bool IsEffectivelySameSiteNone(CookieAccessSemantics access_semantics =
|
|
CookieAccessSemantics::UNKNOWN) const;
|
|
|
|
CookieEffectiveSameSite GetEffectiveSameSiteForTesting(
|
|
CookieAccessSemantics access_semantics =
|
|
CookieAccessSemantics::UNKNOWN) const;
|
|
|
|
// Returns the cookie line (e.g. "cookie1=value1; cookie2=value2") represented
|
|
// by |cookies|. The string is built in the same order as the given list.
|
|
static std::string BuildCookieLine(const CookieList& cookies);
|
|
|
|
// Same as above but takes a CookieAccessResultList
|
|
// (ignores the access result).
|
|
static std::string BuildCookieLine(const CookieAccessResultList& cookies);
|
|
|
|
// Takes a single CanonicalCookie and returns a cookie line containing the
|
|
// attributes of |cookie| formatted like a http set cookie header.
|
|
// (e.g. "cookie1=value1; domain=abc.com; path=/; secure").
|
|
static std::string BuildCookieAttributesLine(const CanonicalCookie& cookie);
|
|
|
|
private:
|
|
FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestPrefixHistograms);
|
|
FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestHasHiddenPrefixName);
|
|
|
|
// The special cookie prefixes as defined in
|
|
// https://tools.ietf.org/html/draft-west-cookie-prefixes
|
|
//
|
|
// This enum is being histogrammed; do not reorder or remove values.
|
|
enum CookiePrefix {
|
|
COOKIE_PREFIX_NONE = 0,
|
|
COOKIE_PREFIX_SECURE,
|
|
COOKIE_PREFIX_HOST,
|
|
COOKIE_PREFIX_LAST
|
|
};
|
|
|
|
// Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that
|
|
// applies to the given cookie |name|.
|
|
static CookiePrefix GetCookiePrefix(const std::string& name) {
|
|
return GetCookiePrefix(name,
|
|
base::FeatureList::IsEnabled(
|
|
net::features::kCaseInsensitiveCookiePrefix));
|
|
}
|
|
|
|
// Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that
|
|
// applies to the given cookie |name|. If `check_insensitively` is true then
|
|
// the string comparison will be performed case insensitively.
|
|
static CookiePrefix GetCookiePrefix(const std::string& name,
|
|
bool check_insensitively);
|
|
// Records histograms to measure how often cookie prefixes appear in
|
|
// the wild and how often they would be blocked.
|
|
static void RecordCookiePrefixMetrics(CookiePrefix prefix_case_sensitive,
|
|
CookiePrefix prefix_case_insensitive,
|
|
bool is_insensitive_prefix_valid);
|
|
// Returns true if a prefixed cookie does not violate any of the rules
|
|
// for that cookie.
|
|
static bool IsCookiePrefixValid(CookiePrefix prefix,
|
|
const GURL& url,
|
|
const ParsedCookie& parsed_cookie);
|
|
static bool IsCookiePrefixValid(CookiePrefix prefix,
|
|
const GURL& url,
|
|
bool secure,
|
|
const std::string& domain,
|
|
const std::string& path);
|
|
|
|
// Returns the effective SameSite mode to apply to this cookie. Depends on the
|
|
// value of the given SameSite attribute and the access semantics of the
|
|
// cookie.
|
|
// Note: If you are converting to a different representation of a cookie, you
|
|
// probably want to use SameSite() instead of this method. Otherwise, if you
|
|
// are considering using this method, consider whether you should use
|
|
// IncludeForRequestURL() or IsSetPermittedInContext() instead of doing the
|
|
// SameSite computation yourself.
|
|
CookieEffectiveSameSite GetEffectiveSameSite(
|
|
CookieAccessSemantics access_semantics) const;
|
|
|
|
// Checks for values that could be misinterpreted as a cookie name prefix.
|
|
static bool HasHiddenPrefixName(const base::StringPiece cookie_value);
|
|
|
|
// Returns whether the cookie was created at most |age_threshold| ago.
|
|
bool IsRecentlyCreated(base::TimeDelta age_threshold) const;
|
|
|
|
// Returns true iff the cookie does not violate any rules associated with
|
|
// creating a cookie with the SameParty attribute. In particular, if a cookie
|
|
// has SameParty, then it must be Secure and must not be SameSite=Strict.
|
|
static bool IsCookieSamePartyValid(const ParsedCookie& parsed_cookie);
|
|
static bool IsCookieSamePartyValid(bool is_same_party,
|
|
bool is_secure,
|
|
CookieSameSite same_site);
|
|
|
|
// Returns true iff the cookie is a partitioned cookie with a nonce or that
|
|
// does not violate the semantics of the Partitioned attribute:
|
|
// - Must have the Secure attribute OR the cookie partition contains a nonce.
|
|
static bool IsCookiePartitionedValid(const GURL& url,
|
|
const ParsedCookie& parsed_cookie,
|
|
bool partition_has_nonce);
|
|
static bool IsCookiePartitionedValid(const GURL& url,
|
|
bool secure,
|
|
bool is_partitioned,
|
|
bool partition_has_nonce);
|
|
|
|
// Keep defaults here in sync with
|
|
// services/network/public/interfaces/cookie_manager.mojom.
|
|
std::string name_;
|
|
std::string value_;
|
|
std::string domain_;
|
|
std::string path_;
|
|
base::Time creation_date_;
|
|
base::Time expiry_date_;
|
|
base::Time last_access_date_;
|
|
base::Time last_update_date_;
|
|
bool secure_{false};
|
|
bool httponly_{false};
|
|
CookieSameSite same_site_{CookieSameSite::NO_RESTRICTION};
|
|
CookiePriority priority_{COOKIE_PRIORITY_MEDIUM};
|
|
bool same_party_{false};
|
|
// This will be absl::nullopt for all cookies not set with the Partitioned
|
|
// attribute or without a nonce. If the value is non-null, then the cookie
|
|
// will only be delivered when the top-frame site matches the partition key
|
|
// and the nonce (if present). If the partition key is non-null and opaque,
|
|
// this means the Partitioned cookie was created on an opaque origin or with
|
|
// a nonce.
|
|
absl::optional<CookiePartitionKey> partition_key_;
|
|
CookieSourceScheme source_scheme_{CookieSourceScheme::kUnset};
|
|
// This can be [0,65535], PORT_UNSPECIFIED, or PORT_INVALID.
|
|
// PORT_UNSPECIFIED is used for cookies which already existed in the cookie
|
|
// store prior to this change and therefore their port is unknown.
|
|
// PORT_INVALID is an error for when an out of range port is provided.
|
|
int source_port_{url::PORT_UNSPECIFIED};
|
|
};
|
|
|
|
// Used to pass excluded cookie information when it's possible that the
|
|
// canonical cookie object may not be available.
|
|
struct NET_EXPORT CookieAndLineWithAccessResult {
|
|
CookieAndLineWithAccessResult();
|
|
CookieAndLineWithAccessResult(absl::optional<CanonicalCookie> cookie,
|
|
std::string cookie_string,
|
|
CookieAccessResult access_result);
|
|
CookieAndLineWithAccessResult(
|
|
const CookieAndLineWithAccessResult& cookie_and_line_with_access_result);
|
|
|
|
CookieAndLineWithAccessResult& operator=(
|
|
const CookieAndLineWithAccessResult& cookie_and_line_with_access_result);
|
|
|
|
CookieAndLineWithAccessResult(
|
|
CookieAndLineWithAccessResult&& cookie_and_line_with_access_result);
|
|
|
|
~CookieAndLineWithAccessResult();
|
|
|
|
absl::optional<CanonicalCookie> cookie;
|
|
std::string cookie_string;
|
|
CookieAccessResult access_result;
|
|
};
|
|
|
|
struct CookieWithAccessResult {
|
|
CanonicalCookie cookie;
|
|
CookieAccessResult access_result;
|
|
};
|
|
|
|
// Provided to allow gtest to create more helpful error messages, instead of
|
|
// printing hex.
|
|
inline void PrintTo(const CanonicalCookie& cc, std::ostream* os) {
|
|
*os << "{ name=" << cc.Name() << ", value=" << cc.Value() << " }";
|
|
}
|
|
inline void PrintTo(const CookieWithAccessResult& cwar, std::ostream* os) {
|
|
*os << "{ ";
|
|
PrintTo(cwar.cookie, os);
|
|
*os << ", ";
|
|
PrintTo(cwar.access_result, os);
|
|
*os << " }";
|
|
}
|
|
inline void PrintTo(const CookieAndLineWithAccessResult& calwar,
|
|
std::ostream* os) {
|
|
*os << "{ ";
|
|
if (calwar.cookie) {
|
|
PrintTo(*calwar.cookie, os);
|
|
} else {
|
|
*os << "nullopt";
|
|
}
|
|
*os << ", " << calwar.cookie_string << ", ";
|
|
PrintTo(calwar.access_result, os);
|
|
*os << " }";
|
|
}
|
|
|
|
} // namespace net
|
|
|
|
#endif // NET_COOKIES_CANONICAL_COOKIE_H_
|