From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Dylan Cutler Date: Tue, 2 May 2023 20:31:30 +0000 Subject: [PATCH] Add method to convert StorageKey to net::IsolationInfo This is useful for computing IsolationInfo, NetworkIsolationKey, etc. in partitioned storage which have network access (e.g. service workers). We want to switch to deriving these using the contexts' StorageKey so that they only have access to network state in their partition. Bug: 1147281 Change-Id: I22ae2cd861ce156b2897cbf0fec713933957a421 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4496124 Commit-Queue: Dylan Cutler Reviewed-by: Steven Bingler Cr-Commit-Position: refs/heads/main@{#1138611} --- .../blink/common/storage_key/storage_key.cc | 10 +++++ .../storage_key/storage_key_unittest.cc | 40 +++++++++++++++++++ .../public/common/storage_key/storage_key.h | 17 ++++++++ 3 files changed, 67 insertions(+) diff --git a/third_party/blink/common/storage_key/storage_key.cc b/third_party/blink/common/storage_key/storage_key.cc index da0925aa2414d..512880ba4afd1 100644 --- a/third_party/blink/common/storage_key/storage_key.cc +++ b/third_party/blink/common/storage_key/storage_key.cc @@ -779,6 +779,16 @@ const net::SiteForCookies StorageKey::ToNetSiteForCookies() const { return net::SiteForCookies(top_level_site_); } +const net::IsolationInfo StorageKey::ToPartialNetIsolationInfo() const { + url::Origin top_frame_origin = + IsFirstPartyContext() ? origin_ + : url::Origin::Create(top_level_site_.GetURL()); + return net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + top_frame_origin, origin_, + ToNetSiteForCookies(), + /*party_context=*/absl::nullopt, nonce_); +} + // static bool StorageKey::ShouldSkipKeyDueToPartitioning( const std::string& reg_key_string) { diff --git a/third_party/blink/common/storage_key/storage_key_unittest.cc b/third_party/blink/common/storage_key/storage_key_unittest.cc index 4066bf8c62691..3d0ecf69fde44 100644 --- a/third_party/blink/common/storage_key/storage_key_unittest.cc +++ b/third_party/blink/common/storage_key/storage_key_unittest.cc @@ -944,6 +944,46 @@ TEST_F(StorageKeyTest, ToNetSiteForCookies) { } } +TEST_F(StorageKeyTest, ToPartialNetIsolationInfo) { + const auto kOrigin = url::Origin::Create(GURL("https://subdomain.foo.com")); + const auto kOtherOrigin = + url::Origin::Create(GURL("https://subdomain.bar.com")); + const auto nonce = base::UnguessableToken::Create(); + + { // Same-site storage key + const auto storage_key = + StorageKey::Create(kOrigin, net::SchemefulSite(kOrigin), + mojom::AncestorChainBit::kSameSite); + + storage_key.ToPartialNetIsolationInfo().IsEqualForTesting( + net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, + kOrigin, kOrigin, + net::SiteForCookies::FromOrigin(kOrigin))); + } + + { // Cross-site storage key + const auto storage_key = + StorageKey::Create(kOrigin, net::SchemefulSite(kOtherOrigin), + mojom::AncestorChainBit::kCrossSite); + + storage_key.ToPartialNetIsolationInfo().IsEqualForTesting( + net::IsolationInfo::Create( + net::IsolationInfo::RequestType::kOther, + net::SchemefulSite(kOrigin).GetInternalOriginForTesting(), + kOtherOrigin, net::SiteForCookies())); + } + + { // Nonced key + const auto storage_key = StorageKey::CreateWithNonce(kOrigin, nonce); + + storage_key.ToPartialNetIsolationInfo().IsEqualForTesting( + net::IsolationInfo::Create( + net::IsolationInfo::RequestType::kOther, + net::SchemefulSite(kOrigin).GetInternalOriginForTesting(), kOrigin, + net::SiteForCookies(), absl::nullopt, nonce)); + } +} + TEST_F(StorageKeyTest, CopyWithForceEnabledThirdPartyStoragePartitioning) { const url::Origin kOrigin = url::Origin::Create(GURL("https://foo.com")); const url::Origin kOtherOrigin = url::Origin::Create(GURL("https://bar.com")); diff --git a/third_party/blink/public/common/storage_key/storage_key.h b/third_party/blink/public/common/storage_key/storage_key.h index 7c452e6563660..7993f652d7542 100644 --- a/third_party/blink/public/common/storage_key/storage_key.h +++ b/third_party/blink/public/common/storage_key/storage_key.h @@ -239,6 +239,23 @@ class BLINK_COMMON_EXPORT StorageKey { // info.) const net::SiteForCookies ToNetSiteForCookies() const; + // Return an instance of net::IsolationInfo. This is used for forms of storage + // like workers which have network access to ensure they only have access to + // network state in their partition. + // + // The IsolationInfo that this creates will not be exactly the same as the + // IsolationInfo of the context that created the worker. This is because + // StorageKey only stores the top-frame *site* whereas IsolationInfo normally + // uses top-frame *origin*. So we may lose the subdomain of the original + // context. Although this is imperfect, it is better than using first-party + // IsolationInfo for partitioned workers. + // + // For first-party contexts, the storage origin is used for the top-frame + // origin in the resulting IsolationInfo. This matches legacy behavior before + // storage partitioning, where the storage origin is always used as the + // top-frame origin. + const net::IsolationInfo ToPartialNetIsolationInfo() const; + // Returns true if the registration key string is partitioned by top-level // site but storage partitioning is currently disabled, otherwise returns // false. Also returns false if the key string contains a serialized nonce.