[Shred] Implement back-end for manual site data shredding (#32197)
Implemented an ability to enforce shred by user request for desktop and android, it means site data cleaning and and related tabs closing. Resolves: https://github.com/brave/brave-browser/issues/50670 --------- Signed-off-by: Vadym Struts <vstruts@brave.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
include_rules = [
|
||||
"+brave/components/brave_shields/core/browser",
|
||||
"+brave/components/ephemeral_storage",
|
||||
"+brave/components/brave_shields/content/test",
|
||||
"+services/network/host_resolver.h",
|
||||
]
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "base/types/cxx23_to_underlying.h"
|
||||
#include "brave/browser/brave_shields/brave_shields_settings_service_factory.h"
|
||||
#include "brave/browser/brave_shields/brave_shields_web_contents_observer.h"
|
||||
#include "brave/browser/ephemeral_storage/ephemeral_storage_service_factory.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_locale_utils.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_settings_service.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_utils.h"
|
||||
@@ -65,8 +66,9 @@ BraveShieldsTabHelper::BraveShieldsTabHelper(content::WebContents* web_contents)
|
||||
web_contents->GetBrowserContext()))),
|
||||
brave_shields_settings_(
|
||||
CHECK_DEREF(BraveShieldsSettingsServiceFactory::GetForProfile(
|
||||
Profile::FromBrowserContext(
|
||||
web_contents->GetBrowserContext())))) {
|
||||
Profile::FromBrowserContext(web_contents->GetBrowserContext())))),
|
||||
ephemeral_storage_service_(EphemeralStorageServiceFactory::GetForContext(
|
||||
web_contents->GetBrowserContext())) {
|
||||
favicon::ContentFaviconDriver::FromWebContents(web_contents)
|
||||
->AddObserver(this);
|
||||
observation_.Observe(&*host_content_settings_map_);
|
||||
@@ -476,6 +478,20 @@ void BraveShieldsTabHelper::BlockAllowedScripts(
|
||||
ReloadWebContents();
|
||||
}
|
||||
|
||||
void BraveShieldsTabHelper::EnforceSiteDataCleanup() {
|
||||
auto* site_instance = web_contents()->GetSiteInstance();
|
||||
CHECK(site_instance);
|
||||
|
||||
if (!ephemeral_storage_service_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Start manual cleanup.
|
||||
ephemeral_storage_service_->CleanupTLDFirstPartyStorage(
|
||||
web_contents()->GetLastCommittedURL(),
|
||||
site_instance->GetStoragePartitionConfig(), true);
|
||||
}
|
||||
|
||||
void BraveShieldsTabHelper::AllowScriptsOnce(
|
||||
const std::vector<std::string>& origins) {
|
||||
BraveShieldsWebContentsObserver* observer =
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "base/scoped_observation.h"
|
||||
#include "brave/components/brave_shields/core/common/brave_shields_panel.mojom.h"
|
||||
#include "brave/components/brave_shields/core/common/shields_settings.mojom.h"
|
||||
#include "brave/components/ephemeral_storage/ephemeral_storage_service.h"
|
||||
#include "components/content_settings/core/browser/content_settings_observer.h"
|
||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||
#include "components/favicon/core/favicon_driver_observer.h"
|
||||
@@ -86,6 +87,7 @@ class BraveShieldsTabHelper
|
||||
void SetHttpsUpgradeMode(mojom::HttpsUpgradeMode mode);
|
||||
void SetIsNoScriptEnabled(bool is_enabled);
|
||||
void SetForgetFirstPartyStorageEnabled(bool is_enabled);
|
||||
void EnforceSiteDataCleanup();
|
||||
void AllowScriptsOnce(const std::vector<std::string>& origins);
|
||||
void BlockAllowedScripts(const std::vector<std::string>& origins);
|
||||
void SetWebcompatEnabled(ContentSettingsType webcompat_settings_type,
|
||||
@@ -146,6 +148,8 @@ class BraveShieldsTabHelper
|
||||
const raw_ref<BraveShieldsSettingsService> brave_shields_settings_;
|
||||
|
||||
PrefChangeRegistrar local_state_change_registrar_;
|
||||
const raw_ptr<ephemeral_storage::EphemeralStorageService>
|
||||
ephemeral_storage_service_;
|
||||
|
||||
WEB_CONTENTS_USER_DATA_KEY_DECL();
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ brave_browser_brave_shields_deps = [
|
||||
"//brave/components/brave_shields/core/browser",
|
||||
"//brave/components/brave_shields/core/common",
|
||||
"//brave/components/constants",
|
||||
"//brave/components/ephemeral_storage",
|
||||
"//chrome/browser/profiles:profile",
|
||||
"//chrome/common",
|
||||
"//components/content_settings/core/browser",
|
||||
@@ -49,4 +50,6 @@ if (is_android) {
|
||||
"//brave/browser/android:android_browser_process",
|
||||
"//brave/build/android:jni_headers",
|
||||
]
|
||||
} else {
|
||||
brave_browser_brave_shields_deps += [ "//brave/browser/ui/tabs:tab_strip" ]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
include_rules = [
|
||||
"+brave/components/ephemeral_storage",
|
||||
"+brave/components/brave_shields/content/test",
|
||||
"+brave/build/android/jni_headers/TabUtils_jni.h",
|
||||
"!brave/components/brave_component_updater/browser/local_data_files_service.h",
|
||||
"!brave/components/brave_component_updater/browser/local_data_files_observer.h",
|
||||
]
|
||||
|
||||
@@ -5,40 +5,97 @@
|
||||
|
||||
#include "brave/browser/ephemeral_storage/brave_ephemeral_storage_service_delegate.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "brave/browser/brave_shields/brave_shields_settings_service_factory.h"
|
||||
#include "brave/browser/ephemeral_storage/ephemeral_storage_tab_helper.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_settings_service.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_utils.h"
|
||||
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/browser/ui/browser_finder.h"
|
||||
#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
|
||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||
#include "components/tabs/public/tab_interface.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/browsing_data_filter_builder.h"
|
||||
#include "content/public/browser/browsing_data_remover.h"
|
||||
#include "content/public/browser/dom_storage_context.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "net/base/features.h"
|
||||
#include "net/base/schemeful_site.h"
|
||||
#include "net/base/url_util.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
#include "brave/browser/ui/brave_browser.h"
|
||||
#include "chrome/browser/ui/browser.h"
|
||||
#include "chrome/browser/ui/browser_list.h"
|
||||
#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
||||
#else
|
||||
#include "chrome/browser/android/tab_android.h"
|
||||
#include "chrome/browser/ui/android/tab_model/tab_model.h"
|
||||
#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
|
||||
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
bool PrepareTabForFirstPartyStorageCleanup(tabs::TabHandle tab_handle,
|
||||
const std::string& etldplusone) {
|
||||
if (tab_handle == tabs::TabHandle::Null()) {
|
||||
return false;
|
||||
}
|
||||
auto* tab = tab_handle.Get();
|
||||
if (!tab) {
|
||||
return false;
|
||||
}
|
||||
|
||||
content::WebContents* contents = tab->GetContents();
|
||||
if (!contents) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto tab_tld =
|
||||
net::URLToEphemeralStorageDomain(contents->GetLastCommittedURL());
|
||||
if (tab_tld.empty() || tab_tld != etldplusone) {
|
||||
return false;
|
||||
}
|
||||
if (auto* ephemeral_storage_tab_helper =
|
||||
ephemeral_storage::EphemeralStorageTabHelper::FromWebContents(
|
||||
contents)) {
|
||||
ephemeral_storage_tab_helper->EnforceFirstPartyStorageCleanup();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace ephemeral_storage {
|
||||
|
||||
BraveEphemeralStorageServiceDelegate::BraveEphemeralStorageServiceDelegate(
|
||||
content::BrowserContext* context,
|
||||
HostContentSettingsMap* host_content_settings_map,
|
||||
scoped_refptr<content_settings::CookieSettings> cookie_settings)
|
||||
scoped_refptr<content_settings::CookieSettings> cookie_settings,
|
||||
brave_shields::BraveShieldsSettingsService* shields_settings_service)
|
||||
: context_(context),
|
||||
host_content_settings_map_(host_content_settings_map),
|
||||
cookie_settings_(std::move(cookie_settings)) {
|
||||
cookie_settings_(std::move(cookie_settings)),
|
||||
shields_settings_service_(shields_settings_service) {
|
||||
DCHECK(context_);
|
||||
DCHECK(host_content_settings_map_);
|
||||
DCHECK(cookie_settings_);
|
||||
CHECK(shields_settings_service_);
|
||||
}
|
||||
|
||||
BraveEphemeralStorageServiceDelegate::~BraveEphemeralStorageServiceDelegate() {
|
||||
@@ -145,4 +202,70 @@ void BraveEphemeralStorageServiceDelegate::OnBrowserAdded(Browser* browser) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void BraveEphemeralStorageServiceDelegate::
|
||||
PrepareTabsForFirstPartyStorageCleanup(
|
||||
const std::string& ephemeral_domain) {
|
||||
auto* profile = Profile::FromBrowserContext(context_);
|
||||
CHECK(profile);
|
||||
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
for (auto* browser : GetAllBrowserWindowInterfaces()) {
|
||||
if (profile != browser->GetProfile()) {
|
||||
continue;
|
||||
}
|
||||
auto* tab_strip = browser->GetTabStripModel();
|
||||
if (!tab_strip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
base::flat_set<tabs::TabHandle> tab_handlers;
|
||||
for (auto* tab : *tab_strip) {
|
||||
if (!tab || !PrepareTabForFirstPartyStorageCleanup(tab->GetHandle(),
|
||||
ephemeral_domain)) {
|
||||
continue;
|
||||
}
|
||||
tab_handlers.emplace(tab->GetHandle());
|
||||
}
|
||||
static_cast<BraveBrowser*>(browser)->SetTabsToIgnoreBeforeUnloadHandlers(
|
||||
tab_handlers);
|
||||
|
||||
for (auto& tab_handle : tab_handlers) {
|
||||
if (tab_handle == tabs::TabHandle::Null() || !tab_handle.Get()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// initiate the closing of the tab
|
||||
tab_handle.Get()->Close();
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (TabModel* model : TabModelList::models()) {
|
||||
const size_t tab_count = model->GetTabCount();
|
||||
std::vector<tabs::TabHandle> tabs_to_close;
|
||||
for (size_t index = 0; index < tab_count; index++) {
|
||||
auto* tab = model->GetTabAt(index);
|
||||
// Do not process tabs from other profiles.
|
||||
if (!tab || profile != tab->profile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PrepareTabForFirstPartyStorageCleanup(tab->GetHandle(),
|
||||
ephemeral_domain)) {
|
||||
continue;
|
||||
}
|
||||
tabs_to_close.emplace_back(tab->GetHandle());
|
||||
}
|
||||
for (auto& tab_handle : tabs_to_close) {
|
||||
tab_handle.Get()->Close();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool BraveEphemeralStorageServiceDelegate::
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf(const GURL& url) const {
|
||||
return shields_settings_service_->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
url);
|
||||
}
|
||||
|
||||
} // namespace ephemeral_storage
|
||||
|
||||
@@ -6,10 +6,14 @@
|
||||
#ifndef BRAVE_BROWSER_EPHEMERAL_STORAGE_BRAVE_EPHEMERAL_STORAGE_SERVICE_DELEGATE_H_
|
||||
#define BRAVE_BROWSER_EPHEMERAL_STORAGE_BRAVE_EPHEMERAL_STORAGE_SERVICE_DELEGATE_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_settings_service.h"
|
||||
#include "brave/components/ephemeral_storage/ephemeral_storage_service_delegate.h"
|
||||
#include "components/content_settings/core/browser/cookie_settings.h"
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
#include "chrome/browser/ui/browser_list_observer.h"
|
||||
@@ -32,7 +36,8 @@ class BraveEphemeralStorageServiceDelegate :
|
||||
BraveEphemeralStorageServiceDelegate(
|
||||
content::BrowserContext* context,
|
||||
HostContentSettingsMap* host_content_settings_map,
|
||||
scoped_refptr<content_settings::CookieSettings> cookie_settings);
|
||||
scoped_refptr<content_settings::CookieSettings> cookie_settings,
|
||||
brave_shields::BraveShieldsSettingsService* shields_settings_service);
|
||||
~BraveEphemeralStorageServiceDelegate() override;
|
||||
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
@@ -44,6 +49,10 @@ class BraveEphemeralStorageServiceDelegate :
|
||||
void CleanupTLDEphemeralArea(const TLDEphemeralAreaKey& key) override;
|
||||
void CleanupFirstPartyStorageArea(const TLDEphemeralAreaKey& key) override;
|
||||
void RegisterFirstWindowOpenedCallback(base::OnceClosure callback) override;
|
||||
void PrepareTabsForFirstPartyStorageCleanup(
|
||||
const std::string& ephemeral_domain) override;
|
||||
bool IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
const GURL& url) const override;
|
||||
|
||||
private:
|
||||
raw_ptr<content::BrowserContext> context_ = nullptr;
|
||||
@@ -52,6 +61,8 @@ class BraveEphemeralStorageServiceDelegate :
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
base::OnceClosure first_window_opened_callback_;
|
||||
#endif // !BUILDFLAG(IS_ANDROID)
|
||||
raw_ptr<brave_shields::BraveShieldsSettingsService>
|
||||
shields_settings_service_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ephemeral_storage
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "brave/browser/ephemeral_storage/ephemeral_storage_tab_helper.h"
|
||||
#include "brave/components/brave_shields/core/browser/brave_shields_utils.h"
|
||||
#include "brave/components/brave_shields/core/common/brave_shield_constants.h"
|
||||
#include "brave/components/brave_shields/core/common/features.h"
|
||||
#include "brave/components/constants/brave_paths.h"
|
||||
#include "brave/components/ephemeral_storage/ephemeral_storage_service.h"
|
||||
#include "chrome/browser/content_settings/cookie_settings_factory.h"
|
||||
@@ -81,8 +82,9 @@ std::unique_ptr<HttpResponse> HandleFileRequestWithCustomHeaders(
|
||||
std::unique_ptr<HttpResponse> http_response;
|
||||
for (const auto& server_root : server_roots) {
|
||||
http_response = net::test_server::HandleFileRequest(server_root, request);
|
||||
if (http_response)
|
||||
if (http_response) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (http_response) {
|
||||
GURL request_url = request.GetURL();
|
||||
@@ -170,8 +172,9 @@ bool HttpRequestMonitor::HasHttpRequestWithCookie(
|
||||
const std::string& cookie_value) const {
|
||||
base::AutoLock lock(lock_);
|
||||
for (const auto& http_request : http_requests_) {
|
||||
if (GetHttpRequestURL(http_request) != url)
|
||||
if (GetHttpRequestURL(http_request) != url) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& header : http_request.headers) {
|
||||
if (header.first == net::HttpRequestHeaders::kCookie &&
|
||||
header.second == cookie_value) {
|
||||
@@ -345,15 +348,7 @@ content::EvalJsResult EphemeralStorageBrowserTest::GetCookiesInFrame(
|
||||
return content::EvalJs(host, "document.cookie");
|
||||
}
|
||||
|
||||
size_t EphemeralStorageBrowserTest::WaitForCleanupAfterKeepAlive(
|
||||
Profile* profile) {
|
||||
if (!profile) {
|
||||
profile = browser()->profile();
|
||||
}
|
||||
const size_t fired_cnt = EphemeralStorageServiceFactory::GetInstance()
|
||||
->GetForContext(profile)
|
||||
->FireCleanupTimersForTesting();
|
||||
|
||||
void WaitForCleanup(Profile* profile) {
|
||||
// NetworkService closes existing connections when a data removal action
|
||||
// linked to these connections is performed. This leads to rare page open
|
||||
// failures when the timing is "just right". Do a no-op removal here to make
|
||||
@@ -365,7 +360,17 @@ size_t EphemeralStorageBrowserTest::WaitForCleanupAfterKeepAlive(
|
||||
&data_remover_observer);
|
||||
data_remover_observer.Wait();
|
||||
remover->RemoveObserver(&data_remover_observer);
|
||||
}
|
||||
|
||||
size_t EphemeralStorageBrowserTest::WaitForCleanupAfterKeepAlive(
|
||||
Profile* profile) {
|
||||
if (!profile) {
|
||||
profile = browser()->profile();
|
||||
}
|
||||
const size_t fired_cnt = EphemeralStorageServiceFactory::GetInstance()
|
||||
->GetForContext(profile)
|
||||
->FireCleanupTimersForTesting();
|
||||
WaitForCleanup(profile);
|
||||
return fired_cnt;
|
||||
}
|
||||
|
||||
@@ -1435,3 +1440,228 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
,
|
||||
EphemeralStorageWithDisableThirdPartyStoragePartitioningBrowserTest,
|
||||
testing::Bool());
|
||||
|
||||
class FirstPartyStorageCleanupSiteDataBrowserTest
|
||||
: public EphemeralStorageBrowserTest {
|
||||
public:
|
||||
FirstPartyStorageCleanupSiteDataBrowserTest() {
|
||||
scoped_feature_list_.InitAndEnableFeature(
|
||||
brave_shields::features::kBraveShredFeature);
|
||||
}
|
||||
|
||||
private:
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(FirstPartyStorageCleanupSiteDataBrowserTest,
|
||||
StorageIsCleanedTabsIsClosed) {
|
||||
// Open two tabs with different sites.
|
||||
WebContents* site_a_tab = LoadURLInNewTab(a_site_ephemeral_storage_url_);
|
||||
EXPECT_TRUE(LoadURLInNewTab(a_site_ephemeral_storage_url_));
|
||||
WebContents* site_b_tab = LoadURLInNewTab(b_site_ephemeral_storage_url_);
|
||||
EXPECT_EQ(browser()->tab_strip_model()->count(), 4);
|
||||
EXPECT_TRUE(site_a_tab);
|
||||
EXPECT_TRUE(site_b_tab);
|
||||
|
||||
// Set first and third party storage values in both tabs.
|
||||
SetValuesInFrames(site_a_tab, "a.com", "from=a.com");
|
||||
ValuesFromFrames site_a_tab_values = GetValuesFromFrames(site_a_tab);
|
||||
EXPECT_EQ("a.com", site_a_tab_values.main_frame.local_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab_values.iframe_1.local_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab_values.iframe_2.local_storage);
|
||||
SetValuesInFrames(site_b_tab, "b.com", "from=b.com");
|
||||
ValuesFromFrames site_b_tab_values = GetValuesFromFrames(site_b_tab);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.main_frame.local_storage);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.iframe_1.local_storage);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.iframe_2.local_storage);
|
||||
|
||||
// Shred site data for site a.com
|
||||
auto* profile = browser()->profile();
|
||||
auto storage_partition_config =
|
||||
site_a_tab->GetSiteInstance()->GetStoragePartitionConfig();
|
||||
EphemeralStorageServiceFactory::GetInstance()
|
||||
->GetForContext(profile)
|
||||
->CleanupTLDFirstPartyStorage(site_a_tab->GetLastCommittedURL(),
|
||||
storage_partition_config, true);
|
||||
|
||||
// Wait for the cleanup to finish.
|
||||
WaitForCleanupAfterKeepAlive(profile);
|
||||
|
||||
// Check if the tab related to site_a_tab has been closed
|
||||
int site_a_tab_index =
|
||||
browser()->tab_strip_model()->GetIndexOfWebContents(site_a_tab);
|
||||
EXPECT_EQ(TabStripModel::kNoTab, site_a_tab_index);
|
||||
|
||||
// Open site A in new tab again and make sure that the storage is empty.
|
||||
site_a_tab = LoadURLInNewTab(a_site_ephemeral_storage_url_);
|
||||
auto site_a_tab_values_cleaned = GetValuesFromFrames(site_a_tab);
|
||||
EXPECT_EQ(base::Value(), site_a_tab_values_cleaned.main_frame.local_storage);
|
||||
EXPECT_EQ(base::Value(), site_a_tab_values_cleaned.iframe_1.local_storage);
|
||||
EXPECT_EQ(base::Value(), site_a_tab_values_cleaned.iframe_2.local_storage);
|
||||
|
||||
// Make sure that site B's first and third party storage data exists.
|
||||
site_b_tab_values = GetValuesFromFrames(site_b_tab);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.main_frame.local_storage);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.iframe_1.local_storage);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.iframe_2.local_storage);
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(FirstPartyStorageCleanupSiteDataBrowserTest,
|
||||
StorageIsCleanedTabsIsClosedForSameDomain) {
|
||||
const auto a_site_ephemeral_storage_url =
|
||||
https_server_.GetURL("a.com", "/ephemeral_storage.html");
|
||||
const auto a_a_site_ephemeral_storage_url =
|
||||
https_server_.GetURL("a.a.com", "/ephemeral_storage.html");
|
||||
const auto b_a_site_ephemeral_storage_url =
|
||||
https_server_.GetURL("b.a.com", "/ephemeral_storage.html");
|
||||
|
||||
// Open tabs with different sites - a.com, a.a.com, b.a.com, and b.com
|
||||
WebContents* site_a_tab = LoadURLInNewTab(a_site_ephemeral_storage_url);
|
||||
WebContents* site_a_a_tab = LoadURLInNewTab(a_a_site_ephemeral_storage_url);
|
||||
WebContents* site_b_a_tab = LoadURLInNewTab(b_a_site_ephemeral_storage_url);
|
||||
WebContents* site_b_tab = LoadURLInNewTab(b_site_ephemeral_storage_url_);
|
||||
|
||||
EXPECT_EQ(browser()->tab_strip_model()->count(), 5);
|
||||
EXPECT_TRUE(site_a_tab);
|
||||
EXPECT_TRUE(site_a_a_tab);
|
||||
EXPECT_TRUE(site_b_a_tab);
|
||||
EXPECT_TRUE(site_b_tab);
|
||||
|
||||
// Set storage values in main frames only (to avoid iframe complexity)
|
||||
// We're primarily testing tab closure behavior, not iframe partitioning
|
||||
RenderFrameHost* site_a_main = site_a_tab->GetPrimaryMainFrame();
|
||||
RenderFrameHost* site_a_a_main = site_a_a_tab->GetPrimaryMainFrame();
|
||||
RenderFrameHost* site_b_a_main = site_b_a_tab->GetPrimaryMainFrame();
|
||||
RenderFrameHost* site_b_main = site_b_tab->GetPrimaryMainFrame();
|
||||
|
||||
SetValuesInFrame(site_a_main, "a.com", "from=a.com");
|
||||
SetValuesInFrame(site_a_a_main, "a.a.com", "from=a.a.com");
|
||||
SetValuesInFrame(site_b_a_main, "b.a.com", "from=b.a.com");
|
||||
SetValuesInFrame(site_b_main, "b.com", "from=b.com");
|
||||
|
||||
// Verify that storage values are set correctly before shredding
|
||||
ValuesFromFrame site_a_tab_values = GetValuesFromFrame(site_a_main);
|
||||
ValuesFromFrame site_a_a_tab_values = GetValuesFromFrame(site_a_a_main);
|
||||
ValuesFromFrame site_b_a_tab_values = GetValuesFromFrame(site_b_a_main);
|
||||
ValuesFromFrame site_b_tab_values = GetValuesFromFrame(site_b_main);
|
||||
|
||||
EXPECT_EQ("a.com", site_a_tab_values.local_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab_values.session_storage);
|
||||
EXPECT_EQ("from=a.com", site_a_tab_values.cookies);
|
||||
|
||||
EXPECT_EQ("a.a.com", site_a_a_tab_values.local_storage);
|
||||
EXPECT_EQ("a.a.com", site_a_a_tab_values.session_storage);
|
||||
EXPECT_EQ("from=a.a.com", site_a_a_tab_values.cookies);
|
||||
|
||||
EXPECT_EQ("b.a.com", site_b_a_tab_values.local_storage);
|
||||
EXPECT_EQ("b.a.com", site_b_a_tab_values.session_storage);
|
||||
EXPECT_EQ("from=b.a.com", site_b_a_tab_values.cookies);
|
||||
|
||||
EXPECT_EQ("b.com", site_b_tab_values.local_storage);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.session_storage);
|
||||
EXPECT_EQ("from=b.com", site_b_tab_values.cookies);
|
||||
|
||||
// Shred site data for a.com - this should close tabs for a.com, a.a.com, and
|
||||
// b.a.com
|
||||
auto* profile = browser()->profile();
|
||||
auto storage_partition_config =
|
||||
site_a_tab->GetSiteInstance()->GetStoragePartitionConfig();
|
||||
EphemeralStorageServiceFactory::GetInstance()
|
||||
->GetForContext(profile)
|
||||
->CleanupTLDFirstPartyStorage(site_a_tab->GetLastCommittedURL(),
|
||||
storage_partition_config, true);
|
||||
|
||||
// Wait for the cleanup to finish.
|
||||
WaitForCleanupAfterKeepAlive(profile);
|
||||
|
||||
// Check that tabs for a.com, a.a.com, and b.a.com have been closed
|
||||
EXPECT_EQ(TabStripModel::kNoTab,
|
||||
browser()->tab_strip_model()->GetIndexOfWebContents(site_a_tab));
|
||||
EXPECT_EQ(TabStripModel::kNoTab,
|
||||
browser()->tab_strip_model()->GetIndexOfWebContents(site_a_a_tab));
|
||||
EXPECT_EQ(TabStripModel::kNoTab,
|
||||
browser()->tab_strip_model()->GetIndexOfWebContents(site_b_a_tab));
|
||||
|
||||
// Make sure that b.com remains open
|
||||
EXPECT_NE(TabStripModel::kNoTab,
|
||||
browser()->tab_strip_model()->GetIndexOfWebContents(site_b_tab));
|
||||
|
||||
// Verify that b.com tab still has its data intact
|
||||
site_b_tab_values = GetValuesFromFrame(site_b_main);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.local_storage);
|
||||
EXPECT_EQ("b.com", site_b_tab_values.session_storage);
|
||||
EXPECT_EQ("from=b.com", site_b_tab_values.cookies);
|
||||
|
||||
// Open new tabs for the shredded domains and verify their storage is empty
|
||||
WebContents* new_site_a_tab = LoadURLInNewTab(a_site_ephemeral_storage_url);
|
||||
WebContents* new_site_a_a_tab =
|
||||
LoadURLInNewTab(a_a_site_ephemeral_storage_url);
|
||||
WebContents* new_site_b_a_tab =
|
||||
LoadURLInNewTab(b_a_site_ephemeral_storage_url);
|
||||
|
||||
// All shredded domains should have empty storage
|
||||
ExpectValuesFromFrameAreEmpty(
|
||||
FROM_HERE, GetValuesFromFrame(new_site_a_tab->GetPrimaryMainFrame()));
|
||||
ExpectValuesFromFrameAreEmpty(
|
||||
FROM_HERE, GetValuesFromFrame(new_site_a_a_tab->GetPrimaryMainFrame()));
|
||||
ExpectValuesFromFrameAreEmpty(
|
||||
FROM_HERE, GetValuesFromFrame(new_site_b_a_tab->GetPrimaryMainFrame()));
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(FirstPartyStorageCleanupSiteDataBrowserTest,
|
||||
DoNotCleanupStorageIfShieldsDisabledOnAnySubdomain) {
|
||||
const auto a_site_ephemeral_storage_url =
|
||||
https_server_.GetURL("a.com", "/ephemeral_storage.html");
|
||||
const auto a_a_site_ephemeral_storage_url =
|
||||
https_server_.GetURL("a.a.com", "/ephemeral_storage.html");
|
||||
|
||||
brave_shields::SetBraveShieldsEnabled(content_settings(), false,
|
||||
a_a_site_ephemeral_storage_url);
|
||||
|
||||
// Open tabs with different sites - a.com, a.a.com, b.a.com, and b.com
|
||||
WebContents* site_a_tab = LoadURLInNewTab(a_site_ephemeral_storage_url);
|
||||
WebContents* site_a_a_tab = LoadURLInNewTab(a_a_site_ephemeral_storage_url);
|
||||
|
||||
EXPECT_EQ(browser()->tab_strip_model()->count(), 3);
|
||||
EXPECT_TRUE(site_a_tab);
|
||||
EXPECT_TRUE(site_a_a_tab);
|
||||
|
||||
// Set storage values in main frames only (to avoid iframe complexity)
|
||||
// We're primarily testing tab closure behavior, not iframe partitioning
|
||||
RenderFrameHost* site_a_main = site_a_tab->GetPrimaryMainFrame();
|
||||
RenderFrameHost* site_a_a_main = site_a_a_tab->GetPrimaryMainFrame();
|
||||
|
||||
SetValuesInFrame(site_a_main, "a.com", "from=a.com");
|
||||
SetValuesInFrame(site_a_a_main, "a.a.com", "from=a.a.com");
|
||||
|
||||
// Verify that storage values are set correctly before shredding
|
||||
ValuesFromFrame site_a_tab_values = GetValuesFromFrame(site_a_main);
|
||||
ValuesFromFrame site_a_a_tab_values = GetValuesFromFrame(site_a_a_main);
|
||||
|
||||
EXPECT_EQ("a.com", site_a_tab_values.local_storage);
|
||||
EXPECT_EQ("a.com", site_a_tab_values.session_storage);
|
||||
EXPECT_EQ("from=a.com", site_a_tab_values.cookies);
|
||||
|
||||
EXPECT_EQ("a.a.com", site_a_a_tab_values.local_storage);
|
||||
EXPECT_EQ("a.a.com", site_a_a_tab_values.session_storage);
|
||||
EXPECT_EQ("from=a.a.com", site_a_a_tab_values.cookies);
|
||||
|
||||
// Try to Shred site data for a.com - this should not be executed as shields
|
||||
// are disabled on a.a.com
|
||||
auto* profile = browser()->profile();
|
||||
auto storage_partition_config =
|
||||
site_a_tab->GetSiteInstance()->GetStoragePartitionConfig();
|
||||
EphemeralStorageServiceFactory::GetInstance()
|
||||
->GetForContext(profile)
|
||||
->CleanupTLDFirstPartyStorage(site_a_tab->GetLastCommittedURL(),
|
||||
storage_partition_config, false);
|
||||
|
||||
// Wait for the cleanup to finish.
|
||||
WaitForCleanupAfterKeepAlive(profile);
|
||||
|
||||
// Check that tabs for a.com, a.a.com, and b.a.com have not been closed
|
||||
EXPECT_NE(TabStripModel::kNoTab,
|
||||
browser()->tab_strip_model()->GetIndexOfWebContents(site_a_tab));
|
||||
EXPECT_NE(TabStripModel::kNoTab,
|
||||
browser()->tab_strip_model()->GetIndexOfWebContents(site_a_a_tab));
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/feature_list.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "brave/browser/brave_shields/brave_shields_settings_service_factory.h"
|
||||
#include "brave/browser/ephemeral_storage/brave_ephemeral_storage_service_delegate.h"
|
||||
#include "brave/components/ephemeral_storage/ephemeral_storage_pref_names.h"
|
||||
#include "brave/components/ephemeral_storage/ephemeral_storage_service.h"
|
||||
@@ -40,6 +41,7 @@ EphemeralStorageServiceFactory::EphemeralStorageServiceFactory()
|
||||
BrowserContextDependencyManager::GetInstance()) {
|
||||
DependsOn(HostContentSettingsMapFactory::GetInstance());
|
||||
DependsOn(CookieSettingsFactory::GetInstance());
|
||||
DependsOn(BraveShieldsSettingsServiceFactory::GetInstance());
|
||||
}
|
||||
|
||||
EphemeralStorageServiceFactory::~EphemeralStorageServiceFactory() = default;
|
||||
@@ -72,7 +74,8 @@ EphemeralStorageServiceFactory::BuildServiceInstanceForBrowserContext(
|
||||
context, host_content_settings_map,
|
||||
std::make_unique<ephemeral_storage::BraveEphemeralStorageServiceDelegate>(
|
||||
context, host_content_settings_map,
|
||||
CookieSettingsFactory::GetForProfile(profile)));
|
||||
CookieSettingsFactory::GetForProfile(profile),
|
||||
BraveShieldsSettingsServiceFactory::GetForProfile(profile)));
|
||||
}
|
||||
|
||||
content::BrowserContext* EphemeralStorageServiceFactory::GetBrowserContextToUse(
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "brave/components/ephemeral_storage/ephemeral_storage_service.h"
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
@@ -52,6 +53,14 @@ class MockDelegate : public EphemeralStorageServiceDelegate {
|
||||
RegisterFirstWindowOpenedCallback,
|
||||
(base::OnceClosure callback),
|
||||
(override));
|
||||
MOCK_METHOD(bool,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf,
|
||||
(const GURL& url),
|
||||
(const override));
|
||||
MOCK_METHOD(void,
|
||||
PrepareTabsForFirstPartyStorageCleanup,
|
||||
(const std::string& ephemeral_domain),
|
||||
(override));
|
||||
|
||||
void ExpectRegisterFirstWindowOpenedCallback(base::OnceClosure callback,
|
||||
bool trigger_callback) {
|
||||
@@ -161,8 +170,8 @@ TEST_F(EphemeralStorageServiceTest, EphemeralCleanup) {
|
||||
{
|
||||
ScopedVerifyAndClearExpectations verify(mock_delegate_);
|
||||
ScopedVerifyAndClearExpectations verify_observer(&mock_observer_);
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
task_environment_.FastForwardBy(base::Seconds(10));
|
||||
}
|
||||
|
||||
@@ -174,8 +183,8 @@ TEST_F(EphemeralStorageServiceTest, EphemeralCleanup) {
|
||||
{
|
||||
ScopedVerifyAndClearExpectations verify(mock_delegate_);
|
||||
ScopedVerifyAndClearExpectations verify_observer(&mock_observer_);
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
task_environment_.FastForwardBy(base::Seconds(20));
|
||||
}
|
||||
|
||||
@@ -213,8 +222,8 @@ TEST_F(EphemeralStorageServiceTest,
|
||||
TLDEphemeralAreaKey key(ephemeral_domain, storage_partition_config);
|
||||
EXPECT_CALL(mock_observer_, OnCleanupTLDEphemeralArea(key));
|
||||
EXPECT_CALL(*mock_delegate_, CleanupTLDEphemeralArea(key));
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
task_environment_.FastForwardBy(base::Seconds(30));
|
||||
}
|
||||
|
||||
@@ -226,7 +235,7 @@ TEST_F(EphemeralStorageServiceTest,
|
||||
EXPECT_CALL(mock_observer_, OnCleanupTLDEphemeralArea(key));
|
||||
EXPECT_CALL(*mock_delegate_, CleanupTLDEphemeralArea(key));
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, second_storage_partition_config, false);
|
||||
ephemeral_domain, second_storage_partition_config, false, false);
|
||||
task_environment_.FastForwardBy(base::Seconds(30));
|
||||
}
|
||||
}
|
||||
@@ -258,8 +267,8 @@ TEST_F(EphemeralStorageServiceNoKeepAliveTest, ImmediateCleanup) {
|
||||
TLDEphemeralAreaKey key(ephemeral_domain, storage_partition_config);
|
||||
EXPECT_CALL(mock_observer_, OnCleanupTLDEphemeralArea(key));
|
||||
EXPECT_CALL(*mock_delegate_, CleanupTLDEphemeralArea(key));
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,9 +332,9 @@ TEST_F(EphemeralStorageServiceForgetFirstPartyTest, CleanupFirstPartyStorage) {
|
||||
.Times(test_case.shields_enabled);
|
||||
EXPECT_CALL(*mock_delegate_, CleanupFirstPartyStorageArea(key))
|
||||
.Times(test_case.should_cleanup);
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config,
|
||||
!test_case.shields_enabled);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config,
|
||||
!test_case.shields_enabled, false);
|
||||
EXPECT_EQ(profile_.GetPrefs()
|
||||
->GetList(kFirstPartyStorageOriginsToCleanup)
|
||||
.size(),
|
||||
@@ -360,8 +369,8 @@ TEST_F(EphemeralStorageServiceForgetFirstPartyTest, CleanupOnRestart) {
|
||||
{
|
||||
ScopedVerifyAndClearExpectations verify(mock_delegate_);
|
||||
ScopedVerifyAndClearExpectations verify_observer(&mock_observer_);
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
EXPECT_EQ(
|
||||
profile_.GetPrefs()->GetList(kFirstPartyStorageOriginsToCleanup).size(),
|
||||
1u);
|
||||
@@ -411,8 +420,8 @@ TEST_F(EphemeralStorageServiceForgetFirstPartyTest,
|
||||
profile_.GetPrefs()->GetList(kFirstPartyStorageOriginsToCleanup).size(),
|
||||
0u);
|
||||
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
EXPECT_EQ(
|
||||
profile_.GetPrefs()->GetList(kFirstPartyStorageOriginsToCleanup).size(),
|
||||
1u);
|
||||
@@ -463,10 +472,10 @@ TEST_F(EphemeralStorageServiceForgetFirstPartyTest,
|
||||
profile_.GetPrefs()->GetList(kFirstPartyStorageOriginsToCleanup).size(),
|
||||
0u);
|
||||
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, second_storage_partition_config, false);
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, second_storage_partition_config, false, false);
|
||||
EXPECT_EQ(
|
||||
profile_.GetPrefs()->GetList(kFirstPartyStorageOriginsToCleanup).size(),
|
||||
2u);
|
||||
@@ -523,8 +532,8 @@ TEST_F(EphemeralStorageServiceForgetFirstPartyTest,
|
||||
{
|
||||
ScopedVerifyAndClearExpectations verify(mock_delegate_);
|
||||
ScopedVerifyAndClearExpectations verify_observer(&mock_observer_);
|
||||
service_->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
service_->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
EXPECT_EQ(
|
||||
profile_.GetPrefs()->GetList(kFirstPartyStorageOriginsToCleanup).size(),
|
||||
1u);
|
||||
@@ -590,8 +599,8 @@ TEST_F(EphemeralStorageServiceForgetFirstPartyTest, OffTheRecordSkipsPrefs) {
|
||||
.size(),
|
||||
0u);
|
||||
|
||||
otr_service->TLDEphemeralLifetimeDestroyed(ephemeral_domain,
|
||||
storage_partition_config, false);
|
||||
otr_service->TLDEphemeralLifetimeDestroyed(
|
||||
ephemeral_domain, storage_partition_config, false, false);
|
||||
EXPECT_EQ(otr_profile->GetPrefs()
|
||||
->GetList(kFirstPartyStorageOriginsToCleanup)
|
||||
.size(),
|
||||
|
||||
@@ -60,6 +60,12 @@ EphemeralStorageTabHelper::GetEphemeralStorageToken(const url::Origin& origin) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void EphemeralStorageTabHelper::EnforceFirstPartyStorageCleanup() {
|
||||
if (tld_ephemeral_lifetime_) {
|
||||
tld_ephemeral_lifetime_->EnforceFirstPartyStorageCleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void EphemeralStorageTabHelper::WebContentsDestroyed() {
|
||||
provisional_tld_ephemeral_lifetimes_.clear();
|
||||
tld_ephemeral_lifetime_.reset();
|
||||
|
||||
@@ -43,6 +43,8 @@ class EphemeralStorageTabHelper
|
||||
std::optional<base::UnguessableToken> GetEphemeralStorageToken(
|
||||
const url::Origin& origin);
|
||||
|
||||
void EnforceFirstPartyStorageCleanup();
|
||||
|
||||
private:
|
||||
friend class content::WebContentsUserData<EphemeralStorageTabHelper>;
|
||||
|
||||
|
||||
@@ -49,12 +49,17 @@ TLDEphemeralLifetime::~TLDEphemeralLifetime() {
|
||||
shields_state_on_hosts_, [](const auto& v) { return !v.second; });
|
||||
ephemeral_storage_service_->TLDEphemeralLifetimeDestroyed(
|
||||
key_.storage_domain, key_.storage_partition_config,
|
||||
shields_disabled_on_one_of_hosts);
|
||||
shields_disabled_on_one_of_hosts,
|
||||
first_party_storage_cleanup_enforced_);
|
||||
}
|
||||
|
||||
ActiveTLDStorageAreas().erase(key_);
|
||||
}
|
||||
|
||||
void TLDEphemeralLifetime::EnforceFirstPartyStorageCleanup() {
|
||||
first_party_storage_cleanup_enforced_ = true;
|
||||
}
|
||||
|
||||
// static
|
||||
TLDEphemeralLifetime* TLDEphemeralLifetime::Get(
|
||||
const TLDEphemeralLifetimeKey& key) {
|
||||
|
||||
@@ -57,6 +57,7 @@ class TLDEphemeralLifetime : public base::RefCounted<TLDEphemeralLifetime> {
|
||||
|
||||
const TLDEphemeralLifetimeKey& key() const { return key_; }
|
||||
void SetShieldsStateOnHost(std::string_view host, bool enabled);
|
||||
void EnforceFirstPartyStorageCleanup();
|
||||
|
||||
private:
|
||||
friend class RefCounted<TLDEphemeralLifetime>;
|
||||
@@ -65,6 +66,7 @@ class TLDEphemeralLifetime : public base::RefCounted<TLDEphemeralLifetime> {
|
||||
TLDEphemeralLifetimeKey key_;
|
||||
base::WeakPtr<EphemeralStorageService> ephemeral_storage_service_;
|
||||
absl::flat_hash_map<std::string, bool> shields_state_on_hosts_;
|
||||
bool first_party_storage_cleanup_enforced_{false};
|
||||
|
||||
base::WeakPtrFactory<TLDEphemeralLifetime> weak_factory_{this};
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/check_is_test.h"
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
@@ -47,6 +48,7 @@
|
||||
#include "components/tabs/public/tab_interface.h"
|
||||
#include "content/public/browser/file_select_listener.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
#include "content/public/common/url_constants.h"
|
||||
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
|
||||
#include "url/gurl.h"
|
||||
@@ -233,6 +235,15 @@ void BraveBrowser::OnTabStripModelChanged(
|
||||
selection.active_tab_changed()) {
|
||||
sidebar_controller->sidebar()->UpdateSidebarItemsState();
|
||||
}
|
||||
|
||||
// Check if all tabs we set to ignore onbeforeunload handler are closed.
|
||||
if (!tabs_closing_with_onbeforeunload_ignore_.empty() &&
|
||||
change.type() == TabStripModelChange::Type::kRemoved) {
|
||||
for (auto& removed_tab : change.GetRemove()->contents) {
|
||||
tabs_closing_with_onbeforeunload_ignore_.erase(
|
||||
removed_tab.tab->GetHandle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BraveBrowser::FinishWarnBeforeClosing(WarnBeforeClosingResult result) {
|
||||
@@ -359,3 +370,15 @@ bool BraveBrowser::AreAllTabsSharedPinnedTabs() {
|
||||
BraveBrowserWindow* BraveBrowser::brave_window() {
|
||||
return static_cast<BraveBrowserWindow*>(window_.get());
|
||||
}
|
||||
|
||||
void BraveBrowser::SetTabsToIgnoreBeforeUnloadHandlers(
|
||||
const base::flat_set<tabs::TabHandle>& for_contents) {
|
||||
tabs_closing_with_onbeforeunload_ignore_ = for_contents;
|
||||
}
|
||||
|
||||
bool BraveBrowser::ShouldSuppressDialogs(content::WebContents* source) {
|
||||
auto* tab = tabs::TabInterface::MaybeGetFromContents(source);
|
||||
return (tab && tabs_closing_with_onbeforeunload_ignore_.contains(
|
||||
tab->GetHandle())) ||
|
||||
content::WebContentsDelegate::ShouldSuppressDialogs(source);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/containers/flat_set.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "chrome/browser/ui/browser.h"
|
||||
@@ -69,6 +70,10 @@ class BraveBrowser : public Browser {
|
||||
// any warning/onbeforeunload handlers.
|
||||
bool ShouldAskForBrowserClosingBeforeHandlers();
|
||||
|
||||
// Allows ignoring onbeforeunload handlers when closing selected tabs.
|
||||
void SetTabsToIgnoreBeforeUnloadHandlers(
|
||||
const base::flat_set<tabs::TabHandle>& for_contents);
|
||||
|
||||
BraveBrowserWindow* brave_window();
|
||||
|
||||
void set_confirmed_to_close(bool close) { confirmed_to_close_ = close; }
|
||||
@@ -87,6 +92,8 @@ class BraveBrowser : public Browser {
|
||||
|
||||
bool AreAllTabsSharedPinnedTabs();
|
||||
|
||||
bool ShouldSuppressDialogs(content::WebContents* source) override;
|
||||
|
||||
// Set true when user allowed to close browser before starting any
|
||||
// warning or onbeforeunload handlers.
|
||||
bool confirmed_to_close_ = false;
|
||||
@@ -96,6 +103,9 @@ class BraveBrowser : public Browser {
|
||||
// new tab, like when user tries to "Bring all tabs" to other window.
|
||||
bool ignore_enable_closing_last_tab_pref_ = false;
|
||||
|
||||
// WebContents for which onbeforeunload handlers should be ignored.
|
||||
base::flat_set<tabs::TabHandle> tabs_closing_with_onbeforeunload_ignore_;
|
||||
|
||||
base::WeakPtrFactory<BraveBrowser> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "components/content_settings/core/common/content_settings_pattern.h"
|
||||
#include "components/content_settings/core/common/content_settings_types.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "net/base/url_util.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace brave_shields {
|
||||
@@ -256,4 +257,42 @@ BraveShieldsSettingsService::GetJsContentSettingOverriddenData(
|
||||
rule, ConvertSettingsSource(info.source));
|
||||
}
|
||||
|
||||
bool BraveShieldsSettingsService::IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
const GURL& url) const {
|
||||
// First check the exact domain
|
||||
if (CONTENT_SETTING_BLOCK ==
|
||||
host_content_settings_map_->GetContentSetting(
|
||||
url, GURL(), ContentSettingsType::BRAVE_SHIELDS)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check parent domains by iterating through all shield settings
|
||||
ContentSettingsForOneType all_shield_settings =
|
||||
host_content_settings_map_->GetSettingsForOneType(
|
||||
ContentSettingsType::BRAVE_SHIELDS);
|
||||
|
||||
const auto ephemeral_domain = net::URLToEphemeralStorageDomain(url);
|
||||
|
||||
for (const auto& setting : all_shield_settings) {
|
||||
// Skip invalid patterns or settings that don't disable shields
|
||||
if (!setting.primary_pattern.IsValid() ||
|
||||
setting.setting_value != CONTENT_SETTING_BLOCK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip wildcard patterns that match all hosts
|
||||
if (setting.primary_pattern.MatchesAllHosts()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (const GURL pattern_url(setting.primary_pattern.ToRepresentativeUrl());
|
||||
pattern_url.is_valid() &&
|
||||
ephemeral_domain == net::URLToEphemeralStorageDomain(pattern_url)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace brave_shields
|
||||
|
||||
@@ -63,6 +63,8 @@ class BraveShieldsSettingsService : public KeyedService {
|
||||
mojom::ContentSettingsOverriddenDataPtr GetJsContentSettingOverriddenData(
|
||||
const GURL& url);
|
||||
|
||||
bool IsShieldsDisabledOnAnyHostMatchingDomainOf(const GURL& url) const;
|
||||
|
||||
private:
|
||||
const raw_ref<HostContentSettingsMap>
|
||||
host_content_settings_map_; // NOT OWNED
|
||||
|
||||
@@ -432,3 +432,186 @@ TEST_F(BraveShieldsSettingsServiceTest,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_NoSettings) {
|
||||
// With no shield settings, should return false
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://test.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_ExactDomainMatch) {
|
||||
// Tests exact domain matching
|
||||
const auto example_com_url = GURL("https://example.com");
|
||||
brave_shields_settings()->SetBraveShieldsEnabled(false, example_com_url);
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://test.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_WildcardPattern) {
|
||||
// Set shields to BLOCK for wildcard pattern
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("[*.]example.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://test.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_SubdomainPattern) {
|
||||
// Tests specific subdomain patterns
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("sub.example.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://test.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_AllowSettingIgnored) {
|
||||
// Set shields to ALLOW (not BLOCK) - should be ignored
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("example.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_ALLOW);
|
||||
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_AllHostsPatternIgnored) {
|
||||
// Test whildcard hosts pattern
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
|
||||
ContentSettingsType::BRAVE_SHIELDS, CONTENT_SETTING_BLOCK);
|
||||
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_MultipleSettings) {
|
||||
// Set multiple settings - some matching, some not
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("test.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("other.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_ALLOW);
|
||||
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("[*.]example.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://test.com")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://other.com")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://unrelated.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_DifferentSubdomains) {
|
||||
// Set shields to BLOCK for specific subdomain
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("mail.test.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
// Should match for test.com ephemeral domain
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://test.com")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_PortsInPatterns) {
|
||||
// Test with patterns that include ports
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("example.com:8080"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com:8080")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://test.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_MixedSchemePatterns) {
|
||||
// Test with different scheme patterns
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("http://example.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("https://test.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://test.com")));
|
||||
}
|
||||
|
||||
TEST_F(BraveShieldsSettingsServiceTest,
|
||||
IsShieldsDisabledOnAnyHostMatchingDomainOf_DeepSubdomainHierarchy) {
|
||||
// Test with deeply nested subdomains
|
||||
GetHostContentSettingsMap()->SetContentSettingCustomScope(
|
||||
ContentSettingsPattern::FromString("a.b.c.d.example.com"),
|
||||
ContentSettingsPattern::Wildcard(), ContentSettingsType::BRAVE_SHIELDS,
|
||||
CONTENT_SETTING_BLOCK);
|
||||
|
||||
EXPECT_TRUE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://example.com")));
|
||||
EXPECT_FALSE(
|
||||
brave_shields_settings()->IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
GURL("https://other.com")));
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ static_library("ephemeral_storage") {
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//brave/components/brave_shields/core/common",
|
||||
"//components/content_settings/core/browser",
|
||||
"//components/keyed_service/core",
|
||||
"//components/prefs",
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/strcat.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "brave/components/brave_shields/core/common/features.h"
|
||||
#include "brave/components/ephemeral_storage/ephemeral_storage_pref_names.h"
|
||||
#include "brave/components/ephemeral_storage/url_storage_checker.h"
|
||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||
@@ -23,6 +25,7 @@
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
#include "content/public/browser/storage_partition_config.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "net/base/features.h"
|
||||
#include "net/base/schemeful_site.h"
|
||||
#include "net/base/url_util.h"
|
||||
@@ -221,20 +224,26 @@ void EphemeralStorageService::TLDEphemeralLifetimeCreated(
|
||||
void EphemeralStorageService::TLDEphemeralLifetimeDestroyed(
|
||||
const std::string& ephemeral_domain,
|
||||
const content::StoragePartitionConfig& storage_partition_config,
|
||||
bool shields_disabled_on_one_of_hosts) {
|
||||
bool shields_disabled_on_one_of_hosts,
|
||||
bool first_party_storage_cleanup_enforced) {
|
||||
DVLOG(1) << __func__ << " " << ephemeral_domain << " "
|
||||
<< storage_partition_config;
|
||||
const TLDEphemeralAreaKey key(ephemeral_domain, storage_partition_config);
|
||||
const bool cleanup_tld_ephemeral_area = !shields_disabled_on_one_of_hosts;
|
||||
const bool cleanup_tld_ephemeral_area =
|
||||
!shields_disabled_on_one_of_hosts || first_party_storage_cleanup_enforced;
|
||||
const bool cleanup_first_party_storage_area =
|
||||
FirstPartyStorageAreaNotInUse(ephemeral_domain, storage_partition_config,
|
||||
shields_disabled_on_one_of_hosts);
|
||||
shields_disabled_on_one_of_hosts) ||
|
||||
first_party_storage_cleanup_enforced;
|
||||
|
||||
if (base::FeatureList::IsEnabled(
|
||||
if (first_party_storage_cleanup_enforced ||
|
||||
base::FeatureList::IsEnabled(
|
||||
net::features::kBraveEphemeralStorageKeepAlive)) {
|
||||
auto cleanup_timer = std::make_unique<base::OneShotTimer>();
|
||||
cleanup_timer->Start(
|
||||
FROM_HERE, tld_ephemeral_area_keep_alive_,
|
||||
FROM_HERE,
|
||||
first_party_storage_cleanup_enforced ? base::Milliseconds(500)
|
||||
: tld_ephemeral_area_keep_alive_,
|
||||
base::BindOnce(&EphemeralStorageService::CleanupTLDEphemeralAreaByTimer,
|
||||
weak_ptr_factory_.GetWeakPtr(), key,
|
||||
cleanup_tld_ephemeral_area,
|
||||
@@ -256,6 +265,27 @@ void EphemeralStorageService::RemoveObserver(
|
||||
observer_list_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
void EphemeralStorageService::CleanupTLDFirstPartyStorage(
|
||||
const GURL& url,
|
||||
const content::StoragePartitionConfig& storage_partition_config,
|
||||
const bool enforced_by_user) {
|
||||
if (!base::FeatureList::IsEnabled(
|
||||
brave_shields::features::kBraveShredFeature)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enforced_by_user &&
|
||||
delegate_->IsShieldsDisabledOnAnyHostMatchingDomainOf(url)) {
|
||||
// Do not start auto shred if shields is disabled on any host matching the
|
||||
// domain or ephemeral_domain is empty.
|
||||
return;
|
||||
}
|
||||
|
||||
const auto ephemeral_domain = net::URLToEphemeralStorageDomain(url);
|
||||
delegate_->PrepareTabsForFirstPartyStorageCleanup(
|
||||
std::move(ephemeral_domain));
|
||||
}
|
||||
|
||||
void EphemeralStorageService::FirstPartyStorageAreaInUse(
|
||||
const std::string& ephemeral_domain,
|
||||
const content::StoragePartitionConfig& storage_partition_config) {
|
||||
|
||||
@@ -77,11 +77,17 @@ class EphemeralStorageService : public KeyedService {
|
||||
void TLDEphemeralLifetimeDestroyed(
|
||||
const std::string& ephemeral_domain,
|
||||
const content::StoragePartitionConfig& storage_partition_config,
|
||||
bool shields_disabled_on_one_of_hosts);
|
||||
bool shields_disabled_on_one_of_hosts,
|
||||
bool first_party_storage_cleanup_enforced);
|
||||
|
||||
void AddObserver(EphemeralStorageServiceObserver* observer);
|
||||
void RemoveObserver(EphemeralStorageServiceObserver* observer);
|
||||
|
||||
void CleanupTLDFirstPartyStorage(
|
||||
const GURL& url,
|
||||
const content::StoragePartitionConfig& storage_partition_config,
|
||||
const bool enforced_by_user);
|
||||
|
||||
private:
|
||||
friend EphemeralStorageBrowserTest;
|
||||
friend EphemeralStorageQaBrowserTest;
|
||||
|
||||
@@ -6,8 +6,11 @@
|
||||
#ifndef BRAVE_COMPONENTS_EPHEMERAL_STORAGE_EPHEMERAL_STORAGE_SERVICE_DELEGATE_H_
|
||||
#define BRAVE_COMPONENTS_EPHEMERAL_STORAGE_EPHEMERAL_STORAGE_SERVICE_DELEGATE_H_
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "base/functional/callback.h"
|
||||
#include "brave/components/ephemeral_storage/ephemeral_storage_types.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace ephemeral_storage {
|
||||
|
||||
@@ -23,6 +26,10 @@ class EphemeralStorageServiceDelegate {
|
||||
// Registers a callback to be called when the first window is opened.
|
||||
virtual void RegisterFirstWindowOpenedCallback(
|
||||
base::OnceClosure callback) = 0;
|
||||
virtual void PrepareTabsForFirstPartyStorageCleanup(
|
||||
const std::string& ephemeral_domain) = 0;
|
||||
virtual bool IsShieldsDisabledOnAnyHostMatchingDomainOf(
|
||||
const GURL& url) const = 0;
|
||||
};
|
||||
|
||||
} // namespace ephemeral_storage
|
||||
|
||||
Reference in New Issue
Block a user