123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- // 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 <cstddef>
- #include <string>
- #include "base/unguessable_token.h"
- #include "base/values.h"
- #include "net/base/features.h"
- #include "net/base/network_isolation_key.h"
- #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
- #include "schemeful_site.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_(IsFrameSiteEnabled()
- ? absl::make_optional(std::move(frame_site))
- : absl::nullopt),
- 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;
- }
- absl::optional<std::string> NetworkIsolationKey::ToCacheKeyString() const {
- if (IsTransient())
- return absl::nullopt;
- std::string frame_site_str =
- " " + (IsFrameSiteEnabled() ? frame_site_->Serialize()
- : top_frame_site_->Serialize());
- return top_frame_site_->Serialize() + frame_site_str;
- }
- 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() &&
- (!IsFrameSiteEnabled() || 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;
- base::Value::List list;
- list.Append(std::move(top_frame_value).value());
- absl::optional<std::string> frame_value =
- IsFrameSiteEnabled() ? SerializeSiteWithNonce(*frame_site_)
- : absl::nullopt;
- if (frame_value.has_value()) {
- // If there is a frame value, append it.
- list.Append(std::move(frame_value).value());
- } else if (IsFrameSiteEnabled()) {
- // If there is supposed to be a frame value but there isn't return false.
- return false;
- }
- // List will have size 1 when frame site is disabled.
- *out_value = base::Value(std::move(list));
- return true;
- }
- bool NetworkIsolationKey::FromValue(
- const base::Value& value,
- NetworkIsolationKey* network_isolation_key) {
- if (!value.is_list())
- return false;
- const base::Value::List& list = value.GetList();
- if (list.empty()) {
- *network_isolation_key = NetworkIsolationKey();
- return true;
- }
- // When frame site is enabled list must be of size 2 and both values must be
- // strings.
- // When frame site is disabled for double key `list` can be either be of size
- // 2 or of size 1. For backwards compatibility, frame site is allowed to be of
- // size 2 when frame site is disabled because a previous expirement set frame
- // site equal to a copy of top frame site rather than setting it empty.
- if (IsFrameSiteEnabled()) {
- if (list.size() != 2 || !list[0].is_string() || !list[1].is_string()) {
- return false;
- }
- } else {
- if (list.size() < 0 || list.size() > 2 || !list[0].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;
- if (list.size() == 1) {
- // The value of the frame_site parameter doesn't matter because the
- // constructor will default it to nullopt.
- *network_isolation_key =
- NetworkIsolationKey(std::move(*top_frame_site), net::SchemefulSite());
- return true;
- }
- 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;
- }
- const absl::optional<SchemefulSite>& NetworkIsolationKey::GetFrameSite() const {
- // TODO: @brgoldstein, add CHECK that
- // `kForceIsolationInfoFrameOriginToTopLevelFrame` is not enabled.
- return frame_site_;
- }
- bool NetworkIsolationKey::IsEmpty() const {
- return !top_frame_site_.has_value() && !frame_site_.has_value();
- }
- bool NetworkIsolationKey::IsFrameSiteEnabled() {
- return !base::FeatureList::IsEnabled(
- net::features::kForceIsolationInfoFrameOriginToTopLevelFrame);
- }
- bool NetworkIsolationKey::IsOpaque() const {
- return top_frame_site_->opaque() ||
- (IsFrameSiteEnabled() && frame_site_->opaque()) || nonce_.has_value();
- }
- absl::optional<std::string> NetworkIsolationKey::SerializeSiteWithNonce(
- const SchemefulSite& site) {
- return *(const_cast<SchemefulSite&>(site).SerializeWithNonce());
- }
- } // namespace net
|