• 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 #include <cstddef>
6 #include <string>
7 
8 #include "base/unguessable_token.h"
9 #include "net/base/features.h"
10 #include "net/base/network_isolation_key.h"
11 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
12 #include "schemeful_site.h"
13 #include "third_party/abseil-cpp/absl/types/optional.h"
14 #include "url/gurl.h"
15 #include "url/origin.h"
16 #include "url/url_constants.h"
17 
18 namespace net {
19 
20 namespace {
21 
GetSiteDebugString(const absl::optional<SchemefulSite> & site)22 std::string GetSiteDebugString(const absl::optional<SchemefulSite>& site) {
23   return site ? site->GetDebugString() : "null";
24 }
25 
26 }  // namespace
27 
NetworkIsolationKey(SerializationPasskey,SchemefulSite top_frame_site,SchemefulSite frame_site,bool is_cross_site,absl::optional<base::UnguessableToken> nonce)28 NetworkIsolationKey::NetworkIsolationKey(
29     SerializationPasskey,
30     SchemefulSite top_frame_site,
31     SchemefulSite frame_site,
32     bool is_cross_site,
33     absl::optional<base::UnguessableToken> nonce)
34     : top_frame_site_(std::move(top_frame_site)),
35       frame_site_(std::move(frame_site)),
36       is_cross_site_(is_cross_site),
37       nonce_(std::move(nonce)) {
38   CHECK_EQ(GetMode(), Mode::kCrossSiteFlagEnabled);
39 }
40 
NetworkIsolationKey(const SchemefulSite & top_frame_site,const SchemefulSite & frame_site,const absl::optional<base::UnguessableToken> & nonce)41 NetworkIsolationKey::NetworkIsolationKey(
42     const SchemefulSite& top_frame_site,
43     const SchemefulSite& frame_site,
44     const absl::optional<base::UnguessableToken>& nonce)
45     : NetworkIsolationKey(SchemefulSite(top_frame_site),
46                           SchemefulSite(frame_site),
47                           absl::optional<base::UnguessableToken>(nonce)) {}
48 
NetworkIsolationKey(SchemefulSite && top_frame_site,SchemefulSite && frame_site,absl::optional<base::UnguessableToken> && nonce)49 NetworkIsolationKey::NetworkIsolationKey(
50     SchemefulSite&& top_frame_site,
51     SchemefulSite&& frame_site,
52     absl::optional<base::UnguessableToken>&& nonce)
53     : top_frame_site_(std::move(top_frame_site)),
54       frame_site_(absl::make_optional(std::move(frame_site))),
55       is_cross_site_((GetMode() == Mode::kCrossSiteFlagEnabled)
56                          ? absl::make_optional(*top_frame_site_ != *frame_site_)
57                          : absl::nullopt),
58       nonce_(std::move(nonce)) {
59   DCHECK(!nonce_ || !nonce_->is_empty());
60 }
61 
NetworkIsolationKey(const url::Origin & top_frame_origin,const url::Origin & frame_origin)62 NetworkIsolationKey::NetworkIsolationKey(const url::Origin& top_frame_origin,
63                                          const url::Origin& frame_origin)
64     : NetworkIsolationKey(SchemefulSite(top_frame_origin),
65                           SchemefulSite(frame_origin)) {}
66 
67 NetworkIsolationKey::NetworkIsolationKey() = default;
68 
69 NetworkIsolationKey::NetworkIsolationKey(
70     const NetworkIsolationKey& network_isolation_key) = default;
71 
72 NetworkIsolationKey::NetworkIsolationKey(
73     NetworkIsolationKey&& network_isolation_key) = default;
74 
75 NetworkIsolationKey::~NetworkIsolationKey() = default;
76 
77 NetworkIsolationKey& NetworkIsolationKey::operator=(
78     const NetworkIsolationKey& network_isolation_key) = default;
79 
80 NetworkIsolationKey& NetworkIsolationKey::operator=(
81     NetworkIsolationKey&& network_isolation_key) = default;
82 
CreateTransient()83 NetworkIsolationKey NetworkIsolationKey::CreateTransient() {
84   SchemefulSite site_with_opaque_origin;
85   return NetworkIsolationKey(site_with_opaque_origin, site_with_opaque_origin);
86 }
87 
CreateWithNewFrameSite(const SchemefulSite & new_frame_site) const88 NetworkIsolationKey NetworkIsolationKey::CreateWithNewFrameSite(
89     const SchemefulSite& new_frame_site) const {
90   if (!top_frame_site_)
91     return NetworkIsolationKey();
92   NetworkIsolationKey key(top_frame_site_.value(), new_frame_site);
93   key.nonce_ = nonce_;
94   return key;
95 }
96 
ToCacheKeyString() const97 absl::optional<std::string> NetworkIsolationKey::ToCacheKeyString() const {
98   if (IsTransient())
99     return absl::nullopt;
100 
101   std::string variable_key_piece;
102   switch (GetMode()) {
103     case Mode::kFrameSiteEnabled:
104       variable_key_piece = frame_site_->Serialize();
105       break;
106     case Mode::kCrossSiteFlagEnabled:
107       variable_key_piece = (*is_cross_site_ ? "_1" : "_0");
108       break;
109   }
110   return top_frame_site_->Serialize() + " " + variable_key_piece;
111 }
112 
ToDebugString() const113 std::string NetworkIsolationKey::ToDebugString() const {
114   // The space-separated serialization of |top_frame_site_| and
115   // |frame_site_|.
116   std::string return_string = GetSiteDebugString(top_frame_site_);
117   switch (GetMode()) {
118     case Mode::kFrameSiteEnabled:
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     return Mode::kCrossSiteFlagEnabled;
156   } else {
157     return Mode::kFrameSiteEnabled;
158   }
159 }
160 
GetFrameSite() const161 const absl::optional<SchemefulSite>& NetworkIsolationKey::GetFrameSite() const {
162   // Frame site will be empty if double-keying is enabled.
163   CHECK(GetMode() == Mode::kFrameSiteEnabled);
164   return frame_site_;
165 }
166 
GetIsCrossSite() const167 absl::optional<bool> NetworkIsolationKey::GetIsCrossSite() const {
168   CHECK(GetMode() == Mode::kCrossSiteFlagEnabled);
169   return is_cross_site_;
170 }
171 
IsEmpty() const172 bool NetworkIsolationKey::IsEmpty() const {
173   return !top_frame_site_.has_value() && !frame_site_.has_value();
174 }
175 
IsOpaque() const176 bool NetworkIsolationKey::IsOpaque() const {
177   if (top_frame_site_->opaque()) {
178     return true;
179   }
180   if (GetMode() == Mode::kFrameSiteEnabled && frame_site_->opaque()) {
181     return true;
182   }
183   if (nonce_.has_value()) {
184     return true;
185   }
186   return false;
187 }
188 
189 }  // namespace net
190