xref: /aosp_15_r20/external/cronet/net/base/network_anonymization_key.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 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_NETWORK_ANONYMIZATION_KEY_H_
6 #define NET_BASE_NETWORK_ANONYMIZATION_KEY_H_
7 
8 #include <cstddef>
9 #include <optional>
10 #include <string>
11 #include <tuple>
12 
13 #include "base/unguessable_token.h"
14 #include "net/base/net_export.h"
15 #include "net/base/network_isolation_key.h"
16 #include "net/base/schemeful_site.h"
17 
18 namespace base {
19 class Value;
20 }
21 
22 namespace net {
23 
24 // NetworkAnonymizationKey will be used to partition shared network state based
25 // on the context on which they were made. This class is an expiremental key
26 // that contains properties that will be changed via feature flags.
27 
28 // NetworkAnonymizationKey contains the following properties:
29 
30 // `top_frame_site` represents the SchemefulSite of the pages top level frame.
31 // In order to separate first and third party context from each other this field
32 // will always be populated.
33 
34 // `is_cross_site` indicates whether the key is cross-site or same-site. A
35 // same-site key indicates that he schemeful site of the top frame and the frame
36 // are the same. Intermediary frames between the two may be cross-site to them.
37 // The effect of this property is to partition first-party and third-party
38 // resources within a given `top_frame_site`.
39 
40 // The following show how the `is_cross_site` boolean is populated for the
41 // innermost frame in the chain.
42 // a->a => is_cross_site = false
43 // a->b => is_cross_site = true
44 // a->b->a => is_cross_site = false
45 // a->(sandboxed a [has nonce]) => is_cross_site = true
46 
47 // The `nonce` value creates a key for anonymous iframes by giving them a
48 // temporary `nonce` value which changes per top level navigation. For now, any
49 // NetworkAnonymizationKey with a nonce will be considered transient. This is
50 // being considered to possibly change in the future in an effort to allow
51 // anonymous iframes with the same partition key access to shared resources.
52 // The nonce value will be empty except for anonymous iframes.
53 
54 // TODO @brgoldstein, add link to public documentation of key scheme naming
55 // conventions.
56 
57 class NET_EXPORT NetworkAnonymizationKey {
58  public:
59   // Construct an empty key.
60   NetworkAnonymizationKey();
61 
62   NetworkAnonymizationKey(
63       const NetworkAnonymizationKey& network_anonymization_key);
64   NetworkAnonymizationKey(NetworkAnonymizationKey&& network_anonymization_key);
65 
66   ~NetworkAnonymizationKey();
67 
68   NetworkAnonymizationKey& operator=(
69       const NetworkAnonymizationKey& network_anonymization_key);
70   NetworkAnonymizationKey& operator=(
71       NetworkAnonymizationKey&& network_anonymization_key);
72 
73   // Compare keys for equality, true if all enabled fields are equal.
74   bool operator==(const NetworkAnonymizationKey& other) const {
75     return std::tie(top_frame_site_, is_cross_site_, nonce_) ==
76            std::tie(other.top_frame_site_, other.is_cross_site_, other.nonce_);
77   }
78 
79   // Compare keys for inequality, true if any enabled field varies.
80   bool operator!=(const NetworkAnonymizationKey& other) const {
81     return !(*this == other);
82   }
83 
84   // Provide an ordering for keys based on all enabled fields.
85   bool operator<(const NetworkAnonymizationKey& other) const {
86     return std::tie(top_frame_site_, is_cross_site_, nonce_) <
87            std::tie(other.top_frame_site_, other.is_cross_site_, other.nonce_);
88   }
89 
90   // Create a `NetworkAnonymizationKey` from a `top_frame_site`, assuming it is
91   // same-site (see comment on the class, above) and has no nonce.
CreateSameSite(const SchemefulSite & top_frame_site)92   static NetworkAnonymizationKey CreateSameSite(
93       const SchemefulSite& top_frame_site) {
94     return NetworkAnonymizationKey(top_frame_site, false, std::nullopt);
95   }
96 
97   // Create a `NetworkAnonymizationKey` from a `top_frame_site`, assuming it is
98   // cross-site (see comment on the class, above) and has no nonce.
CreateCrossSite(const SchemefulSite & top_frame_site)99   static NetworkAnonymizationKey CreateCrossSite(
100       const SchemefulSite& top_frame_site) {
101     return NetworkAnonymizationKey(top_frame_site, true, std::nullopt);
102   }
103 
104   // Create a `NetworkAnonymizationKey` from a `top_frame_site` and
105   // `frame_site`. This calculates is_cross_site on the basis of those two
106   // sites.
107   static NetworkAnonymizationKey CreateFromFrameSite(
108       const SchemefulSite& top_frame_site,
109       const SchemefulSite& frame_site,
110       std::optional<base::UnguessableToken> nonce = std::nullopt);
111 
112   // Creates a `NetworkAnonymizationKey` from a `NetworkIsolationKey`. This is
113   // possible because a `NetworkIsolationKey` must always be more granular
114   // than a `NetworkAnonymizationKey`.
115   static NetworkAnonymizationKey CreateFromNetworkIsolationKey(
116       const net::NetworkIsolationKey& network_isolation_key);
117 
118   // Creates a `NetworkAnonymizationKey` from its constituent parts. This
119   // is intended to be used to build a NAK from Mojo, and for tests.
120   static NetworkAnonymizationKey CreateFromParts(
121       const SchemefulSite& top_frame_site,
122       bool is_cross_site,
123       std::optional<base::UnguessableToken> nonce = std::nullopt) {
124     return NetworkAnonymizationKey(top_frame_site, is_cross_site, nonce);
125   }
126 
127   // Creates a transient non-empty NetworkAnonymizationKey by creating an opaque
128   // origin. This prevents the NetworkAnonymizationKey from sharing data with
129   // other NetworkAnonymizationKey.
130   static NetworkAnonymizationKey CreateTransient();
131 
132   // Returns the string representation of the key.
133   std::string ToDebugString() const;
134 
135   // Returns true if all parts of the key are empty.
136   bool IsEmpty() const;
137 
138   // Returns true if `top_frame_site_` is non-empty.
139   bool IsFullyPopulated() const;
140 
141   // Returns true if this key's lifetime is short-lived. It may not make sense
142   // to persist state to disk related to it (e.g., disk cache).
143   // A NetworkAnonymizationKey will be considered transient if
144   // `top_frame_site_` is empty or opaque or if the key has a `nonce_`.
145   bool IsTransient() const;
146 
147   // Getters for the top frame, frame site, nonce and is cross site flag.
GetTopFrameSite()148   const std::optional<SchemefulSite>& GetTopFrameSite() const {
149     return top_frame_site_;
150   }
151 
IsCrossSite()152   bool IsCrossSite() const { return is_cross_site_; }
153 
IsSameSite()154   bool IsSameSite() const { return !IsCrossSite(); }
155 
GetNonce()156   const std::optional<base::UnguessableToken>& GetNonce() const {
157     return nonce_;
158   }
159 
160   // Returns a representation of |this| as a base::Value. Returns false on
161   // failure. Succeeds if either IsEmpty() or !IsTransient().
162   [[nodiscard]] bool ToValue(base::Value* out_value) const;
163 
164   // Inverse of ToValue(). Writes the result to |network_anonymization_key|.
165   // Returns false on failure. Fails on values that could not have been produced
166   // by ToValue(), like transient origins.
167   [[nodiscard]] static bool FromValue(
168       const base::Value& value,
169       NetworkAnonymizationKey* out_network_anonymization_key);
170 
171   // Determine whether network state partitioning is enabled. This is true if
172   // any of the features
173   //
174   // * `SplitHostCacheByNetworkIsolationKey`
175   // * `PartitionConnectionsByNetworkIsolationKey`
176   // * `PartitionHttpServerPropertiesByNetworkIsolationKey`
177   // * `PartitionSSLSessionsByNetworkIsolationKey`
178   // * `PartitionNelAndReportingByNetworkIsolationKey`
179   //
180   // is enabled, or if `PartitionByDefault()` has been called.
181   static bool IsPartitioningEnabled();
182 
183   // Default partitioning to enabled, regardless of feature settings. This must
184   // be called before any calls to `IsPartitioningEnabled()`.
185   static void PartitionByDefault();
186 
187   // Clear partitioning-related globals.
188   static void ClearGlobalsForTesting();
189 
190  private:
191   NetworkAnonymizationKey(
192       const SchemefulSite& top_frame_site,
193       bool is_cross_site,
194       std::optional<base::UnguessableToken> nonce = std::nullopt);
195 
196   std::string GetSiteDebugString(
197       const std::optional<SchemefulSite>& site) const;
198 
199   static std::optional<std::string> SerializeSiteWithNonce(
200       const SchemefulSite& site);
201 
202   // The origin/etld+1 of the top frame of the page making the request. This
203   // will always be populated unless all other fields are also nullopt.
204   std::optional<SchemefulSite> top_frame_site_;
205 
206   // True if the frame site is cross site when compared to the top frame site.
207   // This is always false for a non-fully-populated NAK.
208   bool is_cross_site_;
209 
210   // for non-opaque origins.
211   std::optional<base::UnguessableToken> nonce_;
212 };
213 
214 }  // namespace net
215 
216 #endif  // NET_BASE_NETWORK_ANONYMIZATION_KEY_H_
217