File: cookie_base.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (261 lines) | stat: -rw-r--r-- 11,928 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
// Copyright 2024 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_COOKIE_BASE_H_
#define NET_COOKIES_COOKIE_BASE_H_

#include <optional>
#include <string>
#include <tuple>

#include "base/types/pass_key.h"
#include "net/base/net_export.h"
#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_partition_key.h"

class GURL;

namespace net {

class RefUniqueCookieKey;
class UniqueCookieKey;

struct CookieAccessParams;
struct CookieAccessResult;

// A base class for cookies and cookie-like objects. Encapsulates logic for
// determining whether a cookie could be sent/set, based on its attributes and
// the request context.
class NET_EXPORT CookieBase {
 public:
  // 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
  // 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 std::optional<CookieAccessResult>& cookie_access_result =
          std::nullopt) const;

  // 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;

  const std::string& Name() const { return name_; }
  // 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_; }
  bool SecureAttribute() const { return secure_; }
  bool IsHttpOnly() const { return httponly_; }
  CookieSameSite SameSite() const { return same_site_; }

  // Returns true if this cookie can only be accessed in a secure context.
  bool IsSecure() const;

  bool IsPartitioned() const { return partition_key_.has_value(); }
  const std::optional<CookiePartitionKey>& PartitionKey() const {
    return partition_key_;
  }

  // Returns whether this cookie is Partitioned and its partition key matches a
  // a same-site context by checking if the cookies domain site is the same as
  // the partition key's site.
  // This function should not be used for third-party cookie blocking
  // enforcement-related decisions. That logic should rely on `IsPartitioned`.
  // These functions are for recording metrics about partitioned cookie usage.
  // Returns false if the cookie has no partition key.
  bool IsFirstPartyPartitioned() const;

  // Returns whether the cookie is partitioned in a third-party context.
  // This function should not be used for third-party cookie blocking
  // enforcement-related decisions. That logic should rely on `IsPartitioned`.
  // These functions are for recording metrics about partitioned cookie usage.
  // Returns false if the cookie has no partition key.
  bool IsThirdPartyPartitioned() const;

  // 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;

  // StrictlyUniqueKey always includes the cookie's source scheme and source
  // port.
  UniqueCookieKey StrictlyUniqueKey() const;

  // 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.
  // The source_scheme and source_port fields depend on whether or not their
  // associated features are enabled.
  UniqueCookieKey UniqueKey() const;

  // Returns a non-owning key such that two cookies with the same RefUniqueKey()
  // are guaranteed to be equivalent in the sense of IsEquivalent().
  // The `partition_key_` field will always be nullopt when partitioned cookies
  // are not enabled.
  // The source_scheme and source_port fields depend on whether or not their
  // associated features are enabled.
  // A RefUniqueKey keeps references that point to data in the CookieBase, so it
  // must not be stored beyond the lifetime of the CookieBase.
  RefUniqueCookieKey RefUniqueKey() const;

  // Same as UniqueKey() except it does not contain a source_port or
  // source_scheme field. For use for determining aliasing cookies, which do not
  // consider the source_port or source_scheme.
  UniqueCookieKey LegacyUniqueKey() const;

  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 SetCreationDate(const base::Time& date) { creation_date_ = date; }

 protected:
  CookieBase();
  CookieBase(const CookieBase& other);
  CookieBase(CookieBase&& other);
  CookieBase& operator=(const CookieBase& other);
  CookieBase& operator=(CookieBase&& other);
  virtual ~CookieBase();

  CookieBase(std::string name,
             std::string domain,
             std::string path,
             base::Time creation,
             bool secure,
             bool httponly,
             CookieSameSite same_site,
             std::optional<CookiePartitionKey> partition_key,
             CookieSourceScheme source_scheme = CookieSourceScheme::kUnset,
             int source_port = url::PORT_UNSPECIFIED);

  // 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;

  // Returns the threshold age for lax-allow-unsafe behavior, below which the
  // effective SameSite behavior for a cookie that does not specify SameSite is
  // lax-allow-unsafe, and above which the effective SameSite is just lax.
  // Lax-allow-unsafe behavior (a.k.a. Lax+POST) is a temporary mitigation for
  // compatibility reasons that allows a cookie which doesn't specify SameSite
  // to still be sent on non-safe requests like POST requests for a short amount
  // of time after creation, despite the default enforcement for most (i.e.
  // older) SameSite-unspecified cookies being Lax. Implementations should
  // override this method if they want to enable Lax-allow-unsafe behavior; by
  // default, this method returns base::TimeDelta::Min(), i.e. no cookies will
  // ever be lax-allow-unsafe.
  virtual base::TimeDelta GetLaxAllowUnsafeThresholdAge() const;

  // Returns whether the cookie was created at most |age_threshold| ago.
  bool IsRecentlyCreated(base::TimeDelta age_threshold) const;

  // Checks if `port` is within [0,65535] or url::PORT_UNSPECIFIED. Returns
  // `port` if so and url::PORT_INVALID otherwise.
  static int ValidateAndAdjustSourcePort(int port);

 private:
  // Allows subclasses to add custom logic for e.g. logging metrics. Called
  // after inclusion has been determined for the respective access.
  virtual void PostIncludeForRequestURL(
      const CookieAccessResult& access_result,
      const CookieOptions& options_used,
      CookieOptions::SameSiteCookieContext::ContextType
          cookie_inclusion_context_used) const {}
  virtual void PostIsSetPermittedInContext(
      const CookieAccessResult& access_result,
      const CookieOptions& options_used) const {}

  // Keep defaults here in sync with
  // services/network/public/interfaces/cookie_manager.mojom.
  std::string name_;
  std::string domain_;
  std::string path_;
  base::Time creation_date_;
  bool secure_{false};
  bool httponly_{false};
  CookieSameSite same_site_{CookieSameSite::NO_RESTRICTION};
  // This will be std::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.
  std::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};
};

}  // namespace net

#endif  // NET_COOKIES_COOKIE_BASE_H_