network_isolation_key.cc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. #include <cstddef>
  5. #include <string>
  6. #include "base/unguessable_token.h"
  7. #include "base/values.h"
  8. #include "net/base/features.h"
  9. #include "net/base/network_isolation_key.h"
  10. #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
  11. #include "schemeful_site.h"
  12. #include "third_party/abseil-cpp/absl/types/optional.h"
  13. #include "url/gurl.h"
  14. #include "url/origin.h"
  15. #include "url/url_constants.h"
  16. namespace net {
  17. namespace {
  18. std::string GetSiteDebugString(const absl::optional<SchemefulSite>& site) {
  19. return site ? site->GetDebugString() : "null";
  20. }
  21. } // namespace
  22. NetworkIsolationKey::NetworkIsolationKey(const SchemefulSite& top_frame_site,
  23. const SchemefulSite& frame_site,
  24. const base::UnguessableToken* nonce)
  25. : NetworkIsolationKey(SchemefulSite(top_frame_site),
  26. SchemefulSite(frame_site),
  27. nonce) {}
  28. NetworkIsolationKey::NetworkIsolationKey(SchemefulSite&& top_frame_site,
  29. SchemefulSite&& frame_site,
  30. const base::UnguessableToken* nonce)
  31. : top_frame_site_(std::move(top_frame_site)),
  32. frame_site_(IsFrameSiteEnabled()
  33. ? absl::make_optional(std::move(frame_site))
  34. : absl::nullopt),
  35. nonce_(nonce ? absl::make_optional(*nonce) : absl::nullopt) {
  36. DCHECK(!nonce || !nonce->is_empty());
  37. }
  38. NetworkIsolationKey::NetworkIsolationKey(const url::Origin& top_frame_origin,
  39. const url::Origin& frame_origin)
  40. : NetworkIsolationKey(SchemefulSite(top_frame_origin),
  41. SchemefulSite(frame_origin)) {}
  42. NetworkIsolationKey::NetworkIsolationKey() = default;
  43. NetworkIsolationKey::NetworkIsolationKey(
  44. const NetworkIsolationKey& network_isolation_key) = default;
  45. NetworkIsolationKey::NetworkIsolationKey(
  46. NetworkIsolationKey&& network_isolation_key) = default;
  47. NetworkIsolationKey::~NetworkIsolationKey() = default;
  48. NetworkIsolationKey& NetworkIsolationKey::operator=(
  49. const NetworkIsolationKey& network_isolation_key) = default;
  50. NetworkIsolationKey& NetworkIsolationKey::operator=(
  51. NetworkIsolationKey&& network_isolation_key) = default;
  52. NetworkIsolationKey NetworkIsolationKey::CreateTransient() {
  53. SchemefulSite site_with_opaque_origin;
  54. return NetworkIsolationKey(site_with_opaque_origin, site_with_opaque_origin);
  55. }
  56. NetworkIsolationKey NetworkIsolationKey::CreateWithNewFrameSite(
  57. const SchemefulSite& new_frame_site) const {
  58. if (!top_frame_site_)
  59. return NetworkIsolationKey();
  60. NetworkIsolationKey key(top_frame_site_.value(), new_frame_site);
  61. key.nonce_ = nonce_;
  62. return key;
  63. }
  64. absl::optional<std::string> NetworkIsolationKey::ToCacheKeyString() const {
  65. if (IsTransient())
  66. return absl::nullopt;
  67. std::string frame_site_str =
  68. " " + (IsFrameSiteEnabled() ? frame_site_->Serialize()
  69. : top_frame_site_->Serialize());
  70. return top_frame_site_->Serialize() + frame_site_str;
  71. }
  72. std::string NetworkIsolationKey::ToDebugString() const {
  73. // The space-separated serialization of |top_frame_site_| and
  74. // |frame_site_|.
  75. std::string return_string = GetSiteDebugString(top_frame_site_);
  76. return_string += " " + GetSiteDebugString(frame_site_);
  77. if (nonce_.has_value()) {
  78. return_string += " (with nonce " + nonce_->ToString() + ")";
  79. }
  80. return return_string;
  81. }
  82. bool NetworkIsolationKey::IsFullyPopulated() const {
  83. return top_frame_site_.has_value() &&
  84. (!IsFrameSiteEnabled() || frame_site_.has_value());
  85. }
  86. bool NetworkIsolationKey::IsTransient() const {
  87. if (!IsFullyPopulated())
  88. return true;
  89. return IsOpaque();
  90. }
  91. bool NetworkIsolationKey::ToValue(base::Value* out_value) const {
  92. if (IsEmpty()) {
  93. *out_value = base::Value(base::Value::Type::LIST);
  94. return true;
  95. }
  96. if (IsTransient())
  97. return false;
  98. // NetworkIsolationKeys with nonces are now always transient, so serializing
  99. // with nonces isn't strictly needed, but it's used for backwards
  100. // compatibility, Origin::Deserialize() is not compatible with
  101. // SerializeWithNonce().
  102. absl::optional<std::string> top_frame_value =
  103. SerializeSiteWithNonce(*top_frame_site_);
  104. if (!top_frame_value)
  105. return false;
  106. base::Value::List list;
  107. list.Append(std::move(top_frame_value).value());
  108. absl::optional<std::string> frame_value =
  109. IsFrameSiteEnabled() ? SerializeSiteWithNonce(*frame_site_)
  110. : absl::nullopt;
  111. if (frame_value.has_value()) {
  112. // If there is a frame value, append it.
  113. list.Append(std::move(frame_value).value());
  114. } else if (IsFrameSiteEnabled()) {
  115. // If there is supposed to be a frame value but there isn't return false.
  116. return false;
  117. }
  118. // List will have size 1 when frame site is disabled.
  119. *out_value = base::Value(std::move(list));
  120. return true;
  121. }
  122. bool NetworkIsolationKey::FromValue(
  123. const base::Value& value,
  124. NetworkIsolationKey* network_isolation_key) {
  125. if (!value.is_list())
  126. return false;
  127. const base::Value::List& list = value.GetList();
  128. if (list.empty()) {
  129. *network_isolation_key = NetworkIsolationKey();
  130. return true;
  131. }
  132. // When frame site is enabled list must be of size 2 and both values must be
  133. // strings.
  134. // When frame site is disabled for double key `list` can be either be of size
  135. // 2 or of size 1. For backwards compatibility, frame site is allowed to be of
  136. // size 2 when frame site is disabled because a previous expirement set frame
  137. // site equal to a copy of top frame site rather than setting it empty.
  138. if (IsFrameSiteEnabled()) {
  139. if (list.size() != 2 || !list[0].is_string() || !list[1].is_string()) {
  140. return false;
  141. }
  142. } else {
  143. if (list.size() < 0 || list.size() > 2 || !list[0].is_string()) {
  144. return false;
  145. }
  146. }
  147. absl::optional<SchemefulSite> top_frame_site =
  148. SchemefulSite::DeserializeWithNonce(list[0].GetString());
  149. // Opaque origins are currently never serialized to disk, but they used to be.
  150. if (!top_frame_site || top_frame_site->opaque())
  151. return false;
  152. if (list.size() == 1) {
  153. // The value of the frame_site parameter doesn't matter because the
  154. // constructor will default it to nullopt.
  155. *network_isolation_key =
  156. NetworkIsolationKey(std::move(*top_frame_site), net::SchemefulSite());
  157. return true;
  158. }
  159. absl::optional<SchemefulSite> frame_site =
  160. SchemefulSite::DeserializeWithNonce(list[1].GetString());
  161. // Opaque origins are currently never serialized to disk, but they used to be.
  162. if (!frame_site || frame_site->opaque())
  163. return false;
  164. *network_isolation_key =
  165. NetworkIsolationKey(std::move(*top_frame_site), std::move(*frame_site));
  166. return true;
  167. }
  168. const absl::optional<SchemefulSite>& NetworkIsolationKey::GetFrameSite() const {
  169. // TODO: @brgoldstein, add CHECK that
  170. // `kForceIsolationInfoFrameOriginToTopLevelFrame` is not enabled.
  171. return frame_site_;
  172. }
  173. bool NetworkIsolationKey::IsEmpty() const {
  174. return !top_frame_site_.has_value() && !frame_site_.has_value();
  175. }
  176. bool NetworkIsolationKey::IsFrameSiteEnabled() {
  177. return !base::FeatureList::IsEnabled(
  178. net::features::kForceIsolationInfoFrameOriginToTopLevelFrame);
  179. }
  180. bool NetworkIsolationKey::IsOpaque() const {
  181. return top_frame_site_->opaque() ||
  182. (IsFrameSiteEnabled() && frame_site_->opaque()) || nonce_.has_value();
  183. }
  184. absl::optional<std::string> NetworkIsolationKey::SerializeSiteWithNonce(
  185. const SchemefulSite& site) {
  186. return *(const_cast<SchemefulSite&>(site).SerializeWithNonce());
  187. }
  188. } // namespace net