xref: /aosp_15_r20/external/cronet/net/cookies/canonical_cookie.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 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 #ifndef NET_COOKIES_CANONICAL_COOKIE_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_COOKIES_CANONICAL_COOKIE_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <memory>
9*6777b538SAndroid Build Coastguard Worker #include <optional>
10*6777b538SAndroid Build Coastguard Worker #include <string>
11*6777b538SAndroid Build Coastguard Worker #include <string_view>
12*6777b538SAndroid Build Coastguard Worker #include <vector>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/types/pass_key.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/base/features.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_access_params.h"
21*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_access_result.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_base.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_constants.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_inclusion_status.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_options.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/cookies/cookie_partition_key.h"
27*6777b538SAndroid Build Coastguard Worker #include "url/third_party/mozilla/url_parse.h"
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker class GURL;
30*6777b538SAndroid Build Coastguard Worker 
31*6777b538SAndroid Build Coastguard Worker namespace net {
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker class ParsedCookie;
34*6777b538SAndroid Build Coastguard Worker class CanonicalCookie;
35*6777b538SAndroid Build Coastguard Worker 
36*6777b538SAndroid Build Coastguard Worker struct CookieWithAccessResult;
37*6777b538SAndroid Build Coastguard Worker struct CookieAndLineWithAccessResult;
38*6777b538SAndroid Build Coastguard Worker 
39*6777b538SAndroid Build Coastguard Worker using CookieList = std::vector<CanonicalCookie>;
40*6777b538SAndroid Build Coastguard Worker using CookieAndLineAccessResultList =
41*6777b538SAndroid Build Coastguard Worker     std::vector<CookieAndLineWithAccessResult>;
42*6777b538SAndroid Build Coastguard Worker using CookieAccessResultList = std::vector<CookieWithAccessResult>;
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker // Represents a real/concrete cookie, which may be sent on requests or set by a
45*6777b538SAndroid Build Coastguard Worker // response if the request context and attributes allow it.
46*6777b538SAndroid Build Coastguard Worker class NET_EXPORT CanonicalCookie : public CookieBase {
47*6777b538SAndroid Build Coastguard Worker  public:
48*6777b538SAndroid Build Coastguard Worker   CanonicalCookie();
49*6777b538SAndroid Build Coastguard Worker   CanonicalCookie(const CanonicalCookie& other);
50*6777b538SAndroid Build Coastguard Worker   CanonicalCookie(CanonicalCookie&& other);
51*6777b538SAndroid Build Coastguard Worker   CanonicalCookie& operator=(const CanonicalCookie& other);
52*6777b538SAndroid Build Coastguard Worker   CanonicalCookie& operator=(CanonicalCookie&& other);
53*6777b538SAndroid Build Coastguard Worker   ~CanonicalCookie() override;
54*6777b538SAndroid Build Coastguard Worker 
55*6777b538SAndroid Build Coastguard Worker   // This constructor does not validate or canonicalize their inputs;
56*6777b538SAndroid Build Coastguard Worker   // the resulting CanonicalCookies should not be relied on to be canonical
57*6777b538SAndroid Build Coastguard Worker   // unless the caller has done appropriate validation and canonicalization
58*6777b538SAndroid Build Coastguard Worker   // themselves.
59*6777b538SAndroid Build Coastguard Worker   //
60*6777b538SAndroid Build Coastguard Worker   // NOTE: Prefer using Create, CreateSanitizedCookie, or FromStorage (depending
61*6777b538SAndroid Build Coastguard Worker   // on the use case) over directly using this constructor.
62*6777b538SAndroid Build Coastguard Worker   //
63*6777b538SAndroid Build Coastguard Worker   // NOTE: Do not add any defaults to this constructor, we want every caller to
64*6777b538SAndroid Build Coastguard Worker   // understand and choose their inputs.
65*6777b538SAndroid Build Coastguard Worker   CanonicalCookie(base::PassKey<CanonicalCookie>,
66*6777b538SAndroid Build Coastguard Worker                   std::string name,
67*6777b538SAndroid Build Coastguard Worker                   std::string value,
68*6777b538SAndroid Build Coastguard Worker                   std::string domain,
69*6777b538SAndroid Build Coastguard Worker                   std::string path,
70*6777b538SAndroid Build Coastguard Worker                   base::Time creation,
71*6777b538SAndroid Build Coastguard Worker                   base::Time expiration,
72*6777b538SAndroid Build Coastguard Worker                   base::Time last_access,
73*6777b538SAndroid Build Coastguard Worker                   base::Time last_update,
74*6777b538SAndroid Build Coastguard Worker                   bool secure,
75*6777b538SAndroid Build Coastguard Worker                   bool httponly,
76*6777b538SAndroid Build Coastguard Worker                   CookieSameSite same_site,
77*6777b538SAndroid Build Coastguard Worker                   CookiePriority priority,
78*6777b538SAndroid Build Coastguard Worker                   std::optional<CookiePartitionKey> partition_key,
79*6777b538SAndroid Build Coastguard Worker                   CookieSourceScheme scheme_secure,
80*6777b538SAndroid Build Coastguard Worker                   int source_port,
81*6777b538SAndroid Build Coastguard Worker                   CookieSourceType source_type);
82*6777b538SAndroid Build Coastguard Worker 
83*6777b538SAndroid Build Coastguard Worker   // Creates a new `CanonicalCookie` from the `cookie_line` and the
84*6777b538SAndroid Build Coastguard Worker   // `creation_time`.  Canonicalizes inputs.  May return nullptr if
85*6777b538SAndroid Build Coastguard Worker   // an attribute value is invalid.  `url` must be valid.  `creation_time` may
86*6777b538SAndroid Build Coastguard Worker   // not be null. Sets optional `status` to the relevant CookieInclusionStatus
87*6777b538SAndroid Build Coastguard Worker   // if provided.  `server_time` indicates what the server sending us the Cookie
88*6777b538SAndroid Build Coastguard Worker   // thought the current time was when the cookie was produced.  This is used to
89*6777b538SAndroid Build Coastguard Worker   // adjust for clock skew between server and host.
90*6777b538SAndroid Build Coastguard Worker   //
91*6777b538SAndroid Build Coastguard Worker   // SameSite and HttpOnly related parameters are not checked here,
92*6777b538SAndroid Build Coastguard Worker   // so creation of CanonicalCookies with e.g. SameSite=Strict from a cross-site
93*6777b538SAndroid Build Coastguard Worker   // context is allowed. Create() also does not check whether `url` has a secure
94*6777b538SAndroid Build Coastguard Worker   // scheme if attempting to create a Secure cookie. The Secure, SameSite, and
95*6777b538SAndroid Build Coastguard Worker   // HttpOnly related parameters should be checked when setting the cookie in
96*6777b538SAndroid Build Coastguard Worker   // the CookieStore.
97*6777b538SAndroid Build Coastguard Worker   //
98*6777b538SAndroid Build Coastguard Worker   // The partition_key argument only needs to be present if the cookie line
99*6777b538SAndroid Build Coastguard Worker   // contains the Partitioned attribute. If the cookie line will never contain
100*6777b538SAndroid Build Coastguard Worker   // that attribute, you should use std::nullopt to indicate you intend to
101*6777b538SAndroid Build Coastguard Worker   // always create an unpartitioned cookie. If partition_key has a value but the
102*6777b538SAndroid Build Coastguard Worker   // cookie line does not contain the Partitioned attribute, the resulting
103*6777b538SAndroid Build Coastguard Worker   // cookie will be unpartitioned. If the partition_key is null, then the cookie
104*6777b538SAndroid Build Coastguard Worker   // will be unpartitioned even when the cookie line has the Partitioned
105*6777b538SAndroid Build Coastguard Worker   // attribute.
106*6777b538SAndroid Build Coastguard Worker   //
107*6777b538SAndroid Build Coastguard Worker   // The `block_truncated` argument indicates whether the '\0', '\n', and '\r'
108*6777b538SAndroid Build Coastguard Worker   // characters should cause the cookie to fail to be created if present
109*6777b538SAndroid Build Coastguard Worker   // (instead of truncating `cookie_line` at the first occurrence).
110*6777b538SAndroid Build Coastguard Worker   //
111*6777b538SAndroid Build Coastguard Worker   // If a cookie is returned, `cookie->IsCanonical()` will be true.
112*6777b538SAndroid Build Coastguard Worker   //
113*6777b538SAndroid Build Coastguard Worker   // NOTE: Do not add any defaults to this constructor, we want every caller to
114*6777b538SAndroid Build Coastguard Worker   // understand and choose their inputs.
115*6777b538SAndroid Build Coastguard Worker   static std::unique_ptr<CanonicalCookie> Create(
116*6777b538SAndroid Build Coastguard Worker       const GURL& url,
117*6777b538SAndroid Build Coastguard Worker       const std::string& cookie_line,
118*6777b538SAndroid Build Coastguard Worker       const base::Time& creation_time,
119*6777b538SAndroid Build Coastguard Worker       std::optional<base::Time> server_time,
120*6777b538SAndroid Build Coastguard Worker       std::optional<CookiePartitionKey> cookie_partition_key,
121*6777b538SAndroid Build Coastguard Worker       bool block_truncated,
122*6777b538SAndroid Build Coastguard Worker       CookieSourceType source_type,
123*6777b538SAndroid Build Coastguard Worker       CookieInclusionStatus* status);
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // Create a canonical cookie based on sanitizing the passed inputs in the
126*6777b538SAndroid Build Coastguard Worker   // context of the passed URL.  Returns a null unique pointer if the inputs
127*6777b538SAndroid Build Coastguard Worker   // cannot be sanitized.  If `status` is provided it will have any relevant
128*6777b538SAndroid Build Coastguard Worker   // CookieInclusionStatus rejection reasons set. If a cookie is created,
129*6777b538SAndroid Build Coastguard Worker   // `cookie->IsCanonical()` will be true.
130*6777b538SAndroid Build Coastguard Worker   //
131*6777b538SAndroid Build Coastguard Worker   // NOTE: Do not add any defaults to this constructor, we want every caller to
132*6777b538SAndroid Build Coastguard Worker   // understand and choose their inputs.
133*6777b538SAndroid Build Coastguard Worker   static std::unique_ptr<CanonicalCookie> CreateSanitizedCookie(
134*6777b538SAndroid Build Coastguard Worker       const GURL& url,
135*6777b538SAndroid Build Coastguard Worker       const std::string& name,
136*6777b538SAndroid Build Coastguard Worker       const std::string& value,
137*6777b538SAndroid Build Coastguard Worker       const std::string& domain,
138*6777b538SAndroid Build Coastguard Worker       const std::string& path,
139*6777b538SAndroid Build Coastguard Worker       base::Time creation_time,
140*6777b538SAndroid Build Coastguard Worker       base::Time expiration_time,
141*6777b538SAndroid Build Coastguard Worker       base::Time last_access_time,
142*6777b538SAndroid Build Coastguard Worker       bool secure,
143*6777b538SAndroid Build Coastguard Worker       bool http_only,
144*6777b538SAndroid Build Coastguard Worker       CookieSameSite same_site,
145*6777b538SAndroid Build Coastguard Worker       CookiePriority priority,
146*6777b538SAndroid Build Coastguard Worker       std::optional<CookiePartitionKey> partition_key,
147*6777b538SAndroid Build Coastguard Worker       CookieInclusionStatus* status);
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker   // FromStorage is a factory method which is meant for creating a new
150*6777b538SAndroid Build Coastguard Worker   // CanonicalCookie using properties of a previously existing cookie
151*6777b538SAndroid Build Coastguard Worker   // that was already ingested into the cookie store.
152*6777b538SAndroid Build Coastguard Worker   // This should NOT be used to create a new CanonicalCookie that was not
153*6777b538SAndroid Build Coastguard Worker   // already in the store.
154*6777b538SAndroid Build Coastguard Worker   // Returns nullptr if the resulting cookie is not canonical,
155*6777b538SAndroid Build Coastguard Worker   // i.e. cc->IsCanonical() returns false.
156*6777b538SAndroid Build Coastguard Worker   //
157*6777b538SAndroid Build Coastguard Worker   // NOTE: Do not add any defaults to this constructor, we want every caller to
158*6777b538SAndroid Build Coastguard Worker   // understand and choose their inputs.
159*6777b538SAndroid Build Coastguard Worker   static std::unique_ptr<CanonicalCookie> FromStorage(
160*6777b538SAndroid Build Coastguard Worker       std::string name,
161*6777b538SAndroid Build Coastguard Worker       std::string value,
162*6777b538SAndroid Build Coastguard Worker       std::string domain,
163*6777b538SAndroid Build Coastguard Worker       std::string path,
164*6777b538SAndroid Build Coastguard Worker       base::Time creation,
165*6777b538SAndroid Build Coastguard Worker       base::Time expiration,
166*6777b538SAndroid Build Coastguard Worker       base::Time last_access,
167*6777b538SAndroid Build Coastguard Worker       base::Time last_update,
168*6777b538SAndroid Build Coastguard Worker       bool secure,
169*6777b538SAndroid Build Coastguard Worker       bool httponly,
170*6777b538SAndroid Build Coastguard Worker       CookieSameSite same_site,
171*6777b538SAndroid Build Coastguard Worker       CookiePriority priority,
172*6777b538SAndroid Build Coastguard Worker       std::optional<CookiePartitionKey> partition_key,
173*6777b538SAndroid Build Coastguard Worker       CookieSourceScheme source_scheme,
174*6777b538SAndroid Build Coastguard Worker       int source_port,
175*6777b538SAndroid Build Coastguard Worker       CookieSourceType source_type);
176*6777b538SAndroid Build Coastguard Worker 
177*6777b538SAndroid Build Coastguard Worker   // Create a CanonicalCookie that is not guaranteed to actually be Canonical
178*6777b538SAndroid Build Coastguard Worker   // for tests. Use this only if you want to bypass parameter validation to
179*6777b538SAndroid Build Coastguard Worker   // create a cookie that otherwise shouldn't be possible to store.
180*6777b538SAndroid Build Coastguard Worker   static std::unique_ptr<CanonicalCookie> CreateUnsafeCookieForTesting(
181*6777b538SAndroid Build Coastguard Worker       const std::string& name,
182*6777b538SAndroid Build Coastguard Worker       const std::string& value,
183*6777b538SAndroid Build Coastguard Worker       const std::string& domain,
184*6777b538SAndroid Build Coastguard Worker       const std::string& path,
185*6777b538SAndroid Build Coastguard Worker       const base::Time& creation,
186*6777b538SAndroid Build Coastguard Worker       const base::Time& expiration,
187*6777b538SAndroid Build Coastguard Worker       const base::Time& last_access,
188*6777b538SAndroid Build Coastguard Worker       const base::Time& last_update,
189*6777b538SAndroid Build Coastguard Worker       bool secure,
190*6777b538SAndroid Build Coastguard Worker       bool httponly,
191*6777b538SAndroid Build Coastguard Worker       CookieSameSite same_site,
192*6777b538SAndroid Build Coastguard Worker       CookiePriority priority,
193*6777b538SAndroid Build Coastguard Worker       std::optional<CookiePartitionKey> partition_key = std::nullopt,
194*6777b538SAndroid Build Coastguard Worker       CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset,
195*6777b538SAndroid Build Coastguard Worker       int source_port = url::PORT_UNSPECIFIED,
196*6777b538SAndroid Build Coastguard Worker       CookieSourceType source_type = CookieSourceType::kUnknown);
197*6777b538SAndroid Build Coastguard Worker 
198*6777b538SAndroid Build Coastguard Worker   // Like Create but with some more friendly defaults for use in tests.
199*6777b538SAndroid Build Coastguard Worker   static std::unique_ptr<CanonicalCookie> CreateForTesting(
200*6777b538SAndroid Build Coastguard Worker       const GURL& url,
201*6777b538SAndroid Build Coastguard Worker       const std::string& cookie_line,
202*6777b538SAndroid Build Coastguard Worker       const base::Time& creation_time,
203*6777b538SAndroid Build Coastguard Worker       std::optional<base::Time> server_time = std::nullopt,
204*6777b538SAndroid Build Coastguard Worker       std::optional<CookiePartitionKey> cookie_partition_key = std::nullopt,
205*6777b538SAndroid Build Coastguard Worker       bool block_truncated = true,
206*6777b538SAndroid Build Coastguard Worker       CookieSourceType source_type = CookieSourceType::kUnknown,
207*6777b538SAndroid Build Coastguard Worker       CookieInclusionStatus* status = nullptr);
208*6777b538SAndroid Build Coastguard Worker 
209*6777b538SAndroid Build Coastguard Worker   bool operator<(const CanonicalCookie& other) const {
210*6777b538SAndroid Build Coastguard Worker     // Use the cookie properties that uniquely identify a cookie to determine
211*6777b538SAndroid Build Coastguard Worker     // ordering.
212*6777b538SAndroid Build Coastguard Worker     return UniqueKey() < other.UniqueKey();
213*6777b538SAndroid Build Coastguard Worker   }
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker   bool operator==(const CanonicalCookie& other) const {
216*6777b538SAndroid Build Coastguard Worker     return IsEquivalent(other);
217*6777b538SAndroid Build Coastguard Worker   }
218*6777b538SAndroid Build Coastguard Worker 
219*6777b538SAndroid Build Coastguard Worker   // See CookieBase for other accessors.
Value()220*6777b538SAndroid Build Coastguard Worker   const std::string& Value() const { return value_; }
ExpiryDate()221*6777b538SAndroid Build Coastguard Worker   const base::Time& ExpiryDate() const { return expiry_date_; }
LastAccessDate()222*6777b538SAndroid Build Coastguard Worker   const base::Time& LastAccessDate() const { return last_access_date_; }
LastUpdateDate()223*6777b538SAndroid Build Coastguard Worker   const base::Time& LastUpdateDate() const { return last_update_date_; }
IsPersistent()224*6777b538SAndroid Build Coastguard Worker   bool IsPersistent() const { return !expiry_date_.is_null(); }
Priority()225*6777b538SAndroid Build Coastguard Worker   CookiePriority Priority() const { return priority_; }
SourceType()226*6777b538SAndroid Build Coastguard Worker   CookieSourceType SourceType() const { return source_type_; }
227*6777b538SAndroid Build Coastguard Worker 
IsExpired(const base::Time & current)228*6777b538SAndroid Build Coastguard Worker   bool IsExpired(const base::Time& current) const {
229*6777b538SAndroid Build Coastguard Worker     return !expiry_date_.is_null() && current >= expiry_date_;
230*6777b538SAndroid Build Coastguard Worker   }
231*6777b538SAndroid Build Coastguard Worker 
232*6777b538SAndroid Build Coastguard Worker   // Are the cookies considered equivalent in the eyes of RFC 2965.
233*6777b538SAndroid Build Coastguard Worker   // The RFC says that name must match (case-sensitive), domain must
234*6777b538SAndroid Build Coastguard Worker   // match (case insensitive), and path must match (case sensitive).
235*6777b538SAndroid Build Coastguard Worker   // For the case insensitive domain compare, we rely on the domain
236*6777b538SAndroid Build Coastguard Worker   // having been canonicalized (in
237*6777b538SAndroid Build Coastguard Worker   // GetCookieDomainWithString->CanonicalizeHost).
238*6777b538SAndroid Build Coastguard Worker   // If partitioned cookies are enabled, then we check the cookies have the same
239*6777b538SAndroid Build Coastguard Worker   // partition key in addition to the checks in RFC 2965.
240*6777b538SAndroid Build Coastguard Worker   //
241*6777b538SAndroid Build Coastguard Worker   // To support origin-bound cookies the check will also include the source
242*6777b538SAndroid Build Coastguard Worker   // scheme and/or port depending on the state of the associated feature.
243*6777b538SAndroid Build Coastguard Worker   // Additionally, domain cookies get a slightly different check which does not
244*6777b538SAndroid Build Coastguard Worker   // include the source port.
IsEquivalent(const CanonicalCookie & ecc)245*6777b538SAndroid Build Coastguard Worker   bool IsEquivalent(const CanonicalCookie& ecc) const {
246*6777b538SAndroid Build Coastguard Worker     // It seems like it would make sense to take secure, httponly, and samesite
247*6777b538SAndroid Build Coastguard Worker     // into account, but the RFC doesn't specify this.
248*6777b538SAndroid Build Coastguard Worker     // NOTE: Keep this logic in-sync with TrimDuplicateCookiesForKey().
249*6777b538SAndroid Build Coastguard Worker 
250*6777b538SAndroid Build Coastguard Worker     // A host cookie will never match a domain cookie or vice-versa, this is
251*6777b538SAndroid Build Coastguard Worker     // because the "host-only-flag" is encoded within the `domain` field of the
252*6777b538SAndroid Build Coastguard Worker     // respective keys. So we don't need to explicitly check if ecc is also host
253*6777b538SAndroid Build Coastguard Worker     // or domain.
254*6777b538SAndroid Build Coastguard Worker     if (IsHostCookie()) {
255*6777b538SAndroid Build Coastguard Worker       return UniqueKey() == ecc.UniqueKey();
256*6777b538SAndroid Build Coastguard Worker     }
257*6777b538SAndroid Build Coastguard Worker     // Is domain cookie
258*6777b538SAndroid Build Coastguard Worker     return UniqueDomainKey() == ecc.UniqueDomainKey();
259*6777b538SAndroid Build Coastguard Worker   }
260*6777b538SAndroid Build Coastguard Worker 
261*6777b538SAndroid Build Coastguard Worker   // Checks a looser set of equivalency rules than 'IsEquivalent()' in order
262*6777b538SAndroid Build Coastguard Worker   // to support the stricter 'Secure' behaviors specified in Step 12 of
263*6777b538SAndroid Build Coastguard Worker   // https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-05#section-5.4
264*6777b538SAndroid Build Coastguard Worker   // which originated from the proposal in
265*6777b538SAndroid Build Coastguard Worker   // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone#section-3
266*6777b538SAndroid Build Coastguard Worker   //
267*6777b538SAndroid Build Coastguard Worker   // Returns 'true' if this cookie's name matches |secure_cookie|, and this
268*6777b538SAndroid Build Coastguard Worker   // cookie is a domain-match for |secure_cookie| (or vice versa), and
269*6777b538SAndroid Build Coastguard Worker   // |secure_cookie|'s path is "on" this cookie's path (as per 'IsOnPath()').
270*6777b538SAndroid Build Coastguard Worker   // If partitioned cookies are enabled, it also checks that the cookie has
271*6777b538SAndroid Build Coastguard Worker   // the same partition key as |secure_cookie|.
272*6777b538SAndroid Build Coastguard Worker   //
273*6777b538SAndroid Build Coastguard Worker   // Note that while the domain-match cuts both ways (e.g. 'example.com'
274*6777b538SAndroid Build Coastguard Worker   // matches 'www.example.com' in either direction), the path-match is
275*6777b538SAndroid Build Coastguard Worker   // unidirectional (e.g. '/login/en' matches '/login' and '/', but
276*6777b538SAndroid Build Coastguard Worker   // '/login' and '/' do not match '/login/en').
277*6777b538SAndroid Build Coastguard Worker   //
278*6777b538SAndroid Build Coastguard Worker   // Conceptually:
279*6777b538SAndroid Build Coastguard Worker   // If new_cookie.IsEquivalentForSecureCookieMatching(secure_cookie) is true,
280*6777b538SAndroid Build Coastguard Worker   // this means that new_cookie would "shadow" secure_cookie: they would would
281*6777b538SAndroid Build Coastguard Worker   // be indistinguishable when serialized into a Cookie header. This is
282*6777b538SAndroid Build Coastguard Worker   // important because, if an attacker is attempting to set new_cookie, it
283*6777b538SAndroid Build Coastguard Worker   // should not be allowed to mislead the server into using new_cookie's value
284*6777b538SAndroid Build Coastguard Worker   // instead of secure_cookie's.
285*6777b538SAndroid Build Coastguard Worker   //
286*6777b538SAndroid Build Coastguard Worker   // The reason for the asymmetric path comparison ("cookie1=bad; path=/a/b"
287*6777b538SAndroid Build Coastguard Worker   // from an insecure source is not allowed if "cookie1=good; secure; path=/a"
288*6777b538SAndroid Build Coastguard Worker   // exists, but "cookie2=bad; path=/a" from an insecure source is allowed if
289*6777b538SAndroid Build Coastguard Worker   // "cookie2=good; secure; path=/a/b" exists) is because cookies in the Cookie
290*6777b538SAndroid Build Coastguard Worker   // header are serialized with longer path first. (See CookieSorter in
291*6777b538SAndroid Build Coastguard Worker   // cookie_monster.cc.) That is, they would be serialized as "Cookie:
292*6777b538SAndroid Build Coastguard Worker   // cookie1=bad; cookie1=good" in one case, and "Cookie: cookie2=good;
293*6777b538SAndroid Build Coastguard Worker   // cookie2=bad" in the other case. The first scenario is not allowed because
294*6777b538SAndroid Build Coastguard Worker   // the attacker injects the bad value, whereas the second scenario is ok
295*6777b538SAndroid Build Coastguard Worker   // because the good value is still listed first.
296*6777b538SAndroid Build Coastguard Worker   bool IsEquivalentForSecureCookieMatching(
297*6777b538SAndroid Build Coastguard Worker       const CanonicalCookie& secure_cookie) const;
298*6777b538SAndroid Build Coastguard Worker 
299*6777b538SAndroid Build Coastguard Worker   // Returns true if the |other| cookie's data members (instance variables)
300*6777b538SAndroid Build Coastguard Worker   // match, for comparing cookies in collections.
301*6777b538SAndroid Build Coastguard Worker   bool HasEquivalentDataMembers(const CanonicalCookie& other) const;
302*6777b538SAndroid Build Coastguard Worker 
303*6777b538SAndroid Build Coastguard Worker   // Similar to operator<, but considers all data members.
304*6777b538SAndroid Build Coastguard Worker   bool DataMembersPrecede(const CanonicalCookie& other) const;
305*6777b538SAndroid Build Coastguard Worker 
SetLastAccessDate(const base::Time & date)306*6777b538SAndroid Build Coastguard Worker   void SetLastAccessDate(const base::Time& date) {
307*6777b538SAndroid Build Coastguard Worker     last_access_date_ = date;
308*6777b538SAndroid Build Coastguard Worker   }
309*6777b538SAndroid Build Coastguard Worker 
310*6777b538SAndroid Build Coastguard Worker   std::string DebugString() const;
311*6777b538SAndroid Build Coastguard Worker 
312*6777b538SAndroid Build Coastguard Worker   // Returns the canonical path based on the specified url and path attribute
313*6777b538SAndroid Build Coastguard Worker   // value. Note that this method does not enforce character set or size
314*6777b538SAndroid Build Coastguard Worker   // checks on `path_string`.
315*6777b538SAndroid Build Coastguard Worker   static std::string CanonPathWithString(const GURL& url,
316*6777b538SAndroid Build Coastguard Worker                                          const std::string& path_string);
317*6777b538SAndroid Build Coastguard Worker 
318*6777b538SAndroid Build Coastguard Worker   // Returns a "null" time if expiration was unspecified or invalid.
319*6777b538SAndroid Build Coastguard Worker   static base::Time ParseExpiration(const ParsedCookie& pc,
320*6777b538SAndroid Build Coastguard Worker                                     const base::Time& current,
321*6777b538SAndroid Build Coastguard Worker                                     const base::Time& server_time);
322*6777b538SAndroid Build Coastguard Worker 
323*6777b538SAndroid Build Coastguard Worker   // Per rfc6265bis the maximum expiry date is no further than 400 days in the
324*6777b538SAndroid Build Coastguard Worker   // future.
325*6777b538SAndroid Build Coastguard Worker   static base::Time ValidateAndAdjustExpiryDate(const base::Time& expiry_date,
326*6777b538SAndroid Build Coastguard Worker                                                 const base::Time& creation_date,
327*6777b538SAndroid Build Coastguard Worker                                                 net::CookieSourceScheme scheme);
328*6777b538SAndroid Build Coastguard Worker 
329*6777b538SAndroid Build Coastguard Worker   // Cookie ordering methods.
330*6777b538SAndroid Build Coastguard Worker 
331*6777b538SAndroid Build Coastguard Worker   // Returns true if the cookie is less than |other|, considering only name,
332*6777b538SAndroid Build Coastguard Worker   // domain and path. In particular, two equivalent cookies (see IsEquivalent())
333*6777b538SAndroid Build Coastguard Worker   // are identical for PartialCompare().
334*6777b538SAndroid Build Coastguard Worker   bool PartialCompare(const CanonicalCookie& other) const;
335*6777b538SAndroid Build Coastguard Worker 
336*6777b538SAndroid Build Coastguard Worker   // Return whether this object is a valid CanonicalCookie().  Invalid
337*6777b538SAndroid Build Coastguard Worker   // cookies may be constructed by the detailed constructor.
338*6777b538SAndroid Build Coastguard Worker   // A cookie is considered canonical if-and-only-if:
339*6777b538SAndroid Build Coastguard Worker   // * It can be created by CanonicalCookie::Create, or
340*6777b538SAndroid Build Coastguard Worker   // * It is identical to a cookie created by CanonicalCookie::Create except
341*6777b538SAndroid Build Coastguard Worker   //   that the creation time is null, or
342*6777b538SAndroid Build Coastguard Worker   // * It can be derived from a cookie created by CanonicalCookie::Create by
343*6777b538SAndroid Build Coastguard Worker   //   entry into and retrieval from a cookie store (specifically, this means
344*6777b538SAndroid Build Coastguard Worker   //   by the setting of an creation time in place of a null creation time, and
345*6777b538SAndroid Build Coastguard Worker   //   the setting of a last access time).
346*6777b538SAndroid Build Coastguard Worker   // An additional requirement on a CanonicalCookie is that if the last
347*6777b538SAndroid Build Coastguard Worker   // access time is non-null, the creation time must also be non-null and
348*6777b538SAndroid Build Coastguard Worker   // greater than the last access time.
349*6777b538SAndroid Build Coastguard Worker   bool IsCanonical() const;
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker   // Return whether this object is a valid CanonicalCookie() when retrieving the
352*6777b538SAndroid Build Coastguard Worker   // cookie from the persistent store. Cookie that exist in the persistent store
353*6777b538SAndroid Build Coastguard Worker   // may have been created before more recent changes to the definition of
354*6777b538SAndroid Build Coastguard Worker   // "canonical". To ease the transition to the new definitions, and to prevent
355*6777b538SAndroid Build Coastguard Worker   // users from having their cookies deleted, this function supports the older
356*6777b538SAndroid Build Coastguard Worker   // definition of canonical. This function is intended to be temporary because
357*6777b538SAndroid Build Coastguard Worker   // as the number of older cookies (which are non-compliant with the newer
358*6777b538SAndroid Build Coastguard Worker   // definition of canonical) decay toward zero it can eventually be replaced
359*6777b538SAndroid Build Coastguard Worker   // by `IsCanonical()` to enforce the newer definition of canonical.
360*6777b538SAndroid Build Coastguard Worker   //
361*6777b538SAndroid Build Coastguard Worker   // A cookie is considered canonical by this function if-and-only-if:
362*6777b538SAndroid Build Coastguard Worker   // * It is considered canonical by IsCanonical()
363*6777b538SAndroid Build Coastguard Worker   // * TODO(crbug.com/1244172): Add exceptions once IsCanonical() starts
364*6777b538SAndroid Build Coastguard Worker   // enforcing them.
365*6777b538SAndroid Build Coastguard Worker   bool IsCanonicalForFromStorage() const;
366*6777b538SAndroid Build Coastguard Worker 
367*6777b538SAndroid Build Coastguard Worker   // Returns whether the effective SameSite mode is SameSite=None (i.e. no
368*6777b538SAndroid Build Coastguard Worker   // SameSite restrictions).
369*6777b538SAndroid Build Coastguard Worker   bool IsEffectivelySameSiteNone(CookieAccessSemantics access_semantics =
370*6777b538SAndroid Build Coastguard Worker                                      CookieAccessSemantics::UNKNOWN) const;
371*6777b538SAndroid Build Coastguard Worker 
372*6777b538SAndroid Build Coastguard Worker   CookieEffectiveSameSite GetEffectiveSameSiteForTesting(
373*6777b538SAndroid Build Coastguard Worker       CookieAccessSemantics access_semantics =
374*6777b538SAndroid Build Coastguard Worker           CookieAccessSemantics::UNKNOWN) const;
375*6777b538SAndroid Build Coastguard Worker 
376*6777b538SAndroid Build Coastguard Worker   // Returns the cookie line (e.g. "cookie1=value1; cookie2=value2") represented
377*6777b538SAndroid Build Coastguard Worker   // by |cookies|. The string is built in the same order as the given list.
378*6777b538SAndroid Build Coastguard Worker   static std::string BuildCookieLine(const CookieList& cookies);
379*6777b538SAndroid Build Coastguard Worker 
380*6777b538SAndroid Build Coastguard Worker   // Same as above but takes a CookieAccessResultList
381*6777b538SAndroid Build Coastguard Worker   // (ignores the access result).
382*6777b538SAndroid Build Coastguard Worker   static std::string BuildCookieLine(const CookieAccessResultList& cookies);
383*6777b538SAndroid Build Coastguard Worker 
384*6777b538SAndroid Build Coastguard Worker   // Takes a single CanonicalCookie and returns a cookie line containing the
385*6777b538SAndroid Build Coastguard Worker   // attributes of |cookie| formatted like a http set cookie header.
386*6777b538SAndroid Build Coastguard Worker   // (e.g. "cookie1=value1; domain=abc.com; path=/; secure").
387*6777b538SAndroid Build Coastguard Worker   static std::string BuildCookieAttributesLine(const CanonicalCookie& cookie);
388*6777b538SAndroid Build Coastguard Worker 
389*6777b538SAndroid Build Coastguard Worker  private:
390*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest,
391*6777b538SAndroid Build Coastguard Worker                            TestGetAndAdjustPortForTrustworthyUrls);
392*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestPrefixHistograms);
393*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestHasHiddenPrefixName);
394*6777b538SAndroid Build Coastguard Worker 
395*6777b538SAndroid Build Coastguard Worker   // The special cookie prefixes as defined in
396*6777b538SAndroid Build Coastguard Worker   // https://tools.ietf.org/html/draft-west-cookie-prefixes
397*6777b538SAndroid Build Coastguard Worker   //
398*6777b538SAndroid Build Coastguard Worker   // This enum is being histogrammed; do not reorder or remove values.
399*6777b538SAndroid Build Coastguard Worker   enum CookiePrefix {
400*6777b538SAndroid Build Coastguard Worker     COOKIE_PREFIX_NONE = 0,
401*6777b538SAndroid Build Coastguard Worker     COOKIE_PREFIX_SECURE,
402*6777b538SAndroid Build Coastguard Worker     COOKIE_PREFIX_HOST,
403*6777b538SAndroid Build Coastguard Worker     COOKIE_PREFIX_LAST
404*6777b538SAndroid Build Coastguard Worker   };
405*6777b538SAndroid Build Coastguard Worker 
406*6777b538SAndroid Build Coastguard Worker   // Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that
407*6777b538SAndroid Build Coastguard Worker   // applies to the given cookie |name|.
GetCookiePrefix(const std::string & name)408*6777b538SAndroid Build Coastguard Worker   static CookiePrefix GetCookiePrefix(const std::string& name) {
409*6777b538SAndroid Build Coastguard Worker     return GetCookiePrefix(name,
410*6777b538SAndroid Build Coastguard Worker                            base::FeatureList::IsEnabled(
411*6777b538SAndroid Build Coastguard Worker                                net::features::kCaseInsensitiveCookiePrefix));
412*6777b538SAndroid Build Coastguard Worker   }
413*6777b538SAndroid Build Coastguard Worker 
414*6777b538SAndroid Build Coastguard Worker   // Returns the CookiePrefix (or COOKIE_PREFIX_NONE if none) that
415*6777b538SAndroid Build Coastguard Worker   // applies to the given cookie |name|. If `check_insensitively` is true then
416*6777b538SAndroid Build Coastguard Worker   // the string comparison will be performed case insensitively.
417*6777b538SAndroid Build Coastguard Worker   static CookiePrefix GetCookiePrefix(const std::string& name,
418*6777b538SAndroid Build Coastguard Worker                                       bool check_insensitively);
419*6777b538SAndroid Build Coastguard Worker   // Records histograms to measure how often cookie prefixes appear in
420*6777b538SAndroid Build Coastguard Worker   // the wild and how often they would be blocked.
421*6777b538SAndroid Build Coastguard Worker   static void RecordCookiePrefixMetrics(CookiePrefix prefix_case_sensitive,
422*6777b538SAndroid Build Coastguard Worker                                         CookiePrefix prefix_case_insensitive,
423*6777b538SAndroid Build Coastguard Worker                                         bool is_insensitive_prefix_valid);
424*6777b538SAndroid Build Coastguard Worker   // Returns true if a prefixed cookie does not violate any of the rules
425*6777b538SAndroid Build Coastguard Worker   // for that cookie.
426*6777b538SAndroid Build Coastguard Worker   static bool IsCookiePrefixValid(CookiePrefix prefix,
427*6777b538SAndroid Build Coastguard Worker                                   const GURL& url,
428*6777b538SAndroid Build Coastguard Worker                                   const ParsedCookie& parsed_cookie);
429*6777b538SAndroid Build Coastguard Worker   static bool IsCookiePrefixValid(CookiePrefix prefix,
430*6777b538SAndroid Build Coastguard Worker                                   const GURL& url,
431*6777b538SAndroid Build Coastguard Worker                                   bool secure,
432*6777b538SAndroid Build Coastguard Worker                                   const std::string& domain,
433*6777b538SAndroid Build Coastguard Worker                                   const std::string& path);
434*6777b538SAndroid Build Coastguard Worker 
435*6777b538SAndroid Build Coastguard Worker   // Returns the appropriate port value for the given `source_url` depending on
436*6777b538SAndroid Build Coastguard Worker   // if the url is considered trustworthy or not.
437*6777b538SAndroid Build Coastguard Worker   //
438*6777b538SAndroid Build Coastguard Worker   // This function normally returns source_url.EffectiveIntPort(), but it can
439*6777b538SAndroid Build Coastguard Worker   // return a different port value if:
440*6777b538SAndroid Build Coastguard Worker   // * `source_url`'s scheme isn't cryptographically secure
441*6777b538SAndroid Build Coastguard Worker   // * `url_is_trustworthy` is true
442*6777b538SAndroid Build Coastguard Worker   // * `source_url`'s port is the default port for the scheme i.e.: 80
443*6777b538SAndroid Build Coastguard Worker   // If all these conditions are true then the returned value will be 443 to
444*6777b538SAndroid Build Coastguard Worker   // indicate that we're treating `source_url` as if it was secure.
445*6777b538SAndroid Build Coastguard Worker   static int GetAndAdjustPortForTrustworthyUrls(const GURL& source_url,
446*6777b538SAndroid Build Coastguard Worker                                                 bool url_is_trustworthy);
447*6777b538SAndroid Build Coastguard Worker 
448*6777b538SAndroid Build Coastguard Worker   // Checks for values that could be misinterpreted as a cookie name prefix.
449*6777b538SAndroid Build Coastguard Worker   static bool HasHiddenPrefixName(const std::string_view cookie_value);
450*6777b538SAndroid Build Coastguard Worker 
451*6777b538SAndroid Build Coastguard Worker   // Returns true iff the cookie is a partitioned cookie with a nonce or that
452*6777b538SAndroid Build Coastguard Worker   // does not violate the semantics of the Partitioned attribute:
453*6777b538SAndroid Build Coastguard Worker   // - Must have the Secure attribute OR the cookie partition contains a nonce.
454*6777b538SAndroid Build Coastguard Worker   static bool IsCookiePartitionedValid(const GURL& url,
455*6777b538SAndroid Build Coastguard Worker                                        const ParsedCookie& parsed_cookie,
456*6777b538SAndroid Build Coastguard Worker                                        bool partition_has_nonce);
457*6777b538SAndroid Build Coastguard Worker   static bool IsCookiePartitionedValid(const GURL& url,
458*6777b538SAndroid Build Coastguard Worker                                        bool secure,
459*6777b538SAndroid Build Coastguard Worker                                        bool is_partitioned,
460*6777b538SAndroid Build Coastguard Worker                                        bool partition_has_nonce);
461*6777b538SAndroid Build Coastguard Worker 
462*6777b538SAndroid Build Coastguard Worker   // CookieBase:
463*6777b538SAndroid Build Coastguard Worker   void PostIncludeForRequestURL(
464*6777b538SAndroid Build Coastguard Worker       const CookieAccessResult& access_result,
465*6777b538SAndroid Build Coastguard Worker       const CookieOptions& options_used,
466*6777b538SAndroid Build Coastguard Worker       CookieOptions::SameSiteCookieContext::ContextType
467*6777b538SAndroid Build Coastguard Worker           cookie_inclusion_context_used) const override;
468*6777b538SAndroid Build Coastguard Worker   void PostIsSetPermittedInContext(
469*6777b538SAndroid Build Coastguard Worker       const CookieAccessResult& access_result,
470*6777b538SAndroid Build Coastguard Worker       const CookieOptions& options_used) const override;
471*6777b538SAndroid Build Coastguard Worker 
472*6777b538SAndroid Build Coastguard Worker   // Keep defaults here in sync with
473*6777b538SAndroid Build Coastguard Worker   // services/network/public/interfaces/cookie_manager.mojom.
474*6777b538SAndroid Build Coastguard Worker   // These are the fields specific to CanonicalCookie. See CookieBase for other
475*6777b538SAndroid Build Coastguard Worker   // data fields.
476*6777b538SAndroid Build Coastguard Worker   std::string value_;
477*6777b538SAndroid Build Coastguard Worker   base::Time expiry_date_;
478*6777b538SAndroid Build Coastguard Worker   base::Time last_access_date_;
479*6777b538SAndroid Build Coastguard Worker   base::Time last_update_date_;
480*6777b538SAndroid Build Coastguard Worker   CookiePriority priority_{COOKIE_PRIORITY_MEDIUM};
481*6777b538SAndroid Build Coastguard Worker   CookieSourceType source_type_{CookieSourceType::kUnknown};
482*6777b538SAndroid Build Coastguard Worker };
483*6777b538SAndroid Build Coastguard Worker 
484*6777b538SAndroid Build Coastguard Worker // Used to pass excluded cookie information when it's possible that the
485*6777b538SAndroid Build Coastguard Worker // canonical cookie object may not be available.
486*6777b538SAndroid Build Coastguard Worker struct NET_EXPORT CookieAndLineWithAccessResult {
487*6777b538SAndroid Build Coastguard Worker   CookieAndLineWithAccessResult();
488*6777b538SAndroid Build Coastguard Worker   CookieAndLineWithAccessResult(std::optional<CanonicalCookie> cookie,
489*6777b538SAndroid Build Coastguard Worker                                 std::string cookie_string,
490*6777b538SAndroid Build Coastguard Worker                                 CookieAccessResult access_result);
491*6777b538SAndroid Build Coastguard Worker   CookieAndLineWithAccessResult(
492*6777b538SAndroid Build Coastguard Worker       const CookieAndLineWithAccessResult& cookie_and_line_with_access_result);
493*6777b538SAndroid Build Coastguard Worker 
494*6777b538SAndroid Build Coastguard Worker   CookieAndLineWithAccessResult& operator=(
495*6777b538SAndroid Build Coastguard Worker       const CookieAndLineWithAccessResult& cookie_and_line_with_access_result);
496*6777b538SAndroid Build Coastguard Worker 
497*6777b538SAndroid Build Coastguard Worker   CookieAndLineWithAccessResult(
498*6777b538SAndroid Build Coastguard Worker       CookieAndLineWithAccessResult&& cookie_and_line_with_access_result);
499*6777b538SAndroid Build Coastguard Worker 
500*6777b538SAndroid Build Coastguard Worker   ~CookieAndLineWithAccessResult();
501*6777b538SAndroid Build Coastguard Worker 
502*6777b538SAndroid Build Coastguard Worker   std::optional<CanonicalCookie> cookie;
503*6777b538SAndroid Build Coastguard Worker   std::string cookie_string;
504*6777b538SAndroid Build Coastguard Worker   CookieAccessResult access_result;
505*6777b538SAndroid Build Coastguard Worker };
506*6777b538SAndroid Build Coastguard Worker 
507*6777b538SAndroid Build Coastguard Worker struct CookieWithAccessResult {
508*6777b538SAndroid Build Coastguard Worker   CanonicalCookie cookie;
509*6777b538SAndroid Build Coastguard Worker   CookieAccessResult access_result;
510*6777b538SAndroid Build Coastguard Worker };
511*6777b538SAndroid Build Coastguard Worker 
512*6777b538SAndroid Build Coastguard Worker // Provided to allow gtest to create more helpful error messages, instead of
513*6777b538SAndroid Build Coastguard Worker // printing hex.
PrintTo(const CanonicalCookie & cc,std::ostream * os)514*6777b538SAndroid Build Coastguard Worker inline void PrintTo(const CanonicalCookie& cc, std::ostream* os) {
515*6777b538SAndroid Build Coastguard Worker   *os << "{ name=" << cc.Name() << ", value=" << cc.Value() << " }";
516*6777b538SAndroid Build Coastguard Worker }
PrintTo(const CookieWithAccessResult & cwar,std::ostream * os)517*6777b538SAndroid Build Coastguard Worker inline void PrintTo(const CookieWithAccessResult& cwar, std::ostream* os) {
518*6777b538SAndroid Build Coastguard Worker   *os << "{ ";
519*6777b538SAndroid Build Coastguard Worker   PrintTo(cwar.cookie, os);
520*6777b538SAndroid Build Coastguard Worker   *os << ", ";
521*6777b538SAndroid Build Coastguard Worker   PrintTo(cwar.access_result, os);
522*6777b538SAndroid Build Coastguard Worker   *os << " }";
523*6777b538SAndroid Build Coastguard Worker }
PrintTo(const CookieAndLineWithAccessResult & calwar,std::ostream * os)524*6777b538SAndroid Build Coastguard Worker inline void PrintTo(const CookieAndLineWithAccessResult& calwar,
525*6777b538SAndroid Build Coastguard Worker                     std::ostream* os) {
526*6777b538SAndroid Build Coastguard Worker   *os << "{ ";
527*6777b538SAndroid Build Coastguard Worker   if (calwar.cookie) {
528*6777b538SAndroid Build Coastguard Worker     PrintTo(*calwar.cookie, os);
529*6777b538SAndroid Build Coastguard Worker   } else {
530*6777b538SAndroid Build Coastguard Worker     *os << "nullopt";
531*6777b538SAndroid Build Coastguard Worker   }
532*6777b538SAndroid Build Coastguard Worker   *os << ", " << calwar.cookie_string << ", ";
533*6777b538SAndroid Build Coastguard Worker   PrintTo(calwar.access_result, os);
534*6777b538SAndroid Build Coastguard Worker   *os << " }";
535*6777b538SAndroid Build Coastguard Worker }
536*6777b538SAndroid Build Coastguard Worker 
537*6777b538SAndroid Build Coastguard Worker }  // namespace net
538*6777b538SAndroid Build Coastguard Worker 
539*6777b538SAndroid Build Coastguard Worker #endif  // NET_COOKIES_CANONICAL_COOKIE_H_
540