| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <string> |
| |
| #include "base/unguessable_token.h" |
| #include "base/values.h" |
| #include "net/base/network_isolation_key.h" |
| #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| #include "url/url_constants.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| std::string GetSiteDebugString(const absl::optional<SchemefulSite>& site) { |
| return site ? site->GetDebugString() : "null"; |
| } |
| |
| } // namespace |
| |
| NetworkIsolationKey::NetworkIsolationKey(const SchemefulSite& top_frame_site, |
| const SchemefulSite& frame_site, |
| const base::UnguessableToken* nonce) |
| : NetworkIsolationKey(SchemefulSite(top_frame_site), |
| SchemefulSite(frame_site), |
| nonce) {} |
| |
| NetworkIsolationKey::NetworkIsolationKey(SchemefulSite&& top_frame_site, |
| SchemefulSite&& frame_site, |
| const base::UnguessableToken* nonce) |
| : top_frame_site_(std::move(top_frame_site)), |
| frame_site_(std::move(frame_site)), |
| nonce_(nonce ? absl::make_optional(*nonce) : absl::nullopt) { |
| DCHECK(!nonce || !nonce->is_empty()); |
| } |
| |
| NetworkIsolationKey::NetworkIsolationKey(const url::Origin& top_frame_origin, |
| const url::Origin& frame_origin) |
| : NetworkIsolationKey(SchemefulSite(top_frame_origin), |
| SchemefulSite(frame_origin)) {} |
| |
| NetworkIsolationKey::NetworkIsolationKey() = default; |
| |
| NetworkIsolationKey::NetworkIsolationKey( |
| const NetworkIsolationKey& network_isolation_key) = default; |
| |
| NetworkIsolationKey::NetworkIsolationKey( |
| NetworkIsolationKey&& network_isolation_key) = default; |
| |
| NetworkIsolationKey::~NetworkIsolationKey() = default; |
| |
| NetworkIsolationKey& NetworkIsolationKey::operator=( |
| const NetworkIsolationKey& network_isolation_key) = default; |
| |
| NetworkIsolationKey& NetworkIsolationKey::operator=( |
| NetworkIsolationKey&& network_isolation_key) = default; |
| |
| NetworkIsolationKey NetworkIsolationKey::CreateTransient() { |
| SchemefulSite site_with_opaque_origin; |
| return NetworkIsolationKey(site_with_opaque_origin, site_with_opaque_origin); |
| } |
| |
| NetworkIsolationKey NetworkIsolationKey::CreateWithNewFrameSite( |
| const SchemefulSite& new_frame_site) const { |
| if (!top_frame_site_) |
| return NetworkIsolationKey(); |
| NetworkIsolationKey key(top_frame_site_.value(), new_frame_site); |
| key.nonce_ = nonce_; |
| return key; |
| } |
| |
| std::string NetworkIsolationKey::ToString() const { |
| if (IsTransient()) |
| return ""; |
| |
| return top_frame_site_->Serialize() + " " + frame_site_->Serialize(); |
| } |
| |
| std::string NetworkIsolationKey::ToDebugString() const { |
| // The space-separated serialization of |top_frame_site_| and |
| // |frame_site_|. |
| std::string return_string = GetSiteDebugString(top_frame_site_); |
| return_string += " " + GetSiteDebugString(frame_site_); |
| |
| if (nonce_.has_value()) { |
| return_string += " (with nonce " + nonce_->ToString() + ")"; |
| } |
| |
| return return_string; |
| } |
| |
| bool NetworkIsolationKey::IsFullyPopulated() const { |
| return top_frame_site_.has_value() && frame_site_.has_value(); |
| } |
| |
| bool NetworkIsolationKey::IsTransient() const { |
| if (!IsFullyPopulated()) |
| return true; |
| return IsOpaque(); |
| } |
| |
| bool NetworkIsolationKey::ToValue(base::Value* out_value) const { |
| if (IsEmpty()) { |
| *out_value = base::Value(base::Value::Type::LIST); |
| return true; |
| } |
| |
| if (IsTransient()) |
| return false; |
| |
| // NetworkIsolationKeys with nonces are now always transient, so serializing |
| // with nonces isn't strictly needed, but it's used for backwards |
| // compatibility, Origin::Deserialize() is not compatible with |
| // SerializeWithNonce(). |
| absl::optional<std::string> top_frame_value = |
| SerializeSiteWithNonce(*top_frame_site_); |
| if (!top_frame_value) |
| return false; |
| *out_value = base::Value(base::Value::Type::LIST); |
| out_value->Append(std::move(*top_frame_value)); |
| |
| absl::optional<std::string> frame_value = |
| SerializeSiteWithNonce(*frame_site_); |
| if (!frame_value) |
| return false; |
| out_value->Append(std::move(*frame_value)); |
| |
| return true; |
| } |
| |
| bool NetworkIsolationKey::FromValue( |
| const base::Value& value, |
| NetworkIsolationKey* network_isolation_key) { |
| if (!value.is_list()) |
| return false; |
| |
| base::Value::ConstListView list = value.GetList(); |
| if (list.empty()) { |
| *network_isolation_key = NetworkIsolationKey(); |
| return true; |
| } |
| |
| if (list.size() != 2 || !list[0].is_string() || !list[1].is_string()) |
| return false; |
| |
| absl::optional<SchemefulSite> top_frame_site = |
| SchemefulSite::DeserializeWithNonce(list[0].GetString()); |
| // Opaque origins are currently never serialized to disk, but they used to be. |
| if (!top_frame_site || top_frame_site->opaque()) |
| return false; |
| |
| absl::optional<SchemefulSite> frame_site = |
| SchemefulSite::DeserializeWithNonce(list[1].GetString()); |
| // Opaque origins are currently never serialized to disk, but they used to be. |
| if (!frame_site || frame_site->opaque()) |
| return false; |
| |
| *network_isolation_key = |
| NetworkIsolationKey(std::move(*top_frame_site), std::move(*frame_site)); |
| return true; |
| } |
| |
| bool NetworkIsolationKey::IsEmpty() const { |
| return !top_frame_site_.has_value() && !frame_site_.has_value(); |
| } |
| |
| bool NetworkIsolationKey::IsOpaque() const { |
| return top_frame_site_->opaque() || frame_site_->opaque() || |
| nonce_.has_value(); |
| } |
| |
| absl::optional<std::string> NetworkIsolationKey::SerializeSiteWithNonce( |
| const SchemefulSite& site) { |
| return *(const_cast<SchemefulSite&>(site).SerializeWithNonce()); |
| } |
| |
| } // namespace net |