1 // Copyright 2019 The Chromium Authors. All rights reserved.
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 <string>
9 
10 #include "base/gtest_prod_util.h"
11 #include "base/macros.h"
12 #include "base/optional.h"
13 #include "base/values.h"
14 #include "net/base/net_export.h"
15 #include "url/origin.h"
16 
17 namespace network {
18 namespace mojom {
19 class NetworkIsolationKeyDataView;
20 }  // namespace mojom
21 }  // namespace network
22 
23 namespace mojo {
24 template <typename DataViewType, typename T>
25 struct StructTraits;
26 }  // namespace mojo
27 
28 namespace net {
29 
30 // Key used to isolate shared network stack resources used by requests based on
31 // the context on which they were made.
32 class NET_EXPORT NetworkIsolationKey {
33  public:
34   // Full constructor.  When a request is initiated by the top frame, it must
35   // also populate the |frame_origin| parameter when calling this constructor.
36   // Arguments can be either origins or schemeful sites.
37   NetworkIsolationKey(const url::Origin& top_frame_origin,
38                       const url::Origin& frame_origin);
39 
40   // Construct an empty key.
41   NetworkIsolationKey();
42 
43   NetworkIsolationKey(const NetworkIsolationKey& network_isolation_key);
44   NetworkIsolationKey(NetworkIsolationKey&& network_isolation_key);
45 
46   ~NetworkIsolationKey();
47 
48   NetworkIsolationKey& operator=(
49       const NetworkIsolationKey& network_isolation_key);
50   NetworkIsolationKey& operator=(NetworkIsolationKey&& network_isolation_key);
51 
52   // Creates a transient non-empty NetworkIsolationKey by creating an opaque
53   // origin. This prevents the NetworkIsolationKey from sharing data with other
54   // NetworkIsolationKeys. Data for transient NetworkIsolationKeys is not
55   // persisted to disk.
56   static NetworkIsolationKey CreateTransient();
57 
58   // Creates a non-empty NetworkIsolationKey with an opaque origin that is not
59   // considered transient. The returned NetworkIsolationKey will be cross-origin
60   // with all other keys and associated data is able to be persisted to disk.
61   static NetworkIsolationKey CreateOpaqueAndNonTransient();
62 
63   // Creates a new key using |top_frame_origin_| and |new_frame_origin|.
64   NetworkIsolationKey CreateWithNewFrameOrigin(
65       const url::Origin& new_frame_origin) const;
66 
67   // Intended for temporary use in locations that should be using a non-empty
68   // NetworkIsolationKey(), but are not yet. This both reduces the chance of
69   // accidentally copying the lack of a NIK where one should be used, and
70   // provides a reasonable way of locating callsites that need to have their
71   // NetworkIsolationKey filled in.
Todo()72   static NetworkIsolationKey Todo() { return NetworkIsolationKey(); }
73 
74   // Compare keys for equality, true if all enabled fields are equal.
75   bool operator==(const NetworkIsolationKey& other) const {
76     return std::tie(top_frame_site_, frame_site_, opaque_and_non_transient_) ==
77            std::tie(other.top_frame_site_, other.frame_site_,
78                     other.opaque_and_non_transient_);
79   }
80 
81   // Compare keys for inequality, true if any enabled field varies.
82   bool operator!=(const NetworkIsolationKey& other) const {
83     return !(*this == other);
84   }
85 
86   // Provide an ordering for keys based on all enabled fields.
87   bool operator<(const NetworkIsolationKey& other) const {
88     return std::tie(top_frame_site_, frame_site_, opaque_and_non_transient_) <
89            std::tie(other.top_frame_site_, other.frame_site_,
90                     other.opaque_and_non_transient_);
91   }
92 
93   // Returns the string representation of the key, which is the string
94   // representation of each piece of the key separated by spaces.
95   std::string ToString() const;
96 
97   // Returns string for debugging. Difference from ToString() is that transient
98   // entries may be distinguishable from each other.
99   std::string ToDebugString() const;
100 
101   // Returns true if all parts of the key are non-empty.
102   bool IsFullyPopulated() const;
103 
104   // Returns true if this key's lifetime is short-lived, or if
105   // IsFullyPopulated() returns true. It may not make sense to persist state to
106   // disk related to it (e.g., disk cache).
107   bool IsTransient() const;
108 
109   // Getters for the top frame and frame sites. These are actually scheme + site
110   // for HTTP/HTTPS origins, or original origins for other schemes and opaque
111   // origins. These accessors are primarily intended for IPC calls, and to be
112   // able to create an IsolationInfo from a NetworkIsolationKey.
GetTopFrameSite()113   const base::Optional<url::Origin>& GetTopFrameSite() const {
114     return top_frame_site_;
115   }
GetFrameSite()116   const base::Optional<url::Origin>& GetFrameSite() const {
117     return frame_site_;
118   }
119 
120   // Returns true if all parts of the key are empty.
121   bool IsEmpty() const;
122 
123   // Returns a representation of |this| as a base::Value. Returns false on
124   // failure. Succeeds if either IsEmpty() or !IsTransient().
125   bool ToValue(base::Value* out_value) const WARN_UNUSED_RESULT;
126 
127   // Inverse of ToValue(). Writes the result to |network_isolation_key|. Returns
128   // false on failure. Fails on values that could not have been produced by
129   // ToValue(), like transient origins. If the value of
130   // net::features::kAppendFrameOriginToNetworkIsolationKey has changed between
131   // saving and loading the data, fails.
132   static bool FromValue(const base::Value& value,
133                         NetworkIsolationKey* out_network_isolation_key)
134       WARN_UNUSED_RESULT;
135 
136  private:
137   // These classes need to be able to set |opaque_and_non_transient_|
138   friend class IsolationInfo;
139   friend struct mojo::StructTraits<network::mojom::NetworkIsolationKeyDataView,
140                                    net::NetworkIsolationKey>;
141 
142   NetworkIsolationKey(const url::Origin& top_frame_site,
143                       const url::Origin& frame_site,
144                       bool opaque_and_non_transient);
145 
146   bool IsOpaque() const;
147 
148   // Whether opaque origins cause the key to be transient. Always false, unless
149   // created with |CreateOpaqueAndNonTransient|.
150   bool opaque_and_non_transient_ = false;
151 
152   // Whether or not to use the |frame_site_| as part of the key.
153   bool use_frame_site_;
154 
155   // The origin/etld+1 of the top frame of the page making the request.
156   base::Optional<url::Origin> top_frame_site_;
157 
158   // The origin/etld+1 of the frame that initiates the request.
159   base::Optional<url::Origin> frame_site_;
160 };
161 
162 }  // namespace net
163 
164 #endif  // NET_BASE_NETWORK_ISOLATION_KEY_H_
165