• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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