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