xref: /aosp_15_r20/external/cronet/net/base/network_isolation_key.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #include "net/base/network_isolation_key.h"
6 
7 #include <cstddef>
8 #include <optional>
9 #include <string>
10 
11 #include "base/unguessable_token.h"
12 #include "net/base/features.h"
13 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
14 #include "schemeful_site.h"
15 #include "url/gurl.h"
16 #include "url/origin.h"
17 #include "url/url_constants.h"
18 
19 namespace net {
20 
21 namespace {
22 
GetSiteDebugString(const std::optional<SchemefulSite> & site)23 std::string GetSiteDebugString(const std::optional<SchemefulSite>& site) {
24   return site ? site->GetDebugString() : "null";
25 }
26 
27 }  // namespace
28 
NetworkIsolationKey(const SchemefulSite & top_frame_site,const SchemefulSite & frame_site,const std::optional<base::UnguessableToken> & nonce)29 NetworkIsolationKey::NetworkIsolationKey(
30     const SchemefulSite& top_frame_site,
31     const SchemefulSite& frame_site,
32     const std::optional<base::UnguessableToken>& nonce)
33     : NetworkIsolationKey(SchemefulSite(top_frame_site),
34                           SchemefulSite(frame_site),
35                           std::optional<base::UnguessableToken>(nonce)) {}
36 
NetworkIsolationKey(SchemefulSite && top_frame_site,SchemefulSite && frame_site,std::optional<base::UnguessableToken> && nonce)37 NetworkIsolationKey::NetworkIsolationKey(
38     SchemefulSite&& top_frame_site,
39     SchemefulSite&& frame_site,
40     std::optional<base::UnguessableToken>&& nonce)
41     : top_frame_site_(std::move(top_frame_site)),
42       frame_site_(std::make_optional(std::move(frame_site))),
43       is_cross_site_((GetMode() == Mode::kCrossSiteFlagEnabled)
44                          ? std::make_optional(*top_frame_site_ != *frame_site_)
45                          : std::nullopt),
46       nonce_(std::move(nonce)) {
47   DCHECK(!nonce_ || !nonce_->is_empty());
48 }
49 
NetworkIsolationKey(const url::Origin & top_frame_origin,const url::Origin & frame_origin)50 NetworkIsolationKey::NetworkIsolationKey(const url::Origin& top_frame_origin,
51                                          const url::Origin& frame_origin)
52     : NetworkIsolationKey(SchemefulSite(top_frame_origin),
53                           SchemefulSite(frame_origin)) {}
54 
55 NetworkIsolationKey::NetworkIsolationKey() = default;
56 
57 NetworkIsolationKey::NetworkIsolationKey(
58     const NetworkIsolationKey& network_isolation_key) = default;
59 
60 NetworkIsolationKey::NetworkIsolationKey(
61     NetworkIsolationKey&& network_isolation_key) = default;
62 
63 NetworkIsolationKey::~NetworkIsolationKey() = default;
64 
65 NetworkIsolationKey& NetworkIsolationKey::operator=(
66     const NetworkIsolationKey& network_isolation_key) = default;
67 
68 NetworkIsolationKey& NetworkIsolationKey::operator=(
69     NetworkIsolationKey&& network_isolation_key) = default;
70 
CreateTransientForTesting()71 NetworkIsolationKey NetworkIsolationKey::CreateTransientForTesting() {
72   SchemefulSite site_with_opaque_origin;
73   return NetworkIsolationKey(site_with_opaque_origin, site_with_opaque_origin);
74 }
75 
CreateWithNewFrameSite(const SchemefulSite & new_frame_site) const76 NetworkIsolationKey NetworkIsolationKey::CreateWithNewFrameSite(
77     const SchemefulSite& new_frame_site) const {
78   if (!top_frame_site_)
79     return NetworkIsolationKey();
80   return NetworkIsolationKey(top_frame_site_.value(), new_frame_site, nonce_);
81 }
82 
ToCacheKeyString() const83 std::optional<std::string> NetworkIsolationKey::ToCacheKeyString() const {
84   if (IsTransient())
85     return std::nullopt;
86 
87   std::string variable_key_piece;
88   switch (GetMode()) {
89     case Mode::kFrameSiteEnabled:
90       variable_key_piece = frame_site_->Serialize();
91       break;
92     case Mode::kFrameSiteWithSharedOpaqueEnabled:
93       if (frame_site_->opaque()) {
94         variable_key_piece = "_opaque";
95         break;
96       }
97       variable_key_piece = frame_site_->Serialize();
98       break;
99     case Mode::kCrossSiteFlagEnabled:
100       variable_key_piece = (*is_cross_site_ ? "_1" : "_0");
101       break;
102   }
103   return top_frame_site_->Serialize() + " " + variable_key_piece;
104 }
105 
ToDebugString() const106 std::string NetworkIsolationKey::ToDebugString() const {
107   // The space-separated serialization of |top_frame_site_| and
108   // |frame_site_|.
109   std::string return_string = GetSiteDebugString(top_frame_site_);
110   switch (GetMode()) {
111     case Mode::kFrameSiteEnabled:
112       return_string += " " + GetSiteDebugString(frame_site_);
113       break;
114     case Mode::kFrameSiteWithSharedOpaqueEnabled:
115       if (frame_site_ && frame_site_->opaque()) {
116         return_string += " opaque-origin";
117         break;
118       }
119       return_string += " " + GetSiteDebugString(frame_site_);
120       break;
121     case Mode::kCrossSiteFlagEnabled:
122       if (is_cross_site_.has_value()) {
123         return_string += (*is_cross_site_ ? " cross-site" : " same-site");
124       }
125       break;
126   }
127 
128   if (nonce_.has_value()) {
129     return_string += " (with nonce " + nonce_->ToString() + ")";
130   }
131 
132   return return_string;
133 }
134 
IsFullyPopulated() const135 bool NetworkIsolationKey::IsFullyPopulated() const {
136   if (!top_frame_site_.has_value()) {
137     return false;
138   }
139   if (GetMode() == Mode::kFrameSiteEnabled && !frame_site_.has_value()) {
140     return false;
141   }
142   return true;
143 }
144 
IsTransient() const145 bool NetworkIsolationKey::IsTransient() const {
146   if (!IsFullyPopulated())
147     return true;
148   return IsOpaque();
149 }
150 
151 // static
GetMode()152 NetworkIsolationKey::Mode NetworkIsolationKey::GetMode() {
153   if (base::FeatureList::IsEnabled(
154           net::features::kEnableCrossSiteFlagNetworkIsolationKey)) {
155     DCHECK(!base::FeatureList::IsEnabled(
156         net::features::kEnableFrameSiteSharedOpaqueNetworkIsolationKey));
157     return Mode::kCrossSiteFlagEnabled;
158   } else if (base::FeatureList::IsEnabled(
159                  net::features::
160                      kEnableFrameSiteSharedOpaqueNetworkIsolationKey)) {
161     return Mode::kFrameSiteWithSharedOpaqueEnabled;
162   } else {
163     return Mode::kFrameSiteEnabled;
164   }
165 }
166 
IsEmpty() const167 bool NetworkIsolationKey::IsEmpty() const {
168   return !top_frame_site_.has_value() && !frame_site_.has_value();
169 }
170 
IsOpaque() const171 bool NetworkIsolationKey::IsOpaque() const {
172   if (top_frame_site_->opaque()) {
173     return true;
174   }
175   // For Mode::kCrossSiteFlagEnabled and Mode::kFrameSiteWithSharedOpaqueEnabled
176   // we don't want to treat NIKs for opaque origin frames as opaque.
177   if (GetMode() == Mode::kFrameSiteEnabled && frame_site_->opaque()) {
178     return true;
179   }
180   if (nonce_.has_value()) {
181     return true;
182   }
183   return false;
184 }
185 
186 }  // namespace net
187