Implement proper in-memory ephemeral localStorage support.
This commit is contained in:
@@ -1,18 +1,3 @@
|
||||
source_set("ephemeral_storage") {
|
||||
sources = [
|
||||
"ephemeral_storage_tab_helper.cc",
|
||||
"ephemeral_storage_tab_helper.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//chrome/browser/ui",
|
||||
"//content/public/browser",
|
||||
"//net",
|
||||
"//third_party/blink/public/common",
|
||||
]
|
||||
}
|
||||
|
||||
if (!is_android) {
|
||||
source_set("ephemeral_storage_tests") {
|
||||
testonly = true
|
||||
@@ -22,7 +7,6 @@ if (!is_android) {
|
||||
]
|
||||
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
|
||||
deps = [
|
||||
":ephemeral_storage",
|
||||
"//base",
|
||||
"//brave/common",
|
||||
"//brave/components/brave_shields/browser:browser",
|
||||
|
||||
@@ -706,6 +706,67 @@ IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest, NetworkCookiesAreSetIn3p) {
|
||||
EXPECT_EQ("", site_b_tab_values.iframe_2.cookies);
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest, LocalStorageIsShared) {
|
||||
WebContents* site_a_tab1 =
|
||||
LoadURLInNewTab(a_site_ephemeral_storage_with_network_cookies_url_);
|
||||
WebContents* site_a_tab2 = LoadURLInNewTab(a_site_ephemeral_storage_url_);
|
||||
|
||||
SetValuesInFrames(site_a_tab1, "a.com", "from=a.com");
|
||||
ValuesFromFrames site_a_tab1_values = GetValuesFromFrames(site_a_tab1);
|
||||
EXPECT_EQ("a.com", site_a_tab1_values.main_frame.local_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab1_values.iframe_1.local_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab1_values.iframe_2.local_storage);
|
||||
|
||||
EXPECT_EQ("a.com", site_a_tab1_values.main_frame.session_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab1_values.iframe_1.session_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab1_values.iframe_2.session_storage);
|
||||
|
||||
EXPECT_EQ("name=acom_simple; from=a.com",
|
||||
site_a_tab1_values.main_frame.cookies);
|
||||
EXPECT_EQ("name=bcom_simple; from=a.com",
|
||||
site_a_tab1_values.iframe_1.cookies);
|
||||
EXPECT_EQ("name=bcom_simple; from=a.com",
|
||||
site_a_tab1_values.iframe_2.cookies);
|
||||
|
||||
// The second tab is loaded on the same domain, so should see the same
|
||||
// storage for the third-party iframes.
|
||||
ValuesFromFrames site_a_tab2_values = GetValuesFromFrames(site_a_tab2);
|
||||
EXPECT_EQ("a.com", site_a_tab2_values.main_frame.local_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab2_values.iframe_1.local_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab2_values.iframe_2.local_storage);
|
||||
|
||||
EXPECT_EQ(nullptr, site_a_tab2_values.main_frame.session_storage);
|
||||
EXPECT_EQ(nullptr, site_a_tab2_values.iframe_1.session_storage);
|
||||
EXPECT_EQ(nullptr, site_a_tab2_values.iframe_2.session_storage);
|
||||
|
||||
EXPECT_EQ("name=acom_simple; from=a.com",
|
||||
site_a_tab2_values.main_frame.cookies);
|
||||
EXPECT_EQ("name=bcom_simple; from=a.com",
|
||||
site_a_tab2_values.iframe_1.cookies);
|
||||
EXPECT_EQ("name=bcom_simple; from=a.com",
|
||||
site_a_tab2_values.iframe_2.cookies);
|
||||
|
||||
// Set values in the first tab. The second tab should see changes.
|
||||
SetValuesInFrames(site_a_tab1, "a.com-modify", "from=a.com-modify");
|
||||
{
|
||||
ValuesFromFrames site_a_tab2_values = GetValuesFromFrames(site_a_tab2);
|
||||
EXPECT_EQ("a.com-modify", site_a_tab2_values.main_frame.local_storage);
|
||||
EXPECT_EQ("a.com-modify", site_a_tab2_values.iframe_1.local_storage);
|
||||
EXPECT_EQ("a.com-modify", site_a_tab2_values.iframe_2.local_storage);
|
||||
|
||||
EXPECT_EQ(nullptr, site_a_tab2_values.main_frame.session_storage);
|
||||
EXPECT_EQ(nullptr, site_a_tab2_values.iframe_1.session_storage);
|
||||
EXPECT_EQ(nullptr, site_a_tab2_values.iframe_2.session_storage);
|
||||
|
||||
EXPECT_EQ("name=acom_simple; from=a.com-modify",
|
||||
site_a_tab2_values.main_frame.cookies);
|
||||
EXPECT_EQ("name=bcom_simple; from=a.com-modify",
|
||||
site_a_tab2_values.iframe_1.cookies);
|
||||
EXPECT_EQ("name=bcom_simple; from=a.com-modify",
|
||||
site_a_tab2_values.iframe_2.cookies);
|
||||
}
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(EphemeralStorageBrowserTest,
|
||||
FirstPartyNestedInThirdParty) {
|
||||
auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
|
||||
|
||||
@@ -6,12 +6,16 @@
|
||||
#include "brave/browser/ephemeral_storage/ephemeral_storage_tab_helper.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
#include "base/feature_list.h"
|
||||
#include "base/hash/md5.h"
|
||||
#include "base/ranges/ranges.h"
|
||||
#include "base/threading/sequenced_task_runner_handle.h"
|
||||
#include "chrome/browser/content_settings/cookie_settings_factory.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "components/content_settings/core/browser/cookie_settings.h"
|
||||
#include "content/public/browser/navigation_handle.h"
|
||||
#include "content/public/browser/session_storage_namespace.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
@@ -31,7 +35,6 @@ namespace {
|
||||
|
||||
// TODO(bridiver) - share these constants with DOMWindowStorage
|
||||
constexpr char kSessionStorageSuffix[] = "/ephemeral-session-storage";
|
||||
constexpr char kLocalStorageSuffix[] = "/ephemeral-local-storage";
|
||||
|
||||
base::TimeDelta g_storage_keep_alive_for_testing = base::TimeDelta::Min();
|
||||
|
||||
@@ -47,6 +50,23 @@ std::string StringToSessionStorageId(const std::string& string,
|
||||
return hash;
|
||||
}
|
||||
|
||||
class EphemeralStorageOriginsSourceImpl
|
||||
: public content::TLDEphemeralLifetime::EphemeralStorageOriginsSource {
|
||||
public:
|
||||
EphemeralStorageOriginsSourceImpl(
|
||||
scoped_refptr<content_settings::CookieSettings> cookie_settings)
|
||||
: cookie_settings_(std::move(cookie_settings)) {}
|
||||
|
||||
std::vector<url::Origin> TakeEphemeralStorageOpaqueOrigins(
|
||||
const std::string& ephemeral_storage_domain) override {
|
||||
return cookie_settings_->TakeEphemeralStorageOpaqueOrigins(
|
||||
ephemeral_storage_domain);
|
||||
}
|
||||
|
||||
private:
|
||||
scoped_refptr<content_settings::CookieSettings> cookie_settings_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// EphemeralStorageTabHelper helps to manage the lifetime of ephemeral storage.
|
||||
@@ -68,7 +88,6 @@ EphemeralStorageTabHelper::~EphemeralStorageTabHelper() {}
|
||||
|
||||
void EphemeralStorageTabHelper::WebContentsDestroyed() {
|
||||
keep_alive_tld_ephemeral_lifetime_list_.clear();
|
||||
keep_alive_local_storage_list_.clear();
|
||||
}
|
||||
|
||||
void EphemeralStorageTabHelper::ReadyToCommitNavigation(
|
||||
@@ -91,9 +110,6 @@ void EphemeralStorageTabHelper::ReadyToCommitNavigation(
|
||||
|
||||
void EphemeralStorageTabHelper::ClearEphemeralLifetimeKeepalive(
|
||||
const content::TLDEphemeralLifetimeKey& key) {
|
||||
ClearLocalStorageKeepAlive(
|
||||
StringToSessionStorageId(key.second, kLocalStorageSuffix));
|
||||
|
||||
auto it = base::ranges::find_if(keep_alive_tld_ephemeral_lifetime_list_,
|
||||
[&key](const auto& tld_ephermal_liftime) {
|
||||
return tld_ephermal_liftime->key() == key;
|
||||
@@ -102,15 +118,6 @@ void EphemeralStorageTabHelper::ClearEphemeralLifetimeKeepalive(
|
||||
keep_alive_tld_ephemeral_lifetime_list_.erase(it);
|
||||
}
|
||||
|
||||
void EphemeralStorageTabHelper::ClearLocalStorageKeepAlive(
|
||||
const std::string& id) {
|
||||
auto it = base::ranges::find_if(
|
||||
keep_alive_local_storage_list_,
|
||||
[&id](const auto& local_storage) { return local_storage->id() == id; });
|
||||
if (it != keep_alive_local_storage_list_.end())
|
||||
keep_alive_local_storage_list_.erase(it);
|
||||
}
|
||||
|
||||
void EphemeralStorageTabHelper::CreateEphemeralStorageAreasForDomainAndURL(
|
||||
const std::string& new_domain,
|
||||
const GURL& new_url) {
|
||||
@@ -126,7 +133,6 @@ void EphemeralStorageTabHelper::CreateEphemeralStorageAreasForDomainAndURL(
|
||||
net::features::kBraveEphemeralStorageKeepAlive) &&
|
||||
tld_ephemeral_lifetime_) {
|
||||
keep_alive_tld_ephemeral_lifetime_list_.push_back(tld_ephemeral_lifetime_);
|
||||
keep_alive_local_storage_list_.push_back(local_storage_namespace_);
|
||||
|
||||
// keep the ephemeral storage alive for some time to handle redirects
|
||||
// including meta refresh or other page driven "redirects" that end up back
|
||||
@@ -143,15 +149,6 @@ void EphemeralStorageTabHelper::CreateEphemeralStorageAreasForDomainAndURL(
|
||||
: g_storage_keep_alive_for_testing);
|
||||
}
|
||||
|
||||
// This will fetch a session storage namespace for this storage partition
|
||||
// and storage domain. If another tab helper is already using the same
|
||||
// namespace, this will just give us a new reference. When the last tab helper
|
||||
// drops the reference, the namespace should be deleted.
|
||||
std::string local_partition_id =
|
||||
StringToSessionStorageId(new_domain, kLocalStorageSuffix);
|
||||
local_storage_namespace_ = content::CreateSessionStorageNamespace(
|
||||
partition, local_partition_id, absl::nullopt);
|
||||
|
||||
// Session storage is always per-tab and never per-TLD, so we always delete
|
||||
// and recreate the session storage when switching domains.
|
||||
//
|
||||
@@ -176,7 +173,10 @@ void EphemeralStorageTabHelper::CreateEphemeralStorageAreasForDomainAndURL(
|
||||
: absl::nullopt);
|
||||
|
||||
tld_ephemeral_lifetime_ = content::TLDEphemeralLifetime::GetOrCreate(
|
||||
browser_context, partition, new_domain);
|
||||
browser_context, partition, new_domain,
|
||||
std::make_unique<EphemeralStorageOriginsSourceImpl>(
|
||||
CookieSettingsFactory::GetForProfile(
|
||||
Profile::FromBrowserContext(browser_context))));
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -45,20 +45,16 @@ class EphemeralStorageTabHelper
|
||||
|
||||
void ClearEphemeralLifetimeKeepalive(
|
||||
const content::TLDEphemeralLifetimeKey& key);
|
||||
void ClearLocalStorageKeepAlive(const std::string& id);
|
||||
|
||||
void CreateEphemeralStorageAreasForDomainAndURL(const std::string& new_domain,
|
||||
const GURL& new_url);
|
||||
|
||||
friend class content::WebContentsUserData<EphemeralStorageTabHelper>;
|
||||
scoped_refptr<content::SessionStorageNamespace> local_storage_namespace_;
|
||||
scoped_refptr<content::SessionStorageNamespace> session_storage_namespace_;
|
||||
scoped_refptr<content::TLDEphemeralLifetime> tld_ephemeral_lifetime_;
|
||||
|
||||
std::vector<scoped_refptr<content::TLDEphemeralLifetime>>
|
||||
keep_alive_tld_ephemeral_lifetime_list_;
|
||||
std::vector<scoped_refptr<content::SessionStorageNamespace>>
|
||||
keep_alive_local_storage_list_;
|
||||
|
||||
base::WeakPtrFactory<EphemeralStorageTabHelper> weak_factory_{this};
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
brave_browser_ephemeral_storage_sources = [
|
||||
"//brave/browser/ephemeral_storage/ephemeral_storage_tab_helper.cc",
|
||||
"//brave/browser/ephemeral_storage/ephemeral_storage_tab_helper.h",
|
||||
]
|
||||
|
||||
brave_browser_ephemeral_storage_deps = [
|
||||
"//base",
|
||||
"//chrome/browser/profiles",
|
||||
"//chrome/browser/ui",
|
||||
"//components/content_settings/core/browser",
|
||||
"//content/public/browser",
|
||||
"//net",
|
||||
"//third_party/blink/public/common",
|
||||
]
|
||||
@@ -13,7 +13,6 @@ if (!is_android) {
|
||||
|
||||
deps = [
|
||||
"//brave/browser",
|
||||
"//brave/browser/ephemeral_storage",
|
||||
"//chrome/browser",
|
||||
"//chrome/browser/ui",
|
||||
"//chrome/test:test_support",
|
||||
|
||||
+3
-1
@@ -14,6 +14,7 @@ import("//brave/browser/component_updater/sources.gni")
|
||||
import("//brave/browser/crypto_dot_com/sources.gni")
|
||||
import("//brave/browser/decentralized_dns/sources.gni")
|
||||
import("//brave/browser/download/sources.gni")
|
||||
import("//brave/browser/ephemeral_storage/sources.gni")
|
||||
import("//brave/browser/ethereum_remote_client/buildflags/buildflags.gni")
|
||||
import("//brave/browser/gemini/sources.gni")
|
||||
import("//brave/browser/greaselion/sources.gni")
|
||||
@@ -93,7 +94,6 @@ brave_chrome_browser_deps = [
|
||||
"//brave/browser/brave_ads/notifications",
|
||||
"//brave/browser/component_updater",
|
||||
"//brave/browser/content_settings",
|
||||
"//brave/browser/ephemeral_storage",
|
||||
"//brave/browser/gcm_driver",
|
||||
"//brave/browser/net",
|
||||
"//brave/browser/ntp_background_images",
|
||||
@@ -340,6 +340,7 @@ brave_chrome_browser_sources += brave_browser_component_updater_sources
|
||||
brave_chrome_browser_sources += brave_browser_crypto_dot_com_sources
|
||||
brave_chrome_browser_sources += brave_browser_decentralized_dns_sources
|
||||
brave_chrome_browser_sources += brave_browser_download_sources
|
||||
brave_chrome_browser_sources += brave_browser_ephemeral_storage_sources
|
||||
brave_chrome_browser_sources += brave_browser_gemini_sources
|
||||
brave_chrome_browser_sources += brave_browser_greaselion_sources
|
||||
brave_chrome_browser_sources += brave_browser_importer_sources
|
||||
@@ -361,6 +362,7 @@ brave_chrome_browser_deps += brave_browser_component_updater_deps
|
||||
brave_chrome_browser_deps += brave_browser_crypto_dot_com_deps
|
||||
brave_chrome_browser_deps += brave_browser_decentralized_dns_deps
|
||||
brave_chrome_browser_deps += brave_browser_download_deps
|
||||
brave_chrome_browser_deps += brave_browser_ephemeral_storage_deps
|
||||
brave_chrome_browser_deps += brave_browser_gemini_deps
|
||||
brave_chrome_browser_deps += brave_browser_greaselion_deps
|
||||
brave_chrome_browser_deps += brave_browser_importer_deps
|
||||
|
||||
@@ -15,9 +15,13 @@ void ContentSettingsManagerImpl::AllowEphemeralStorageAccess(
|
||||
const url::Origin& origin,
|
||||
const GURL& site_for_cookies,
|
||||
const url::Origin& top_frame_origin,
|
||||
base::OnceCallback<void(bool)> callback) {
|
||||
std::move(callback).Run(cookie_settings_->ShouldUseEphemeralStorage(
|
||||
origin.GetURL(), site_for_cookies, top_frame_origin));
|
||||
AllowEphemeralStorageAccessCallback callback) {
|
||||
url::Origin storage_origin;
|
||||
const bool should_use = cookie_settings_->ShouldUseEphemeralStorage(
|
||||
origin, site_for_cookies, top_frame_origin, storage_origin);
|
||||
std::move(callback).Run(should_use
|
||||
? absl::make_optional<url::Origin>(storage_origin)
|
||||
: absl::nullopt);
|
||||
}
|
||||
|
||||
} // namespace content_settings
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#ifndef BRAVE_CHROMIUM_SRC_COMPONENTS_CONTENT_SETTINGS_BROWSER_CONTENT_SETTINGS_MANAGER_IMPL_H_
|
||||
#define BRAVE_CHROMIUM_SRC_COMPONENTS_CONTENT_SETTINGS_BROWSER_CONTENT_SETTINGS_MANAGER_IMPL_H_
|
||||
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "components/content_settings/common/content_settings_manager.mojom.h"
|
||||
|
||||
#define OnContentBlocked \
|
||||
@@ -14,7 +15,7 @@
|
||||
int32_t render_frame_id, StorageType storage_type, \
|
||||
const url::Origin& origin, const GURL& site_for_cookies, \
|
||||
const url::Origin& top_frame_origin, \
|
||||
base::OnceCallback<void(bool)> callback) override; \
|
||||
AllowEphemeralStorageAccessCallback callback) override; \
|
||||
void OnContentBlocked
|
||||
|
||||
#include "../../../../../components/content_settings/browser/content_settings_manager_impl.h"
|
||||
|
||||
@@ -11,5 +11,5 @@ interface ContentSettingsManager {
|
||||
StorageType storage_type,
|
||||
url.mojom.Origin origin,
|
||||
url.mojom.Url site_for_cookies,
|
||||
url.mojom.Origin top_frame_origin) => (bool ephemeral_storage_allowed);
|
||||
url.mojom.Origin top_frame_origin) => (url.mojom.Origin? storage_origin);
|
||||
};
|
||||
|
||||
@@ -2,4 +2,5 @@ include_rules = [
|
||||
"+../../../../../../components/content_settings/core/browser",
|
||||
"+components/content_settings/core/browser",
|
||||
"+components/content_settings/core/common",
|
||||
"+components/keyed_service/core",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "components/content_settings/core/browser/cookie_settings.h"
|
||||
|
||||
#include "net/base/url_util.h"
|
||||
|
||||
#define ShutdownOnUIThread ShutdownOnUIThread_ChromiumImpl
|
||||
|
||||
#include "../../../../../../components/content_settings/core/browser/cookie_settings.cc"
|
||||
|
||||
#undef ShutdownOnUIThread
|
||||
|
||||
namespace content_settings {
|
||||
|
||||
void CookieSettings::ShutdownOnUIThread() {
|
||||
ShutdownOnUIThread_ChromiumImpl();
|
||||
ephemeral_storage_origins_.clear();
|
||||
}
|
||||
|
||||
bool CookieSettings::ShouldUseEphemeralStorage(
|
||||
const url::Origin& origin,
|
||||
const GURL& site_for_cookies,
|
||||
const absl::optional<url::Origin>& top_frame_origin,
|
||||
url::Origin& storage_origin) {
|
||||
const bool should_use = CookieSettingsBase::ShouldUseEphemeralStorage(
|
||||
origin.GetURL(), site_for_cookies, top_frame_origin);
|
||||
if (!should_use) {
|
||||
return false;
|
||||
}
|
||||
DCHECK(top_frame_origin);
|
||||
const std::string ephemeral_storage_domain =
|
||||
net::URLToEphemeralStorageDomain(top_frame_origin->GetURL());
|
||||
|
||||
auto ephemeral_storage_origins_it =
|
||||
ephemeral_storage_origins_.find(ephemeral_storage_domain);
|
||||
if (ephemeral_storage_origins_it != ephemeral_storage_origins_.end()) {
|
||||
const auto& storage_origins = ephemeral_storage_origins_it->second;
|
||||
auto storage_origin_it = storage_origins.find(origin);
|
||||
if (storage_origin_it != storage_origins.end()) {
|
||||
storage_origin = storage_origin_it->second;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
ephemeral_storage_origins_it =
|
||||
ephemeral_storage_origins_
|
||||
.emplace(ephemeral_storage_domain,
|
||||
EphemeralStorageOrigins::mapped_type())
|
||||
.first;
|
||||
}
|
||||
|
||||
url::Origin opaque_origin = origin.DeriveNewOpaqueOrigin();
|
||||
ephemeral_storage_origins_it->second[origin] = opaque_origin;
|
||||
storage_origin = std::move(opaque_origin);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<url::Origin> CookieSettings::TakeEphemeralStorageOpaqueOrigins(
|
||||
const std::string& ephemeral_storage_domain) {
|
||||
std::vector<url::Origin> result;
|
||||
auto ephemeral_storage_origins_it =
|
||||
ephemeral_storage_origins_.find(ephemeral_storage_domain);
|
||||
if (ephemeral_storage_origins_it != ephemeral_storage_origins_.end()) {
|
||||
result.reserve(ephemeral_storage_origins_it->second.size());
|
||||
for (auto& origins : ephemeral_storage_origins_it->second) {
|
||||
result.push_back(std::move(origins.second));
|
||||
}
|
||||
ephemeral_storage_origins_.erase(ephemeral_storage_origins_it);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace content_settings
|
||||
|
||||
#undef BRAVE_COOKIE_SETTINGS_GET_COOKIES_SETTINGS_INTERNAL
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_CHROMIUM_SRC_COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_COOKIE_SETTINGS_H_
|
||||
#define BRAVE_CHROMIUM_SRC_COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_COOKIE_SETTINGS_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "components/content_settings/core/browser/content_settings_provider.h"
|
||||
#include "components/keyed_service/core/refcounted_keyed_service.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
#define ShutdownOnUIThread \
|
||||
ShutdownOnUIThread_ChromiumImpl(); \
|
||||
bool ShouldUseEphemeralStorage( \
|
||||
const url::Origin& origin, const GURL& site_for_cookies, \
|
||||
const absl::optional<url::Origin>& top_frame_origin, \
|
||||
url::Origin& storage_origin); \
|
||||
std::vector<url::Origin> TakeEphemeralStorageOpaqueOrigins( \
|
||||
const std::string& ephemeral_storage_domain); \
|
||||
\
|
||||
private: \
|
||||
/* Ephemeral storage domain to non_opaque->opaque origins map. */ \
|
||||
using EphemeralStorageOrigins = \
|
||||
base::flat_map<std::string, base::flat_map<url::Origin, url::Origin>>; \
|
||||
EphemeralStorageOrigins ephemeral_storage_origins_; \
|
||||
\
|
||||
public: \
|
||||
void ShutdownOnUIThread
|
||||
|
||||
#include "../../../../../../components/content_settings/core/browser/cookie_settings.h"
|
||||
|
||||
#undef ShutdownOnUIThread
|
||||
|
||||
#endif // BRAVE_CHROMIUM_SRC_COMPONENTS_CONTENT_SETTINGS_CORE_BROWSER_COOKIE_SETTINGS_H_
|
||||
@@ -1,4 +1,5 @@
|
||||
include_rules = [
|
||||
"+../../../../../../components/content_settings/core/common",
|
||||
"+components/content_settings/common",
|
||||
"+components/content_settings/core/common",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
include_rules = [
|
||||
"+../../../../../../components/services/storage",
|
||||
"+components/services/storage",
|
||||
]
|
||||
@@ -0,0 +1,119 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "components/services/storage/dom_storage/local_storage_impl.h"
|
||||
|
||||
#define LocalStorageImpl LocalStorageImpl_ChromiumImpl
|
||||
|
||||
#include "../../../../../../components/services/storage/dom_storage/local_storage_impl.cc"
|
||||
|
||||
#undef LocalStorageImpl
|
||||
|
||||
namespace storage {
|
||||
|
||||
LocalStorageImpl::LocalStorageImpl(
|
||||
const base::FilePath& storage_root,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner,
|
||||
scoped_refptr<base::SequencedTaskRunner> legacy_task_runner,
|
||||
mojo::PendingReceiver<mojom::LocalStorageControl> receiver)
|
||||
: local_storage_(std::make_unique<LocalStorageImpl_ChromiumImpl>(
|
||||
storage_root,
|
||||
task_runner,
|
||||
legacy_task_runner,
|
||||
mojo::PendingReceiver<mojom::LocalStorageControl>())),
|
||||
in_memory_local_storage_(std::make_unique<LocalStorageImpl_ChromiumImpl>(
|
||||
base::FilePath(),
|
||||
task_runner,
|
||||
legacy_task_runner,
|
||||
mojo::PendingReceiver<mojom::LocalStorageControl>())) {
|
||||
if (receiver)
|
||||
control_receiver_.Bind(std::move(receiver));
|
||||
}
|
||||
|
||||
LocalStorageImpl::~LocalStorageImpl() = default;
|
||||
|
||||
void LocalStorageImpl::ShutDown(base::OnceClosure callback) {
|
||||
local_storage_->ShutDown(
|
||||
base::BindOnce(&LocalStorageImpl::ShutDownInMemoryStorage,
|
||||
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
|
||||
}
|
||||
|
||||
void LocalStorageImpl::BindStorageArea(
|
||||
const url::Origin& origin,
|
||||
mojo::PendingReceiver<blink::mojom::StorageArea> receiver) {
|
||||
if (origin.opaque()) {
|
||||
in_memory_local_storage_->BindStorageArea(*GetNonOpaqueOrigin(origin, true),
|
||||
std::move(receiver));
|
||||
} else {
|
||||
local_storage_->BindStorageArea(origin, std::move(receiver));
|
||||
}
|
||||
}
|
||||
|
||||
void LocalStorageImpl::GetUsage(GetUsageCallback callback) {
|
||||
local_storage_->GetUsage(std::move(callback));
|
||||
}
|
||||
|
||||
void LocalStorageImpl::DeleteStorage(const url::Origin& origin,
|
||||
DeleteStorageCallback callback) {
|
||||
if (origin.opaque()) {
|
||||
if (const auto* non_opaque_origin = GetNonOpaqueOrigin(origin, false)) {
|
||||
in_memory_local_storage_->DeleteStorage(*non_opaque_origin,
|
||||
std::move(callback));
|
||||
non_opaque_origins_.erase(origin);
|
||||
}
|
||||
} else {
|
||||
local_storage_->DeleteStorage(origin, std::move(callback));
|
||||
}
|
||||
}
|
||||
|
||||
void LocalStorageImpl::CleanUpStorage(CleanUpStorageCallback callback) {
|
||||
local_storage_->CleanUpStorage(std::move(callback));
|
||||
}
|
||||
|
||||
void LocalStorageImpl::Flush(FlushCallback callback) {
|
||||
local_storage_->Flush(std::move(callback));
|
||||
}
|
||||
|
||||
void LocalStorageImpl::PurgeMemory() {
|
||||
local_storage_->PurgeMemory();
|
||||
}
|
||||
|
||||
void LocalStorageImpl::ApplyPolicyUpdates(
|
||||
std::vector<mojom::StoragePolicyUpdatePtr> policy_updates) {
|
||||
local_storage_->ApplyPolicyUpdates(std::move(policy_updates));
|
||||
}
|
||||
|
||||
void LocalStorageImpl::ForceKeepSessionState() {
|
||||
local_storage_->ForceKeepSessionState();
|
||||
}
|
||||
|
||||
const url::Origin* LocalStorageImpl::GetNonOpaqueOrigin(
|
||||
const url::Origin& origin,
|
||||
bool create) {
|
||||
DCHECK(origin.opaque());
|
||||
auto non_opaque_origin_it = non_opaque_origins_.find(origin);
|
||||
if (non_opaque_origin_it != non_opaque_origins_.end()) {
|
||||
return &non_opaque_origin_it->second;
|
||||
}
|
||||
if (!create) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& origin_scheme_host_port =
|
||||
origin.GetTupleOrPrecursorTupleIfOpaque();
|
||||
auto emplaced_pair = non_opaque_origins_.emplace(
|
||||
origin,
|
||||
url::Origin::CreateFromNormalizedTuple(
|
||||
origin_scheme_host_port.scheme(),
|
||||
base::ToLowerASCII(base::UnguessableToken::Create().ToString()),
|
||||
origin_scheme_host_port.port()));
|
||||
return &emplaced_pair.first->second;
|
||||
}
|
||||
|
||||
void LocalStorageImpl::ShutDownInMemoryStorage(base::OnceClosure callback) {
|
||||
in_memory_local_storage_->ShutDown(std::move(callback));
|
||||
}
|
||||
|
||||
} // namespace storage
|
||||
@@ -0,0 +1,58 @@
|
||||
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_CHROMIUM_SRC_COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_LOCAL_STORAGE_IMPL_H_
|
||||
#define BRAVE_CHROMIUM_SRC_COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_LOCAL_STORAGE_IMPL_H_
|
||||
|
||||
#define LocalStorageImpl LocalStorageImpl_ChromiumImpl
|
||||
|
||||
#include "../../../../../../components/services/storage/dom_storage/local_storage_impl.h"
|
||||
|
||||
#undef LocalStorageImpl
|
||||
|
||||
namespace storage {
|
||||
|
||||
class LocalStorageImpl : public mojom::LocalStorageControl {
|
||||
public:
|
||||
LocalStorageImpl(const base::FilePath& storage_root,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner,
|
||||
scoped_refptr<base::SequencedTaskRunner> legacy_task_runner,
|
||||
mojo::PendingReceiver<mojom::LocalStorageControl> receiver);
|
||||
~LocalStorageImpl() override;
|
||||
|
||||
void ShutDown(base::OnceClosure callback);
|
||||
|
||||
// mojom::LocalStorageControl implementation:
|
||||
void BindStorageArea(
|
||||
const url::Origin& origin,
|
||||
mojo::PendingReceiver<blink::mojom::StorageArea> receiver) override;
|
||||
void GetUsage(GetUsageCallback callback) override;
|
||||
void DeleteStorage(const url::Origin& origin,
|
||||
DeleteStorageCallback callback) override;
|
||||
void CleanUpStorage(CleanUpStorageCallback callback) override;
|
||||
void Flush(FlushCallback callback) override;
|
||||
void PurgeMemory() override;
|
||||
void ApplyPolicyUpdates(
|
||||
std::vector<mojom::StoragePolicyUpdatePtr> policy_updates) override;
|
||||
void ForceKeepSessionState() override;
|
||||
|
||||
private:
|
||||
const url::Origin* GetNonOpaqueOrigin(const url::Origin& origin, bool create);
|
||||
|
||||
void ShutDownInMemoryStorage(base::OnceClosure callback);
|
||||
|
||||
std::unique_ptr<LocalStorageImpl_ChromiumImpl> local_storage_;
|
||||
std::unique_ptr<LocalStorageImpl_ChromiumImpl> in_memory_local_storage_;
|
||||
mojo::Receiver<mojom::LocalStorageControl> control_receiver_{this};
|
||||
// LocalStorageImpl works only with non-opaque origins, that's why we use an
|
||||
// opaque->non-opaque origin map.
|
||||
std::map<url::Origin, url::Origin> non_opaque_origins_;
|
||||
|
||||
base::WeakPtrFactory<LocalStorageImpl> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace storage
|
||||
|
||||
#endif // BRAVE_CHROMIUM_SRC_COMPONENTS_SERVICES_STORAGE_DOM_STORAGE_LOCAL_STORAGE_IMPL_H_
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <map>
|
||||
|
||||
#include "base/no_destructor.h"
|
||||
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
|
||||
#include "services/network/public/mojom/cookie_manager.mojom.h"
|
||||
|
||||
namespace content {
|
||||
@@ -28,12 +29,19 @@ TLDEphemeralLifetimeMap& active_tld_storage_areas() {
|
||||
|
||||
} // namespace
|
||||
|
||||
TLDEphemeralLifetime::TLDEphemeralLifetime(const TLDEphemeralLifetimeKey& key,
|
||||
StoragePartition* storage_partition)
|
||||
: key_(key), storage_partition_(storage_partition) {
|
||||
TLDEphemeralLifetime::TLDEphemeralLifetime(
|
||||
const TLDEphemeralLifetimeKey& key,
|
||||
StoragePartition* storage_partition,
|
||||
std::unique_ptr<EphemeralStorageOriginsSource>
|
||||
ephemeral_storage_origins_source)
|
||||
: key_(key),
|
||||
storage_partition_(storage_partition),
|
||||
ephemeral_storage_origins_source_(
|
||||
std::move(ephemeral_storage_origins_source)) {
|
||||
DCHECK(active_tld_storage_areas().find(key_) ==
|
||||
active_tld_storage_areas().end());
|
||||
DCHECK(storage_partition_);
|
||||
DCHECK(ephemeral_storage_origins_source_);
|
||||
active_tld_storage_areas().emplace(key_, weak_factory_.GetWeakPtr());
|
||||
}
|
||||
|
||||
@@ -42,6 +50,12 @@ TLDEphemeralLifetime::~TLDEphemeralLifetime() {
|
||||
filter->ephemeral_storage_domain = key_.second;
|
||||
storage_partition_->GetCookieManagerForBrowserProcess()->DeleteCookies(
|
||||
std::move(filter), base::NullCallback());
|
||||
for (const auto& opaque_origin :
|
||||
ephemeral_storage_origins_source_->TakeEphemeralStorageOpaqueOrigins(
|
||||
key_.second)) {
|
||||
storage_partition_->GetDOMStorageContext()->DeleteLocalStorage(
|
||||
opaque_origin, base::DoNothing());
|
||||
}
|
||||
|
||||
if (!on_destroy_callbacks_.empty()) {
|
||||
auto on_destroy_callbacks = std::move(on_destroy_callbacks_);
|
||||
@@ -65,13 +79,16 @@ TLDEphemeralLifetime* TLDEphemeralLifetime::Get(
|
||||
scoped_refptr<TLDEphemeralLifetime> TLDEphemeralLifetime::GetOrCreate(
|
||||
BrowserContext* browser_context,
|
||||
StoragePartition* storage_partition,
|
||||
const std::string& storage_domain) {
|
||||
const std::string& storage_domain,
|
||||
std::unique_ptr<EphemeralStorageOriginsSource>
|
||||
ephemeral_storage_origins_source) {
|
||||
const TLDEphemeralLifetimeKey key(browser_context, storage_domain);
|
||||
if (scoped_refptr<TLDEphemeralLifetime> existing = Get(key)) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
return base::MakeRefCounted<TLDEphemeralLifetime>(key, storage_partition);
|
||||
return base::MakeRefCounted<TLDEphemeralLifetime>(
|
||||
key, storage_partition, std::move(ephemeral_storage_origins_source));
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -11,9 +11,11 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/containers/flat_map.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/common/content_export.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
@@ -41,14 +43,26 @@ class CONTENT_EXPORT TLDEphemeralLifetime
|
||||
public:
|
||||
using OnDestroyCallback = base::OnceCallback<void(const std::string&)>;
|
||||
|
||||
class EphemeralStorageOriginsSource {
|
||||
public:
|
||||
virtual ~EphemeralStorageOriginsSource() = default;
|
||||
|
||||
virtual std::vector<url::Origin> TakeEphemeralStorageOpaqueOrigins(
|
||||
const std::string& ephemeral_storage_domain) = 0;
|
||||
};
|
||||
|
||||
TLDEphemeralLifetime(const TLDEphemeralLifetimeKey& key,
|
||||
StoragePartition* storage_partition);
|
||||
StoragePartition* storage_partition,
|
||||
std::unique_ptr<EphemeralStorageOriginsSource>
|
||||
ephemeral_storage_origins_source);
|
||||
static TLDEphemeralLifetime* Get(BrowserContext* browser_context,
|
||||
const std::string& storage_domain);
|
||||
static scoped_refptr<TLDEphemeralLifetime> GetOrCreate(
|
||||
BrowserContext* browser_context,
|
||||
StoragePartition* storage_partition,
|
||||
const std::string& storage_domain);
|
||||
const std::string& storage_domain,
|
||||
std::unique_ptr<EphemeralStorageOriginsSource>
|
||||
ephemeral_storage_origins_source);
|
||||
|
||||
// Add a callback to a callback list to be called on destruction.
|
||||
void RegisterOnDestroyCallback(OnDestroyCallback callback);
|
||||
@@ -63,6 +77,8 @@ class CONTENT_EXPORT TLDEphemeralLifetime
|
||||
|
||||
TLDEphemeralLifetimeKey key_;
|
||||
StoragePartition* storage_partition_;
|
||||
std::unique_ptr<EphemeralStorageOriginsSource>
|
||||
ephemeral_storage_origins_source_;
|
||||
std::vector<OnDestroyCallback> on_destroy_callbacks_;
|
||||
|
||||
base::WeakPtrFactory<TLDEphemeralLifetime> weak_factory_{this};
|
||||
|
||||
+4
-2
@@ -7,6 +7,7 @@
|
||||
#define BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_CONTENT_SETTINGS_CLIENT_H_
|
||||
|
||||
#include "brave/third_party/blink/renderer/brave_farbling_constants.h"
|
||||
#include "third_party/blink/public/platform/web_security_origin.h"
|
||||
|
||||
#define AllowStorageAccessSync \
|
||||
AllowAutoplay(bool play_requested) { return true; } \
|
||||
@@ -16,8 +17,9 @@
|
||||
virtual BraveFarblingLevel GetBraveFarblingLevel() { \
|
||||
return BraveFarblingLevel::OFF; \
|
||||
} \
|
||||
virtual bool UseEphemeralStorageSync(StorageType storageType) { \
|
||||
return false; \
|
||||
virtual blink::WebSecurityOrigin GetEphemeralStorageOriginSync( \
|
||||
StorageType storageType) { \
|
||||
return blink::WebSecurityOrigin(); \
|
||||
} \
|
||||
virtual bool AllowStorageAccessSync
|
||||
|
||||
|
||||
+2
-1
@@ -33,7 +33,8 @@ class BraveDOMWindowStorage final
|
||||
|
||||
private:
|
||||
StorageArea* ephemeralSessionStorage();
|
||||
StorageArea* ephemeralLocalStorage();
|
||||
StorageArea* ephemeralLocalStorage(
|
||||
const SecurityOrigin* ephemeral_storage_origin);
|
||||
|
||||
mutable Member<StorageArea> ephemeral_session_storage_;
|
||||
mutable Member<StorageArea> ephemeral_local_storage_;
|
||||
|
||||
+44
-76
@@ -20,7 +20,6 @@ namespace blink {
|
||||
namespace {
|
||||
|
||||
constexpr char kSessionStorageSuffix[] = "/ephemeral-session-storage";
|
||||
constexpr char kLocalStorageSuffix[] = "/ephemeral-local-storage";
|
||||
|
||||
// This replicates the conversion of a string into a session storage namespace
|
||||
// id that is found in the implementation of EphemeralStorageTabHelper.
|
||||
@@ -32,80 +31,73 @@ String StringToSessionStorageId(const String& string,
|
||||
return String(hash.c_str());
|
||||
}
|
||||
|
||||
bool ShouldUseEphemeralStorage(
|
||||
const SecurityOrigin* GetEphemeralStorageOrigin(
|
||||
LocalDOMWindow* window,
|
||||
WebContentSettingsClient::StorageType storage_type) {
|
||||
auto* frame = window->GetFrame();
|
||||
if (!frame)
|
||||
return false;
|
||||
return nullptr;
|
||||
|
||||
if (auto* settings_client = frame->GetContentSettingsClient())
|
||||
return settings_client->UseEphemeralStorageSync(storage_type);
|
||||
return settings_client->GetEphemeralStorageOriginSync(storage_type).Get();
|
||||
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// EphemeralStorageNamespace manage ephemeral storage namespaces for a
|
||||
// particular Page object. The namespaces are instantiated on the Page lazily,
|
||||
// as soon as a third-party frame needs ephemeral storage. They are then shared
|
||||
// by all third-party frames that are embedded in this Page.
|
||||
// EphemeralSessionStorageNamespace manages ephemeral sessionStorage namespace
|
||||
// for a particular Page object. The namespace is instantiated on the Page
|
||||
// lazily, as soon as a third-party frame needs ephemeral sessionStorage. It's
|
||||
// then shared by all third-party frames that are embedded in this Page.
|
||||
//
|
||||
// These namespaces are created in the browser process ahead of time. We ensure
|
||||
// The namespace is created in the browser process ahead of time. We ensure
|
||||
// that we are using the same namespace by using a common naming scheme.
|
||||
class EphemeralStorageNamespaces
|
||||
: public GarbageCollected<EphemeralStorageNamespaces>,
|
||||
class EphemeralSessionStorageNamespace
|
||||
: public GarbageCollected<EphemeralSessionStorageNamespace>,
|
||||
public Supplement<Page> {
|
||||
public:
|
||||
EphemeralStorageNamespaces(StorageController* controller,
|
||||
const String& session_storage_id,
|
||||
const String& local_storage_id);
|
||||
virtual ~EphemeralStorageNamespaces() = default;
|
||||
EphemeralSessionStorageNamespace(StorageController* controller,
|
||||
const String& session_storage_id);
|
||||
virtual ~EphemeralSessionStorageNamespace() = default;
|
||||
|
||||
static const char kSupplementName[];
|
||||
static EphemeralStorageNamespaces* From(Page* page, LocalDOMWindow* window);
|
||||
static EphemeralSessionStorageNamespace* From(Page* page,
|
||||
LocalDOMWindow* window);
|
||||
|
||||
StorageNamespace* session_storage() { return session_storage_.Get(); }
|
||||
StorageNamespace* local_storage() { return local_storage_.Get(); }
|
||||
void Trace(Visitor* visitor) const override;
|
||||
|
||||
private:
|
||||
Member<StorageNamespace> session_storage_;
|
||||
Member<StorageNamespace> local_storage_;
|
||||
};
|
||||
|
||||
const char EphemeralStorageNamespaces::kSupplementName[] =
|
||||
"EphemeralStorageNamespaces";
|
||||
const char EphemeralSessionStorageNamespace::kSupplementName[] =
|
||||
"EphemeralSessionStorageNamespace";
|
||||
|
||||
EphemeralStorageNamespaces::EphemeralStorageNamespaces(
|
||||
EphemeralSessionStorageNamespace::EphemeralSessionStorageNamespace(
|
||||
StorageController* controller,
|
||||
const String& session_storage_id,
|
||||
const String& local_storage_id)
|
||||
const String& session_storage_id)
|
||||
: Supplement(nullptr),
|
||||
session_storage_(
|
||||
MakeGarbageCollected<StorageNamespace>(controller,
|
||||
session_storage_id)),
|
||||
local_storage_(MakeGarbageCollected<StorageNamespace>(controller,
|
||||
local_storage_id)) {
|
||||
}
|
||||
session_storage_id)) {}
|
||||
|
||||
void EphemeralStorageNamespaces::Trace(Visitor* visitor) const {
|
||||
void EphemeralSessionStorageNamespace::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(session_storage_);
|
||||
visitor->Trace(local_storage_);
|
||||
Supplement<Page>::Trace(visitor);
|
||||
}
|
||||
|
||||
// static
|
||||
EphemeralStorageNamespaces* EphemeralStorageNamespaces::From(
|
||||
EphemeralSessionStorageNamespace* EphemeralSessionStorageNamespace::From(
|
||||
Page* page,
|
||||
LocalDOMWindow* window) {
|
||||
DCHECK(window);
|
||||
if (!page)
|
||||
return nullptr;
|
||||
|
||||
EphemeralStorageNamespaces* supplement =
|
||||
Supplement<Page>::From<EphemeralStorageNamespaces>(page);
|
||||
EphemeralSessionStorageNamespace* supplement =
|
||||
Supplement<Page>::From<EphemeralSessionStorageNamespace>(page);
|
||||
if (supplement)
|
||||
return supplement;
|
||||
|
||||
@@ -117,20 +109,8 @@ EphemeralStorageNamespaces* EphemeralStorageNamespaces::From(
|
||||
String::FromUTF8(webview->GetSessionStorageNamespaceId()),
|
||||
kSessionStorageSuffix);
|
||||
|
||||
auto* security_origin =
|
||||
page->MainFrame()->GetSecurityContext()->GetSecurityOrigin();
|
||||
String domain = security_origin->RegistrableDomain();
|
||||
// RegistrableDomain might return an empty string if this host is an IP
|
||||
// address or a file URL.
|
||||
if (domain.IsEmpty()) {
|
||||
url::Origin origin = url::Origin::Create(GURL(window->Url()).GetOrigin());
|
||||
domain = String::FromUTF8(origin.Serialize());
|
||||
}
|
||||
|
||||
String local_storage_id =
|
||||
StringToSessionStorageId(domain, kLocalStorageSuffix);
|
||||
supplement = MakeGarbageCollected<EphemeralStorageNamespaces>(
|
||||
StorageController::GetInstance(), session_storage_id, local_storage_id);
|
||||
supplement = MakeGarbageCollected<EphemeralSessionStorageNamespace>(
|
||||
StorageController::GetInstance(), session_storage_id);
|
||||
|
||||
ProvideTo(*page, supplement);
|
||||
return supplement;
|
||||
@@ -173,7 +153,7 @@ StorageArea* BraveDOMWindowStorage::sessionStorage(
|
||||
auto* storage =
|
||||
DOMWindowStorage::From(*window).sessionStorage(exception_state);
|
||||
|
||||
if (!ShouldUseEphemeralStorage(
|
||||
if (!GetEphemeralStorageOrigin(
|
||||
window, WebContentSettingsClient::StorageType::kSessionStorage))
|
||||
return storage;
|
||||
|
||||
@@ -186,13 +166,13 @@ StorageArea* BraveDOMWindowStorage::ephemeralSessionStorage() {
|
||||
|
||||
LocalDOMWindow* window = GetSupplementable();
|
||||
Page* page = window->GetFrame()->GetDocument()->GetPage();
|
||||
EphemeralStorageNamespaces* namespaces =
|
||||
EphemeralStorageNamespaces::From(page, window);
|
||||
if (!namespaces)
|
||||
EphemeralSessionStorageNamespace* ephemeral_namespace =
|
||||
EphemeralSessionStorageNamespace::From(page, window);
|
||||
if (!ephemeral_namespace)
|
||||
return nullptr;
|
||||
|
||||
auto storage_area =
|
||||
namespaces->session_storage()->GetCachedArea(window->GetSecurityOrigin());
|
||||
auto storage_area = ephemeral_namespace->session_storage()->GetCachedArea(
|
||||
window->GetSecurityOrigin());
|
||||
|
||||
ephemeral_session_storage_ =
|
||||
StorageArea::Create(window, std::move(storage_area),
|
||||
@@ -205,38 +185,26 @@ StorageArea* BraveDOMWindowStorage::localStorage(
|
||||
LocalDOMWindow* window = GetSupplementable();
|
||||
auto* storage = DOMWindowStorage::From(*window).localStorage(exception_state);
|
||||
|
||||
if (!ShouldUseEphemeralStorage(
|
||||
window, WebContentSettingsClient::StorageType::kLocalStorage))
|
||||
const SecurityOrigin* ephemeral_storage_origin = GetEphemeralStorageOrigin(
|
||||
window, WebContentSettingsClient::StorageType::kLocalStorage);
|
||||
if (!ephemeral_storage_origin)
|
||||
return storage;
|
||||
|
||||
return ephemeralLocalStorage();
|
||||
return ephemeralLocalStorage(ephemeral_storage_origin);
|
||||
}
|
||||
|
||||
StorageArea* BraveDOMWindowStorage::ephemeralLocalStorage() {
|
||||
StorageArea* BraveDOMWindowStorage::ephemeralLocalStorage(
|
||||
const SecurityOrigin* ephemeral_storage_origin) {
|
||||
DCHECK(ephemeral_storage_origin);
|
||||
if (ephemeral_local_storage_)
|
||||
return ephemeral_local_storage_;
|
||||
|
||||
LocalDOMWindow* window = GetSupplementable();
|
||||
Page* page = window->GetFrame()->GetDocument()->GetPage();
|
||||
EphemeralStorageNamespaces* namespaces =
|
||||
EphemeralStorageNamespaces::From(page, window);
|
||||
if (!namespaces)
|
||||
return nullptr;
|
||||
|
||||
auto* controller = StorageController::GetInstance();
|
||||
controller->ClearAreasIfNeeded();
|
||||
auto storage_area = base::MakeRefCounted<CachedStorageArea>(
|
||||
CachedStorageArea::AreaType::kSessionStorage, window->GetSecurityOrigin(),
|
||||
controller->TaskRunner(), namespaces->local_storage(),
|
||||
/*is_session_storage_for_prerendering=*/false);
|
||||
|
||||
// Ephemeral localStorage never persists stored data, which is also how
|
||||
// sessionStorage works. Due to this, when opening up a new ephemeral
|
||||
// localStorage area, we use the sessionStorage infrastructure.
|
||||
ephemeral_local_storage_ =
|
||||
StorageArea::Create(window, std::move(storage_area),
|
||||
StorageArea::StorageType::kSessionStorage);
|
||||
auto storage_area = StorageController::GetInstance()->GetLocalStorageArea(
|
||||
ephemeral_storage_origin);
|
||||
|
||||
ephemeral_local_storage_ = StorageArea::Create(
|
||||
window, std::move(storage_area), StorageArea::StorageType::kLocalStorage);
|
||||
return ephemeral_local_storage_;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,46 +133,53 @@ void BraveContentSettingsAgentImpl::DidNotAllowScript() {
|
||||
ContentSettingsAgentImpl::DidNotAllowScript();
|
||||
}
|
||||
|
||||
bool BraveContentSettingsAgentImpl::UseEphemeralStorageSync(
|
||||
blink::WebSecurityOrigin
|
||||
BraveContentSettingsAgentImpl::GetEphemeralStorageOriginSync(
|
||||
StorageType storage_type) {
|
||||
if (!base::FeatureList::IsEnabled(net::features::kBraveEphemeralStorage))
|
||||
return false;
|
||||
return blink::WebSecurityOrigin();
|
||||
|
||||
if (storage_type != StorageType::kLocalStorage &&
|
||||
storage_type != StorageType::kSessionStorage)
|
||||
return false;
|
||||
return blink::WebSecurityOrigin();
|
||||
|
||||
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
|
||||
|
||||
if (!frame || IsFrameWithOpaqueOrigin(frame))
|
||||
return false;
|
||||
return blink::WebSecurityOrigin();
|
||||
|
||||
auto frame_origin = url::Origin(frame->GetSecurityOrigin());
|
||||
StoragePermissionsKey key(frame_origin, storage_type);
|
||||
const auto permissions = cached_storage_permissions_.find(key);
|
||||
if (permissions != cached_storage_permissions_.end())
|
||||
return permissions->second;
|
||||
const auto ephemeral_storage_origin_it =
|
||||
cached_ephemeral_storage_origins_.find(key);
|
||||
if (ephemeral_storage_origin_it != cached_ephemeral_storage_origins_.end())
|
||||
return ephemeral_storage_origin_it->second;
|
||||
|
||||
auto top_origin = url::Origin(frame->Top()->GetSecurityOrigin());
|
||||
if (net::registry_controlled_domains::SameDomainOrHost(
|
||||
top_origin, frame_origin,
|
||||
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES))
|
||||
return false;
|
||||
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
|
||||
return blink::WebSecurityOrigin();
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
absl::optional<url::Origin> optional_ephemeral_storage_origin;
|
||||
GetContentSettingsManager().AllowEphemeralStorageAccess(
|
||||
routing_id(), ConvertToMojoStorageType(storage_type), frame_origin,
|
||||
frame->GetDocument().SiteForCookies().RepresentativeUrl(), top_origin,
|
||||
&result);
|
||||
cached_storage_permissions_[key] = result;
|
||||
return result;
|
||||
&optional_ephemeral_storage_origin);
|
||||
blink::WebSecurityOrigin ephemeral_storage_origin(
|
||||
optional_ephemeral_storage_origin
|
||||
? blink::WebSecurityOrigin(*optional_ephemeral_storage_origin)
|
||||
: blink::WebSecurityOrigin());
|
||||
cached_ephemeral_storage_origins_[key] = ephemeral_storage_origin;
|
||||
return ephemeral_storage_origin;
|
||||
}
|
||||
|
||||
bool BraveContentSettingsAgentImpl::AllowStorageAccessSync(
|
||||
StorageType storage_type) {
|
||||
bool result = ContentSettingsAgentImpl::AllowStorageAccessSync(storage_type);
|
||||
|
||||
if (result || UseEphemeralStorageSync(storage_type))
|
||||
if (result || !GetEphemeralStorageOriginSync(storage_type).IsNull())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
||||
@@ -46,7 +46,8 @@ class BraveContentSettingsAgentImpl
|
||||
const blink::WebURL& script_url) override;
|
||||
void DidNotAllowScript() override;
|
||||
|
||||
bool UseEphemeralStorageSync(StorageType storage_type) override;
|
||||
blink::WebSecurityOrigin GetEphemeralStorageOriginSync(
|
||||
StorageType storage_type) override;
|
||||
bool AllowStorageAccessSync(StorageType storage_type) override;
|
||||
|
||||
void BraveSpecificDidBlockJavaScript(const std::u16string& details);
|
||||
@@ -96,7 +97,8 @@ class BraveContentSettingsAgentImpl
|
||||
base::flat_set<std::string> preloaded_temporarily_allowed_scripts_;
|
||||
|
||||
using StoragePermissionsKey = std::pair<url::Origin, StorageType>;
|
||||
base::flat_map<StoragePermissionsKey, bool> cached_storage_permissions_;
|
||||
base::flat_map<StoragePermissionsKey, blink::WebSecurityOrigin>
|
||||
cached_ephemeral_storage_origins_;
|
||||
|
||||
mojo::AssociatedRemote<brave_shields::mojom::BraveShieldsHost>
|
||||
brave_shields_remote_;
|
||||
|
||||
Reference in New Issue
Block a user