xref: /aosp_15_r20/external/cronet/net/base/schemeful_site.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2020 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_BASE_SCHEMEFUL_SITE_H_
6 #define NET_BASE_SCHEMEFUL_SITE_H_
7 
8 #include <optional>
9 #include <ostream>
10 #include <string>
11 
12 #include "base/gtest_prod_util.h"
13 #include "base/types/pass_key.h"
14 #include "net/base/net_export.h"
15 #include "url/origin.h"
16 
17 class GURL;
18 
19 namespace blink {
20 class BlinkSchemefulSite;
21 class StorageKey;
22 }  // namespace blink
23 
24 namespace IPC {
25 template <class P>
26 struct ParamTraits;
27 }  // namespace IPC
28 
29 namespace network::mojom {
30 class SchemefulSiteDataView;
31 }  // namespace network::mojom
32 
33 namespace mojo {
34 template <typename DataViewType, typename T>
35 struct StructTraits;
36 }  // namespace mojo
37 
38 namespace net {
39 
40 class NetworkAnonymizationKey;
41 class SiteForCookies;
42 
43 // Class which represents a scheme and etld+1 for an origin, as specified by
44 // https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site.
45 //
46 // A SchemefulSite is obtained from an input origin by normalizing, such that:
47 // 1. Opaque origins have distinct SchemefulSites.
48 // 2. Origins whose schemes have network hosts have the same SchemefulSite iff
49 //    they share a scheme, and share a hostname or registrable domain. Origins
50 //    whose schemes have network hosts include http, https, ws, wss, file, etc.
51 // 3. Origins whose schemes do not have a network host have the same
52 //    SchemefulSite iff they share a scheme and host.
53 // 4. Origins which differ only by port have the same SchemefulSite.
54 // 5. Websocket origins cannot have a SchemefulSite (they trigger a DCHECK).
55 //
56 // Note that blink::BlinkSchemefulSite mirrors this class and needs to be kept
57 // in sync with any data member changes.
58 class NET_EXPORT SchemefulSite {
59  public:
60   SchemefulSite() = default;
61 
62   // The passed `origin` may not match the resulting internal representation in
63   // certain circumstances. See the comment, below, on the `site_as_origin_`
64   // member.
65   explicit SchemefulSite(const url::Origin& origin);
66 
67   // Using the origin constructor is preferred as this is less efficient.
68   // Should only be used if the origin for a given GURL is not readily
69   // available.
70   explicit SchemefulSite(const GURL& url);
71 
72   SchemefulSite(const SchemefulSite& other);
73   SchemefulSite(SchemefulSite&& other) noexcept;
74 
75   SchemefulSite& operator=(const SchemefulSite& other);
76   SchemefulSite& operator=(SchemefulSite&& other) noexcept;
77 
78   // Tries to construct an instance from a (potentially untrusted) value of the
79   // internal `site_as_origin_` that got received over an RPC.
80   //
81   // Returns whether successful or not. Doesn't touch |*out| if false is
82   // returned.  This returning |true| does not mean that whoever sent the values
83   // did not lie, merely that they are well-formed.
84   static bool FromWire(const url::Origin& site_as_origin, SchemefulSite* out);
85 
86   // Creates a SchemefulSite iff the passed-in origin has a registerable domain.
87   static std::optional<SchemefulSite> CreateIfHasRegisterableDomain(
88       const url::Origin&);
89 
90   // If the scheme is ws or wss, it is converted to http or https, respectively.
91   // Has no effect on SchemefulSites with any other schemes.
92   //
93   // See Step 1 of algorithm "establish a WebSocket connection" in
94   // https://fetch.spec.whatwg.org/#websocket-opening-handshake.
95   void ConvertWebSocketToHttp();
96 
97   // Deserializes a string obtained from `Serialize()` to a `SchemefulSite`.
98   // Returns an opaque `SchemefulSite` if the value was invalid in any way.
99   static SchemefulSite Deserialize(const std::string& value);
100 
101   // Returns a serialized version of `site_as_origin_`. If the underlying origin
102   // is invalid, returns an empty string. If serialization of opaque origins
103   // with their associated nonce is necessary, see `SerializeWithNonce()`.
104   std::string Serialize() const;
105 
106   // Serializes `site_as_origin_` in cases when it has a 'file' scheme but
107   // we want to preserve the Origin's host.
108   // This was added to serialize cookie partition keys, which may contain
109   // file origins with a host.
110   std::string SerializeFileSiteWithHost() const;
111 
112   std::string GetDebugString() const;
113 
114   // Gets the underlying site as a GURL. If the internal Origin is opaque,
115   // returns an empty GURL.
116   GURL GetURL() const;
117 
118   // Deserializes a string obtained from `SerializeWithNonce()` to a
119   // `SchemefulSite`. Returns nullopt if the value was invalid in any way.
120   static std::optional<SchemefulSite> DeserializeWithNonce(
121       base::PassKey<NetworkAnonymizationKey>,
122       const std::string& value);
123 
124   // Returns a serialized version of `site_as_origin_`. For an opaque
125   // `site_as_origin_`, this serializes with the nonce.  See
126   // `url::origin::SerializeWithNonce()` for usage information.
127   std::optional<std::string> SerializeWithNonce(
128       base::PassKey<NetworkAnonymizationKey>);
129 
opaque()130   bool opaque() const { return site_as_origin_.opaque(); }
131 
has_registrable_domain_or_host()132   bool has_registrable_domain_or_host() const {
133     return !registrable_domain_or_host().empty();
134   }
135 
136   // Testing only function which allows tests to access the underlying
137   // `site_as_origin_` in order to verify behavior.
138   const url::Origin& GetInternalOriginForTesting() const;
139 
140   // Testing-only function which allows access to the private
141   // `registrable_domain_or_host` method.
registrable_domain_or_host_for_testing()142   std::string registrable_domain_or_host_for_testing() const {
143     return registrable_domain_or_host();
144   }
145 
146   // Estimates dynamic memory usage.
147   // See base/trace_event/memory_usage_estimator.h for more info.
148   size_t EstimateMemoryUsage() const;
149 
150   bool operator==(const SchemefulSite& other) const;
151 
152   bool operator!=(const SchemefulSite& other) const;
153 
154   bool operator<(const SchemefulSite& other) const;
155 
156  private:
157   // IPC serialization code needs to access internal origin.
158   friend struct mojo::StructTraits<network::mojom::SchemefulSiteDataView,
159                                    SchemefulSite>;
160   friend struct IPC::ParamTraits<net::SchemefulSite>;
161 
162   friend class blink::BlinkSchemefulSite;
163 
164   // Create SiteForCookies from SchemefulSite needs to access internal origin,
165   // and SiteForCookies needs to access private method SchemelesslyEqual.
166   friend class SiteForCookies;
167 
168   // Needed to create a bogus origin from a site.
169   // TODO(https://crbug.com/1148927): Give IsolationInfos empty origins instead,
170   // in this case, and unfriend IsolationInfo.
171   friend class IsolationInfo;
172 
173   // Needed to create a bogus origin from a site.
174   friend class URLRequest;
175 
176   // Needed for access to nonce for serialization.
177   friend class blink::StorageKey;
178 
179   FRIEND_TEST_ALL_PREFIXES(SchemefulSiteTest, OpaqueSerialization);
180   FRIEND_TEST_ALL_PREFIXES(SchemefulSiteTest, InternalValue);
181 
182   struct ObtainASiteResult {
183     url::Origin origin;
184     bool used_registerable_domain;
185   };
186 
187   static ObtainASiteResult ObtainASite(const url::Origin&);
188 
189   explicit SchemefulSite(ObtainASiteResult);
190 
191   // Deserializes a string obtained from `SerializeWithNonce()` to a
192   // `SchemefulSite`. Returns nullopt if the value was invalid in any way.
193   static std::optional<SchemefulSite> DeserializeWithNonce(
194       const std::string& value);
195 
196   // Returns a serialized version of `site_as_origin_`. For an opaque
197   // `site_as_origin_`, this serializes with the nonce.  See
198   // `url::origin::SerializeWithNonce()` for usage information.
199   std::optional<std::string> SerializeWithNonce();
200 
201   // Returns whether `this` and `other` share a host or registrable domain.
202   // Should NOT be used to check equality or equivalence. This is only used
203   // for legacy same-site cookie logic that does not check schemes. Private to
204   // restrict usage.
205   bool SchemelesslyEqual(const SchemefulSite& other) const;
206 
207   // Returns the host of the underlying `origin`, which will usually be the
208   // registrable domain. This is private because if it were public, it would
209   // trivially allow circumvention of the "Schemeful"-ness of this class.
210   std::string registrable_domain_or_host() const {
211     return site_as_origin_.host();
212   }
213 
214   // This should not be used casually, it's an opaque Origin or an scheme+eTLD+1
215   // packed into an Origin. If you extract this value SchemefulSite is not
216   // responsible for any unexpected friction you might encounter.
217   const url::Origin& internal_value() const { return site_as_origin_; }
218 
219   // Origin which stores the result of running the steps documented at
220   // https://html.spec.whatwg.org/multipage/origin.html#obtain-a-site.
221   // This is not an arbitrary origin. It must either be an opaque origin, or a
222   // scheme + eTLD+1 + default port.
223   //
224   // The `origin` passed into the SchemefulSite(const url::Origin&) constructor
225   // might not match this internal representation used by this class to track
226   // the scheme and eTLD+1 representing a schemeful site. This may be the case
227   // if, e.g., the passed `origin` has an eTLD+1 that is not equal to its
228   // hostname, or if the port number is not the default port for its scheme.
229   //
230   // In general, this `site_as_origin_` used for the internal representation
231   // should NOT be used directly by SchemefulSite consumers.
232   url::Origin site_as_origin_;
233 };
234 
235 // Provided to allow gtest to create more helpful error messages, instead of
236 // printing hex.
237 //
238 // Also used so that SchemefulSites can be the arguments of DCHECK_EQ.
239 NET_EXPORT std::ostream& operator<<(std::ostream& os, const SchemefulSite& ss);
240 
241 }  // namespace net
242 
243 #endif  // NET_BASE_SCHEMEFUL_SITE_H_
244