1 // Copyright 2019 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_ISOLATION_KEY_H_ 6 #define NET_BASE_NETWORK_ISOLATION_KEY_H_ 7 8 #include <optional> 9 #include <string> 10 11 #include "base/types/pass_key.h" 12 #include "base/unguessable_token.h" 13 #include "net/base/net_export.h" 14 #include "net/base/schemeful_site.h" 15 16 namespace network::mojom { 17 class NonEmptyNetworkIsolationKeyDataView; 18 } 19 20 namespace net { 21 class CookiePartitionKey; 22 class NetworkAnonymizationKey; 23 } 24 25 namespace net { 26 27 // NetworkIsolationKey (NIK) is used to partition shared network state based on 28 // the context in which the requests were made. It is used to divide the HTTP 29 // cache, while the NetworkAnonymizationKey is used for most other network 30 // state. 31 // 32 // The NetworkIsolationKey uses the "triple-key" scheme to partition the HTTP 33 // cache. The key has the following properties: 34 // `top_frame_site` -> the schemeful site of the top level page. 35 // `frame_site ` -> the schemeful site of the frame. 36 class NET_EXPORT NetworkIsolationKey { 37 public: 38 // Full constructor. When a request is initiated by the top frame, it must 39 // also populate the |frame_site| parameter when calling this constructor. 40 NetworkIsolationKey( 41 const SchemefulSite& top_frame_site, 42 const SchemefulSite& frame_site, 43 const std::optional<base::UnguessableToken>& nonce = std::nullopt); 44 45 // Alternative constructor that takes ownership of arguments, to save copies. 46 NetworkIsolationKey( 47 SchemefulSite&& top_frame_site, 48 SchemefulSite&& frame_site, 49 std::optional<base::UnguessableToken>&& nonce = std::nullopt); 50 51 // Construct an empty key. 52 NetworkIsolationKey(); 53 54 NetworkIsolationKey(const NetworkIsolationKey& network_isolation_key); 55 NetworkIsolationKey(NetworkIsolationKey&& network_isolation_key); 56 57 ~NetworkIsolationKey(); 58 59 NetworkIsolationKey& operator=( 60 const NetworkIsolationKey& network_isolation_key); 61 NetworkIsolationKey& operator=(NetworkIsolationKey&& network_isolation_key); 62 63 // Creates a transient non-empty NetworkIsolationKey by creating an opaque 64 // origin. This prevents the NetworkIsolationKey from sharing data with other 65 // NetworkIsolationKeys. Data for transient NetworkIsolationKeys is not 66 // persisted to disk. 67 static NetworkIsolationKey CreateTransientForTesting(); 68 69 // Creates a new key using |top_frame_site_| and |new_frame_site|. 70 NetworkIsolationKey CreateWithNewFrameSite( 71 const SchemefulSite& new_frame_site) const; 72 73 // Compare keys for equality, true if all enabled fields are equal. 74 bool operator==(const NetworkIsolationKey& other) const { 75 return std::tie(top_frame_site_, frame_site_, nonce_) == 76 std::tie(other.top_frame_site_, other.frame_site_, other.nonce_); 77 } 78 79 // Compare keys for inequality, true if any enabled field varies. 80 bool operator!=(const NetworkIsolationKey& other) const { 81 return !(*this == other); 82 } 83 84 // Provide an ordering for keys based on all enabled fields. 85 bool operator<(const NetworkIsolationKey& other) const { 86 return std::tie(top_frame_site_, frame_site_, nonce_) < 87 std::tie(other.top_frame_site_, other.frame_site_, other.nonce_); 88 } 89 90 // Returns the string representation of the key for use in string-keyed disk 91 // cache. This is the string representation of each piece of the key separated 92 // by spaces. Returns nullopt if the network isolation key is transient, in 93 // which case, nothing should typically be saved to disk using the key. 94 std::optional<std::string> ToCacheKeyString() const; 95 96 // Returns string for debugging. Difference from ToString() is that transient 97 // entries may be distinguishable from each other. 98 std::string ToDebugString() const; 99 100 // Returns true if all parts of the key are non-empty. 101 bool IsFullyPopulated() const; 102 103 // Returns true if this key's lifetime is short-lived, or if 104 // IsFullyPopulated() returns true. It may not make sense to persist state to 105 // disk related to it (e.g., disk cache). 106 bool IsTransient() const; 107 108 // Getters for the top frame and frame sites. These accessors are primarily 109 // intended for IPC calls, and to be able to create an IsolationInfo from a 110 // NetworkIsolationKey. GetTopFrameSite()111 const std::optional<SchemefulSite>& GetTopFrameSite() const { 112 return top_frame_site_; 113 } 114 115 // Do not use outside of testing. Returns the `frame_site_`. GetFrameSiteForTesting()116 const std::optional<SchemefulSite> GetFrameSiteForTesting() const { 117 return frame_site_; 118 } 119 120 // When serializing a NIK for sending via mojo we want to access the frame 121 // site directly. We don't want to expose this broadly, though, hence the 122 // passkey. 123 using SerializationPassKey = base::PassKey<struct mojo::StructTraits< 124 network::mojom::NonEmptyNetworkIsolationKeyDataView, 125 NetworkIsolationKey>>; GetFrameSiteForSerialization(SerializationPassKey)126 const std::optional<SchemefulSite>& GetFrameSiteForSerialization( 127 SerializationPassKey) const { 128 CHECK(!IsEmpty()); 129 return frame_site_; 130 } 131 // We also need to access the frame site directly when constructing 132 // CookiePartitionKey for nonced partitions. We also use a passkey for this 133 // case. 134 using CookiePartitionKeyPassKey = base::PassKey<CookiePartitionKey>; GetFrameSiteForCookiePartitionKey(CookiePartitionKeyPassKey)135 const std::optional<SchemefulSite>& GetFrameSiteForCookiePartitionKey( 136 CookiePartitionKeyPassKey) const { 137 CHECK(!IsEmpty()); 138 return frame_site_; 139 } 140 // Same as above but for constructing a `NetworkAnonymizationKey()` from this 141 // NIK. 142 using NetworkAnonymizationKeyPassKey = base::PassKey<NetworkAnonymizationKey>; GetFrameSiteForNetworkAnonymizationKey(NetworkAnonymizationKeyPassKey)143 const std::optional<SchemefulSite>& GetFrameSiteForNetworkAnonymizationKey( 144 NetworkAnonymizationKeyPassKey) const { 145 CHECK(!IsEmpty()); 146 return frame_site_; 147 } 148 149 // Getter for the nonce. GetNonce()150 const std::optional<base::UnguessableToken>& GetNonce() const { 151 return nonce_; 152 } 153 154 // Returns true if all parts of the key are empty. 155 bool IsEmpty() const; 156 157 private: 158 // Whether this key has opaque origins or a nonce. 159 bool IsOpaque() const; 160 161 // The origin/etld+1 of the top frame of the page making the request. 162 std::optional<SchemefulSite> top_frame_site_; 163 164 // The origin/etld+1 of the frame that initiates the request. 165 std::optional<SchemefulSite> frame_site_; 166 167 // Having a nonce is a way to force a transient opaque `NetworkIsolationKey` 168 // for non-opaque origins. 169 std::optional<base::UnguessableToken> nonce_; 170 }; 171 172 NET_EXPORT std::ostream& operator<<(std::ostream& os, 173 const NetworkIsolationKey& nak); 174 175 } // namespace net 176 177 #endif // NET_BASE_NETWORK_ISOLATION_KEY_H_ 178