Skip to content

Commit

Permalink
Merge pull request #22619 from brave/issues/35686
Browse files Browse the repository at this point in the history
Fixup and migrate to Chromium blob partitioning impl.
  • Loading branch information
goodov authored Apr 1, 2024
2 parents 55a0f82 + 323a387 commit 3d901ec
Show file tree
Hide file tree
Showing 10 changed files with 23 additions and 270 deletions.
43 changes: 3 additions & 40 deletions browser/ephemeral_storage/blob_url_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -293,16 +293,7 @@ class BlobUrlBrowserTestBase : public EphemeralStorageBrowserTest {
}
};

class BlobUrlPartitionEnabledBrowserTest : public BlobUrlBrowserTestBase {
public:
BlobUrlPartitionEnabledBrowserTest() {
scoped_feature_list_.InitAndEnableFeature(
net::features::kBravePartitionBlobStorage);
}

private:
base::test::ScopedFeatureList scoped_feature_list_;
};
using BlobUrlPartitionEnabledBrowserTest = BlobUrlBrowserTestBase;

IN_PROC_BROWSER_TEST_F(BlobUrlPartitionEnabledBrowserTest,
BlobsArePartitioned) {
Expand All @@ -325,17 +316,6 @@ IN_PROC_BROWSER_TEST_F(BlobUrlPartitionEnabledWithoutSiteIsolationBrowserTest,
TestBlobsArePartitioned();
}

IN_PROC_BROWSER_TEST_F(BlobUrlPartitionEnabledBrowserTest,
BlobsAreNotPartitionedWhenShieldsDisabled) {
// Disable shields on a.com and b.com.
brave_shields::SetBraveShieldsEnabled(content_settings(), false,
a_site_ephemeral_storage_url_);
brave_shields::SetBraveShieldsEnabled(content_settings(), false,
b_site_ephemeral_storage_url_);

TestBlobsAreNotPartitioned();
}

IN_PROC_BROWSER_TEST_F(BlobUrlPartitionEnabledBrowserTest,
BlobsArePartitionedIn1PESMode) {
SetCookieSetting(a_site_ephemeral_storage_url_, CONTENT_SETTING_SESSION_ONLY);
Expand All @@ -353,7 +333,7 @@ class BlobUrlPartitionDisabledBrowserTest : public BlobUrlBrowserTestBase {
public:
BlobUrlPartitionDisabledBrowserTest() {
scoped_feature_list_.InitAndDisableFeature(
net::features::kBravePartitionBlobStorage);
net::features::kSupportPartitionedBlobUrl);
}

private:
Expand All @@ -365,23 +345,6 @@ IN_PROC_BROWSER_TEST_F(BlobUrlPartitionDisabledBrowserTest,
TestBlobsAreNotPartitioned();
}

class BlobUrlEphemeralStorageDisabledBrowserTest
: public BlobUrlBrowserTestBase {
public:
BlobUrlEphemeralStorageDisabledBrowserTest() {
scoped_feature_list_.InitAndDisableFeature(
net::features::kBraveEphemeralStorage);
}

private:
base::test::ScopedFeatureList scoped_feature_list_;
};

IN_PROC_BROWSER_TEST_F(BlobUrlEphemeralStorageDisabledBrowserTest,
BlobsAreNotPartitioned) {
TestBlobsAreNotPartitioned();
}

// Tests for the blob: URL scheme, originally implemented in
// content/browser/blob_storage/blob_url_browsertest.cc,
// migrated from content_browsertests to brave_browser_tests.
Expand All @@ -390,7 +353,7 @@ class BlobUrlBrowserTest : public BlobUrlBrowserTestBase,
public:
BlobUrlBrowserTest() {
scoped_feature_list_.InitWithFeatureState(
net::features::kBravePartitionBlobStorage, GetParam());
net::features::kSupportPartitionedBlobUrl, GetParam());
}

private:
Expand Down
9 changes: 0 additions & 9 deletions chromium_src/net/base/features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ OVERRIDE_FEATURE_DEFAULT_STATES({{
{kPartitionSSLSessionsByNetworkIsolationKey,
base::FEATURE_ENABLED_BY_DEFAULT},
{kSplitHostCacheByNetworkIsolationKey, base::FEATURE_ENABLED_BY_DEFAULT},
// It is necessary yet to make chromium storage partitioning compatible with
// Brave ephemeral storage. For reference:
// https://github.com/brave/brave-browser/issues/26165
{kSupportPartitionedBlobUrl, base::FEATURE_DISABLED_BY_DEFAULT},
{kTpcdMetadataGrants, base::FEATURE_DISABLED_BY_DEFAULT},
{kWaitForFirstPartySetsInit, base::FEATURE_DISABLED_BY_DEFAULT},
}});
Expand All @@ -44,11 +40,6 @@ BASE_FEATURE(kBraveFirstPartyEphemeralStorage,
"BraveFirstPartyEphemeralStorage",
base::FEATURE_ENABLED_BY_DEFAULT);

// Partition Blob storage in ephemeral context.
BASE_FEATURE(kBravePartitionBlobStorage,
"BravePartitionBlobStorage",
base::FEATURE_ENABLED_BY_DEFAULT);

// Partition HSTS state storage by top frame site.
BASE_FEATURE(kBravePartitionHSTS,
"BravePartitionHSTS",
Expand Down
1 change: 0 additions & 1 deletion chromium_src/net/base/features.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ NET_EXPORT BASE_DECLARE_FEATURE(kBraveHttpsByDefault);
NET_EXPORT BASE_DECLARE_FEATURE(kBraveFallbackDoHProvider);
NET_EXPORT extern const base::FeatureParam<DohFallbackEndpointType>
kBraveFallbackDoHProviderEndpoint;
NET_EXPORT BASE_DECLARE_FEATURE(kBravePartitionBlobStorage);
NET_EXPORT BASE_DECLARE_FEATURE(kBravePartitionHSTS);
NET_EXPORT BASE_DECLARE_FEATURE(kBraveTorWindowsHttpsOnly);
NET_EXPORT BASE_DECLARE_FEATURE(kBraveForgetFirstPartyStorage);
Expand Down
12 changes: 0 additions & 12 deletions chromium_src/net/base/url_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,6 @@ std::string URLToEphemeralStorageDomain(const GURL& url) {
return domain;
}

bool EphemeralStorageOriginUtils::CanUseNonceForEphemeralStorageKeying(
const url::Origin& origin) {
return origin.opaque() && !origin.nonce_->raw_token().is_empty();
}

const base::UnguessableToken&
EphemeralStorageOriginUtils::GetNonceForEphemeralStorageKeying(
const url::Origin& origin) {
CHECK(CanUseNonceForEphemeralStorageKeying(origin));
return origin.nonce_->raw_token();
}

bool IsOnion(const GURL& url) {
return url.DomainIs(kOnionDomain);
}
Expand Down
11 changes: 0 additions & 11 deletions chromium_src/net/base/url_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,6 @@ namespace net {
// to identify a particular storage domain uniquely in a BrowserContext.
NET_EXPORT std::string URLToEphemeralStorageDomain(const GURL& url);

// Helpers to access Origin internal data to use for Ephemeral Storage.
class NET_EXPORT EphemeralStorageOriginUtils {
public:
/* Checks if an origin is opaque and nonce is initialized. */
static bool CanUseNonceForEphemeralStorageKeying(const url::Origin& origin);
/* Returns nonce to use as an Ephemeral Storage key. CHECKs if an origin
* cannot be used for Ephemeral Storage keying. */
static const base::UnguessableToken& GetNonceForEphemeralStorageKeying(
const url::Origin& origin);
};

NET_EXPORT bool IsOnion(const GURL& url);

NET_EXPORT bool IsLocalhostOrOnion(const GURL& url);
Expand Down
125 changes: 18 additions & 107 deletions chromium_src/storage/browser/blob/blob_url_store_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,144 +3,55 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#include <optional>

#include "base/strings/strcat.h"
#include "net/base/features.h"
#include "net/base/url_util.h"
#include "storage/browser/blob/blob_url_store_impl.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace storage {
namespace {

// Checks if an origin is usable for partitioning. Origin is considered usable
// if it's opaque and has a valid precursor origin. Partitioning is done by
// appending an opaque nonce internally to all URLs, the valid precursor origin
// is used to check if an URL can be used to access a blob.
bool CanUseOriginForPartitioning(const url::Origin& origin) {
return net::EphemeralStorageOriginUtils::CanUseNonceForEphemeralStorageKeying(
origin) &&
origin.GetTupleOrPrecursorTupleIfOpaque().IsValid() &&
base::FeatureList::IsEnabled(
net::features::kBravePartitionBlobStorage);
}

bool IsBlobUrlValidForPartitionedOrigin(const url::Origin& origin,
const url::Origin& url_origin) {
if (!CanUseOriginForPartitioning(origin)) {
return false;
}

const url::Origin& non_opaque_origin =
url::Origin::Create(origin.GetTupleOrPrecursorTupleIfOpaque().GetURL());
return non_opaque_origin == url_origin;
}

} // namespace
} // namespace storage

#define BlobURLStoreImpl BlobURLStoreImpl_ChromiumImpl
#define BRAVE_BLOB_URL_STORE_IMPL_BLOB_URL_IS_VALID \
if (!valid_origin) { \
valid_origin = \
IsBlobUrlValidForPartitionedOrigin(storage_key_origin, url_origin); \
}

#include "src/storage/browser/blob/blob_url_store_impl.cc"

#undef BRAVE_BLOB_URL_STORE_IMPL_BLOB_URL_IS_VALID
#undef BlobURLStoreImpl

namespace storage {

BlobURLStoreImpl::BlobURLStoreImpl(
const blink::StorageKey& storage_key,
base::WeakPtr<BlobUrlRegistry> registry,
BlobURLValidityCheckBehavior validity_check_behavior)
: BlobURLStoreImpl_ChromiumImpl::BlobURLStoreImpl_ChromiumImpl(
storage_key,
std::move(registry),
validity_check_behavior) {}

void BlobURLStoreImpl::Register(
mojo::PendingRemote<blink::mojom::Blob> blob,
const GURL& url,
const base::UnguessableToken& unsafe_agent_cluster_id,
const std::optional<net::SchemefulSite>& unsafe_top_level_site,
RegisterCallback callback) {
BlobURLStoreImpl_ChromiumImpl::Register(
std::move(blob), GetPartitionedOrOriginalUrl(url),
unsafe_agent_cluster_id, unsafe_top_level_site, std::move(callback));
}

void BlobURLStoreImpl::Revoke(const GURL& url) {
BlobURLStoreImpl_ChromiumImpl::Revoke(GetPartitionedOrOriginalUrl(url));
}

void BlobURLStoreImpl::Resolve(const GURL& url, ResolveCallback callback) {
BlobURLStoreImpl_ChromiumImpl::Resolve(GetPartitionedOrOriginalUrl(url),
std::move(callback));
// If a URL is not mapped to the current `storage_key_`, it's likely stored
// with a different StorageKey (partitioned) and should not be resolved.
if (registry_ && !registry_->IsUrlMapped(url, storage_key_)) {
std::move(callback).Run(mojo::NullRemote(), std::nullopt);
return;
}

BlobURLStoreImpl_ChromiumImpl::Resolve(url, std::move(callback));
}

void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
const GURL& url,
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
ResolveAsURLLoaderFactoryCallback callback) {
if (!registry_) {
BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver));
// If a URL is not mapped to the current `storage_key_`, it's likely stored
// with a different StorageKey (partitioned) and should not be resolved.
if (registry_ && !registry_->IsUrlMapped(url, storage_key_)) {
std::move(callback).Run(std::nullopt, std::nullopt);
return;
}

// Use modified URL only for accessing blob registry. Original URL is passed
// as is into BlobURLLoaderFactory.
const GURL& ephemeral_url = GetPartitionedOrOriginalUrl(url);
BlobURLLoaderFactory::Create(registry_->GetBlobFromUrl(ephemeral_url), url,
std::move(receiver));
std::move(callback).Run(registry_->GetUnsafeAgentClusterID(ephemeral_url),
registry_->GetUnsafeTopLevelSite(ephemeral_url));
BlobURLStoreImpl_ChromiumImpl::ResolveAsURLLoaderFactory(
url, std::move(receiver), std::move(callback));
}

void BlobURLStoreImpl::ResolveForNavigation(
const GURL& url,
mojo::PendingReceiver<blink::mojom::BlobURLToken> token,
ResolveForNavigationCallback callback) {
if (!registry_) {
// If a URL is not mapped to the current `storage_key_`, it's likely stored
// with a different StorageKey (partitioned) and should not be resolved.
if (registry_ && !registry_->IsUrlMapped(url, storage_key_)) {
std::move(callback).Run(std::nullopt);
return;
}

// Use modified URL only for accessing blob registry. Original URL is passed
// as is into BlobURLTokenImpl.
const GURL& ephemeral_url = GetPartitionedOrOriginalUrl(url);
mojo::PendingRemote<blink::mojom::Blob> blob =
registry_->GetBlobFromUrl(ephemeral_url);
if (!blob) {
std::move(callback).Run(std::nullopt);
return;
}
new BlobURLTokenImpl(registry_, url, std::move(blob), std::move(token));
std::move(callback).Run(registry_->GetUnsafeAgentClusterID(ephemeral_url));
}

GURL BlobURLStoreImpl::GetPartitionedOrOriginalUrl(const GURL& url) const {
const url::Origin& storage_key_origin = storage_key_.origin();
if (!CanUseOriginForPartitioning(storage_key_origin)) {
return url;
}

// Use origin nonce as a partition key and append it to the URL path.
GURL clean_url = BlobUrlUtils::ClearUrlFragment(url);
std::string partitioned_path = base::StrCat(
{clean_url.path_piece(), "_",
net::EphemeralStorageOriginUtils::GetNonceForEphemeralStorageKeying(
storage_key_origin)
.ToString()});
GURL::Replacements replacements;
replacements.SetPathStr(partitioned_path);
return clean_url.ReplaceComponents(replacements);
BlobURLStoreImpl_ChromiumImpl::ResolveForNavigation(url, std::move(token),
std::move(callback));
}

} // namespace storage
16 changes: 2 additions & 14 deletions chromium_src/storage/browser/blob/blob_url_store_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,8 @@ namespace storage {
class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
: public BlobURLStoreImpl_ChromiumImpl {
public:
BlobURLStoreImpl(const blink::StorageKey& storage_key,
base::WeakPtr<BlobUrlRegistry> registry,
BlobURLValidityCheckBehavior validity_check_options =
BlobURLValidityCheckBehavior::DEFAULT);

void Register(mojo::PendingRemote<blink::mojom::Blob> blob,
const GURL& url,
const base::UnguessableToken& unsafe_agent_cluster_id,
const std::optional<net::SchemefulSite>& unsafe_top_level_site,
RegisterCallback callback) override;
void Revoke(const GURL& url) override;
using BlobURLStoreImpl_ChromiumImpl::BlobURLStoreImpl_ChromiumImpl;

void Resolve(const GURL& url, ResolveCallback callback) override;
void ResolveAsURLLoaderFactory(
const GURL& url,
Expand All @@ -49,9 +40,6 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
const GURL& url,
mojo::PendingReceiver<blink::mojom::BlobURLToken> token,
ResolveForNavigationCallback callback) override;

private:
GURL GetPartitionedOrOriginalUrl(const GURL& url) const;
};

} // namespace storage
Expand Down

This file was deleted.

Loading

0 comments on commit 3d901ec

Please sign in to comment.