Support StoragePartitionConfig setting on WebContents creation. (#31761)
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import("//brave/components/containers/buildflags/buildflags.gni")
|
||||
|
||||
assert(enable_containers)
|
||||
|
||||
source_set("browser_tests") {
|
||||
testonly = true
|
||||
|
||||
sources = [ "containers_browsertest.cc" ]
|
||||
|
||||
deps = [
|
||||
"//brave/components/containers/core/common:features",
|
||||
"//chrome/browser",
|
||||
"//chrome/test:test_support",
|
||||
]
|
||||
|
||||
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
|
||||
}
|
||||
@@ -0,0 +1,465 @@
|
||||
/* Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/containers/core/common/features.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/browser/ui/browser.h"
|
||||
#include "chrome/browser/ui/browser_navigator.h"
|
||||
#include "chrome/browser/ui/browser_navigator_params.h"
|
||||
#include "chrome/test/base/in_process_browser_test.h"
|
||||
#include "chrome/test/base/ui_test_utils.h"
|
||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||
#include "content/public/test/browser_test.h"
|
||||
#include "content/public/test/browser_test_utils.h"
|
||||
#include "net/dns/mock_host_resolver.h"
|
||||
#include "net/test/embedded_test_server/embedded_test_server.h"
|
||||
#include "services/network/public/cpp/network_switches.h"
|
||||
#include "third_party/abseil-cpp/absl/strings/str_format.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace containers {
|
||||
|
||||
class ContainersBrowserTest : public InProcessBrowserTest {
|
||||
public:
|
||||
ContainersBrowserTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
|
||||
feature_list_.InitAndEnableFeature(features::kContainers);
|
||||
https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
|
||||
|
||||
// Register a request handler for serving test HTML content
|
||||
https_server_.AddDefaultHandlers(
|
||||
base::FilePath(FILE_PATH_LITERAL("brave/test/data")));
|
||||
|
||||
EXPECT_TRUE(https_server_.Start());
|
||||
}
|
||||
|
||||
~ContainersBrowserTest() override = default;
|
||||
|
||||
void SetUpCommandLine(base::CommandLine* command_line) override {
|
||||
InProcessBrowserTest::SetUpCommandLine(command_line);
|
||||
command_line->AppendSwitchASCII(
|
||||
network::switches::kHostResolverRules,
|
||||
absl::StrFormat("MAP *:443 127.0.0.1:%d", https_server_.port()));
|
||||
}
|
||||
|
||||
void SetUpOnMainThread() override {
|
||||
InProcessBrowserTest::SetUpOnMainThread();
|
||||
host_resolver()->AddRule("*", "127.0.0.1");
|
||||
}
|
||||
|
||||
// JavaScript helper to set a cookie
|
||||
std::string SetCookieJS(const std::string& name, const std::string& value) {
|
||||
return absl::StrFormat(
|
||||
"document.cookie = `%s=%s; path=/; SameSite=None; Secure; expires=Wed "
|
||||
"Jan 01 2038 00:00:00 GMT`; "
|
||||
"document.cookie;",
|
||||
name, value);
|
||||
}
|
||||
|
||||
// JavaScript helper to get all cookies
|
||||
std::string GetCookiesJS() { return "document.cookie;"; }
|
||||
|
||||
// JavaScript helper to set localStorage item
|
||||
std::string SetLocalStorageJS(const std::string& key,
|
||||
const std::string& value) {
|
||||
return content::JsReplace(
|
||||
"localStorage.setItem($1, $2); "
|
||||
"localStorage.getItem($1);",
|
||||
key, value);
|
||||
}
|
||||
|
||||
// JavaScript helper to get localStorage item
|
||||
std::string GetLocalStorageJS(const std::string& key) {
|
||||
return content::JsReplace("localStorage.getItem($1);", key);
|
||||
}
|
||||
|
||||
// JavaScript helper to set sessionStorage item
|
||||
std::string SetSessionStorageJS(const std::string& key,
|
||||
const std::string& value) {
|
||||
return content::JsReplace(
|
||||
"sessionStorage.setItem($1, $2); "
|
||||
"sessionStorage.getItem($1);",
|
||||
key, value);
|
||||
}
|
||||
|
||||
// JavaScript helper to get sessionStorage item
|
||||
std::string GetSessionStorageJS(const std::string& key) {
|
||||
return content::JsReplace("sessionStorage.getItem($1);", key);
|
||||
}
|
||||
|
||||
// JavaScript helper to set IndexedDB item
|
||||
std::string SetIndexedDBJS(const std::string& key, const std::string& value) {
|
||||
return content::JsReplace(
|
||||
"new Promise((resolve, reject) => {"
|
||||
" const request = indexedDB.open('testDB', 1);"
|
||||
" request.onerror = (e) => reject(e.target.error);"
|
||||
" request.onsuccess = () => {"
|
||||
" const db = request.result;"
|
||||
" const transaction = db.transaction(['testStore'], 'readwrite');"
|
||||
" const store = transaction.objectStore('testStore');"
|
||||
" const putRequest = store.put($1, $2);"
|
||||
" putRequest.onsuccess = () => resolve(true);"
|
||||
" putRequest.onerror = (e) => reject(e.target.error);"
|
||||
" };"
|
||||
" request.onupgradeneeded = () => {"
|
||||
" const db = request.result;"
|
||||
" if (!db.objectStoreNames.contains('testStore')) {"
|
||||
" db.createObjectStore('testStore');"
|
||||
" }"
|
||||
" };"
|
||||
"});",
|
||||
value, key);
|
||||
}
|
||||
|
||||
// JavaScript helper to get IndexedDB item
|
||||
std::string GetIndexedDBJS(const std::string& key) {
|
||||
return content::JsReplace(
|
||||
"new Promise((resolve, reject) => {"
|
||||
" const request = indexedDB.open('testDB', 1);"
|
||||
" request.onerror = (e) => reject(e.target.error);"
|
||||
" request.onsuccess = () => {"
|
||||
" const db = request.result;"
|
||||
" const transaction = db.transaction(['testStore'], 'readonly');"
|
||||
" const store = transaction.objectStore('testStore');"
|
||||
" const getRequest = store.get($1);"
|
||||
" getRequest.onsuccess = () => resolve(getRequest.result || null);"
|
||||
" getRequest.onerror = (e) => reject(e.target.error);"
|
||||
" };"
|
||||
" request.onupgradeneeded = () => {"
|
||||
" const db = request.result;"
|
||||
" if (!db.objectStoreNames.contains('testStore')) {"
|
||||
" db.createObjectStore('testStore');"
|
||||
" }"
|
||||
" };"
|
||||
"});",
|
||||
key);
|
||||
}
|
||||
|
||||
// JavaScript helper to clear all storage
|
||||
std::string ClearAllStorageJS() {
|
||||
return "localStorage.clear(); sessionStorage.clear(); 'cleared';";
|
||||
}
|
||||
|
||||
// JavaScript helper to register a service worker
|
||||
std::string RegisterServiceWorkerJS(const std::string& script_url,
|
||||
const std::string& scope) {
|
||||
return content::JsReplace(
|
||||
"new Promise((resolve, reject) => {"
|
||||
" navigator.serviceWorker.register($1, {scope: $2})"
|
||||
" .then(registration => {"
|
||||
" console.log('Service worker registered:', registration);"
|
||||
" resolve('registered');"
|
||||
" })"
|
||||
" .catch(error => {"
|
||||
" console.error('Service worker registration failed:', error);"
|
||||
" reject(error.toString());"
|
||||
" });"
|
||||
"});",
|
||||
script_url, scope);
|
||||
}
|
||||
|
||||
// JavaScript helper to check if a service worker is registered
|
||||
std::string CheckServiceWorkerRegisteredJS(const std::string& scope) {
|
||||
return content::JsReplace(
|
||||
"new Promise((resolve) => {"
|
||||
" navigator.serviceWorker.getRegistrations().then(registrations => {"
|
||||
" const matching = registrations.filter(reg => reg.scope === $1);"
|
||||
" resolve(matching.length > 0 ? 'registered' : 'not_registered');"
|
||||
" });"
|
||||
"});",
|
||||
scope);
|
||||
}
|
||||
|
||||
// JavaScript helper to get service worker registration count
|
||||
std::string GetServiceWorkerRegistrationCountJS() {
|
||||
return "new Promise((resolve) => {"
|
||||
" navigator.serviceWorker.getRegistrations().then(registrations => "
|
||||
"{"
|
||||
" resolve(registrations.length);"
|
||||
" });"
|
||||
"});";
|
||||
}
|
||||
|
||||
// JavaScript helper to unregister all service workers
|
||||
std::string UnregisterAllServiceWorkersJS() {
|
||||
return "new Promise((resolve) => {"
|
||||
" navigator.serviceWorker.getRegistrations().then(registrations => "
|
||||
"{"
|
||||
" const promises = registrations.map(reg => reg.unregister());"
|
||||
" Promise.all(promises).then(() => resolve('unregistered'));"
|
||||
" });"
|
||||
"});";
|
||||
}
|
||||
|
||||
protected:
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
net::EmbeddedTestServer https_server_;
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(ContainersBrowserTest, IsolateCookiesAndStorage) {
|
||||
const GURL url("https://a.test/simple.html");
|
||||
|
||||
// Navigate to URL without container
|
||||
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
|
||||
content::WebContents* web_contents_default =
|
||||
browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(web_contents_default);
|
||||
|
||||
// Set storage data in the default storage partition
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_default,
|
||||
SetCookieJS("test_cookie", "value_a")));
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_default,
|
||||
SetLocalStorageJS("test_key", "value_a")));
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_default,
|
||||
SetSessionStorageJS("test_key", "value_a")));
|
||||
|
||||
// Set IndexedDB data in the default storage partition
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_default,
|
||||
SetIndexedDBJS("test_key", "value_a")));
|
||||
|
||||
// Verify storage data is set correctly in the default storage partition
|
||||
content::EvalJsResult cookie_result =
|
||||
content::EvalJs(web_contents_default, GetCookiesJS());
|
||||
EXPECT_TRUE(cookie_result.ExtractString().find("test_cookie=value_a") !=
|
||||
std::string::npos);
|
||||
|
||||
EXPECT_EQ("value_a", content::EvalJs(web_contents_default,
|
||||
GetLocalStorageJS("test_key")));
|
||||
EXPECT_EQ("value_a", content::EvalJs(web_contents_default,
|
||||
GetSessionStorageJS("test_key")));
|
||||
EXPECT_EQ("value_a",
|
||||
content::EvalJs(web_contents_default, GetIndexedDBJS("test_key")));
|
||||
|
||||
// Open a new tab with a different storage partition
|
||||
NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK);
|
||||
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
|
||||
params.storage_partition_config = content::StoragePartitionConfig::Create(
|
||||
browser()->profile(), "default", "container-a",
|
||||
browser()->profile()->IsOffTheRecord());
|
||||
ui_test_utils::NavigateToURL(¶ms);
|
||||
|
||||
content::WebContents* web_contents_container_a =
|
||||
browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(web_contents_container_a);
|
||||
|
||||
// Verify that the new container doesn't have access to the first container's
|
||||
// storage
|
||||
content::EvalJsResult cookie_result_a =
|
||||
content::EvalJs(web_contents_container_a, GetCookiesJS());
|
||||
EXPECT_TRUE(cookie_result_a.ExtractString().find("test_cookie=value_a") ==
|
||||
std::string::npos);
|
||||
|
||||
EXPECT_EQ(base::Value(), content::EvalJs(web_contents_container_a,
|
||||
GetLocalStorageJS("test_key")));
|
||||
EXPECT_EQ(base::Value(), content::EvalJs(web_contents_container_a,
|
||||
GetSessionStorageJS("test_key")));
|
||||
EXPECT_EQ(base::Value(), content::EvalJs(web_contents_container_a,
|
||||
GetIndexedDBJS("test_key")));
|
||||
|
||||
// Set different storage data in the container
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_container_a,
|
||||
SetCookieJS("test_cookie", "value_b")));
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_container_a,
|
||||
SetLocalStorageJS("test_key", "value_b")));
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_container_a,
|
||||
SetSessionStorageJS("test_key", "value_b")));
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_container_a,
|
||||
SetIndexedDBJS("test_key", "value_b")));
|
||||
|
||||
// Verify container has its own data
|
||||
cookie_result_a = content::EvalJs(web_contents_container_a, GetCookiesJS());
|
||||
EXPECT_TRUE(cookie_result_a.ExtractString().find("test_cookie=value_b") !=
|
||||
std::string::npos);
|
||||
EXPECT_EQ("value_b", content::EvalJs(web_contents_container_a,
|
||||
GetLocalStorageJS("test_key")));
|
||||
EXPECT_EQ("value_b", content::EvalJs(web_contents_container_a,
|
||||
GetSessionStorageJS("test_key")));
|
||||
EXPECT_EQ("value_b", content::EvalJs(web_contents_container_a,
|
||||
GetIndexedDBJS("test_key")));
|
||||
|
||||
// Check the data in default tab to container and verify its data is unchanged
|
||||
content::EvalJsResult cookie_result_default =
|
||||
content::EvalJs(web_contents_default, GetCookiesJS());
|
||||
EXPECT_TRUE(cookie_result_default.ExtractString().find(
|
||||
"test_cookie=value_a") != std::string::npos);
|
||||
EXPECT_EQ("value_a", content::EvalJs(web_contents_default,
|
||||
GetLocalStorageJS("test_key")));
|
||||
EXPECT_EQ("value_a", content::EvalJs(web_contents_default,
|
||||
GetSessionStorageJS("test_key")));
|
||||
EXPECT_EQ("value_a",
|
||||
content::EvalJs(web_contents_default, GetIndexedDBJS("test_key")));
|
||||
|
||||
// Verify default storage partition doesn't have access to container's data
|
||||
EXPECT_TRUE(cookie_result_default.ExtractString().find(
|
||||
"test_cookie=value_b") == std::string::npos);
|
||||
|
||||
// Open a new tab with a different storage partition
|
||||
NavigateParams params_b(browser(), url, ui::PAGE_TRANSITION_LINK);
|
||||
params_b.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
|
||||
params_b.storage_partition_config = content::StoragePartitionConfig::Create(
|
||||
browser()->profile(), "default", "container-b",
|
||||
browser()->profile()->IsOffTheRecord());
|
||||
ui_test_utils::NavigateToURL(¶ms_b);
|
||||
|
||||
content::WebContents* web_contents_container_b =
|
||||
browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(web_contents_container_b);
|
||||
|
||||
// Verify that the new container doesn't have access to the first container's
|
||||
// storage
|
||||
content::EvalJsResult cookie_result_b =
|
||||
content::EvalJs(web_contents_container_b, GetCookiesJS());
|
||||
EXPECT_TRUE(cookie_result_b.ExtractString().find("test_cookie=value_a") ==
|
||||
std::string::npos);
|
||||
EXPECT_EQ(base::Value(), content::EvalJs(web_contents_container_b,
|
||||
GetLocalStorageJS("test_key")));
|
||||
EXPECT_EQ(base::Value(), content::EvalJs(web_contents_container_b,
|
||||
GetSessionStorageJS("test_key")));
|
||||
EXPECT_EQ(base::Value(), content::EvalJs(web_contents_container_b,
|
||||
GetIndexedDBJS("test_key")));
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(ContainersBrowserTest, IsolateServiceWorkers) {
|
||||
const GURL url("https://a.test/containers/container_test.html");
|
||||
const GURL worker_url("https://a.test/containers/container_worker.js");
|
||||
const std::string scope = "https://a.test/containers/";
|
||||
|
||||
// Navigate to URL without container
|
||||
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
|
||||
content::WebContents* web_contents_default =
|
||||
browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(web_contents_default);
|
||||
|
||||
// Register service worker in default storage partition
|
||||
EXPECT_TRUE(content::ExecJs(
|
||||
web_contents_default, RegisterServiceWorkerJS(worker_url.spec(), scope)));
|
||||
|
||||
// Verify service worker is registered in default partition
|
||||
EXPECT_EQ("registered",
|
||||
content::EvalJs(web_contents_default,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
|
||||
// Verify we have exactly 1 service worker registration
|
||||
EXPECT_EQ(1, content::EvalJs(web_contents_default,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
// Open a new tab with a different storage partition (container-a)
|
||||
NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK);
|
||||
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
|
||||
params.storage_partition_config = content::StoragePartitionConfig::Create(
|
||||
browser()->profile(), "default", "container-a",
|
||||
browser()->profile()->IsOffTheRecord());
|
||||
ui_test_utils::NavigateToURL(¶ms);
|
||||
|
||||
content::WebContents* web_contents_container_a =
|
||||
browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(web_contents_container_a);
|
||||
|
||||
// Verify that the container doesn't see the service worker from default
|
||||
// partition
|
||||
EXPECT_EQ("not_registered",
|
||||
content::EvalJs(web_contents_container_a,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
|
||||
// Verify container has 0 service worker registrations
|
||||
EXPECT_EQ(0, content::EvalJs(web_contents_container_a,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
// Register a different service worker in the container
|
||||
EXPECT_TRUE(
|
||||
content::ExecJs(web_contents_container_a,
|
||||
RegisterServiceWorkerJS(worker_url.spec(), scope)));
|
||||
|
||||
// Verify service worker is registered in container partition
|
||||
EXPECT_EQ("registered",
|
||||
content::EvalJs(web_contents_container_a,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
|
||||
// Verify container has exactly 1 service worker registration
|
||||
EXPECT_EQ(1, content::EvalJs(web_contents_container_a,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
// Verify default partition still has its service worker
|
||||
EXPECT_EQ("registered",
|
||||
content::EvalJs(web_contents_default,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
|
||||
// Verify default partition still has exactly 1 service worker registration
|
||||
EXPECT_EQ(1, content::EvalJs(web_contents_default,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
// Open another container (container-b)
|
||||
NavigateParams params_b(browser(), url, ui::PAGE_TRANSITION_LINK);
|
||||
params_b.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
|
||||
params_b.storage_partition_config = content::StoragePartitionConfig::Create(
|
||||
browser()->profile(), "default", "container-b",
|
||||
browser()->profile()->IsOffTheRecord());
|
||||
ui_test_utils::NavigateToURL(¶ms_b);
|
||||
|
||||
content::WebContents* web_contents_container_b =
|
||||
browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(web_contents_container_b);
|
||||
|
||||
// Verify that container_b doesn't see service workers from other partitions
|
||||
EXPECT_EQ("not_registered",
|
||||
content::EvalJs(web_contents_container_b,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
|
||||
// Verify container_b has 0 service worker registrations
|
||||
EXPECT_EQ(0, content::EvalJs(web_contents_container_b,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
// Register service worker in container_b
|
||||
EXPECT_TRUE(
|
||||
content::ExecJs(web_contents_container_b,
|
||||
RegisterServiceWorkerJS(worker_url.spec(), scope)));
|
||||
|
||||
// Verify service worker is registered in container_b partition
|
||||
EXPECT_EQ("registered",
|
||||
content::EvalJs(web_contents_container_b,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
|
||||
// Verify container_b has exactly 1 service worker registration
|
||||
EXPECT_EQ(1, content::EvalJs(web_contents_container_b,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
// Verify other partitions are unaffected
|
||||
EXPECT_EQ("registered",
|
||||
content::EvalJs(web_contents_default,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
EXPECT_EQ(1, content::EvalJs(web_contents_default,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
EXPECT_EQ("registered",
|
||||
content::EvalJs(web_contents_container_a,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
EXPECT_EQ(1, content::EvalJs(web_contents_container_a,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
// Test unregistering service worker in one container doesn't affect others
|
||||
EXPECT_TRUE(content::ExecJs(web_contents_container_a,
|
||||
UnregisterAllServiceWorkersJS()));
|
||||
|
||||
// Verify container_a no longer has service workers
|
||||
EXPECT_EQ("not_registered",
|
||||
content::EvalJs(web_contents_container_a,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
EXPECT_EQ(0, content::EvalJs(web_contents_container_a,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
// Verify other partitions still have their service workers
|
||||
EXPECT_EQ("registered",
|
||||
content::EvalJs(web_contents_default,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
EXPECT_EQ(1, content::EvalJs(web_contents_default,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
|
||||
EXPECT_EQ("registered",
|
||||
content::EvalJs(web_contents_container_b,
|
||||
CheckServiceWorkerRegisteredJS(scope)));
|
||||
EXPECT_EQ(1, content::EvalJs(web_contents_container_b,
|
||||
GetServiceWorkerRegistrationCountJS()));
|
||||
}
|
||||
|
||||
} // namespace containers
|
||||
@@ -36,11 +36,17 @@ group("ui_public_dependencies") {
|
||||
":brave_tab_features",
|
||||
":brave_tab_prefs",
|
||||
"//brave/components/brave_wayback_machine/buildflags",
|
||||
"//brave/components/containers/buildflags",
|
||||
"//brave/components/playlist/core/common/buildflags",
|
||||
"//brave/components/speedreader/common/buildflags",
|
||||
]
|
||||
}
|
||||
|
||||
group("browser_navigator_params_headers_public_dependencies") {
|
||||
visibility = [ "//chrome/browser/ui:browser_navigator_params_headers" ]
|
||||
public_deps = [ "//brave/components/containers/buildflags" ]
|
||||
}
|
||||
|
||||
source_set("ui") {
|
||||
# Depend on //chrome/browser/ui instead of //brave/browser/ui.
|
||||
visibility = [
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
include_rules = [
|
||||
"+brave/components/containers/buildflags",
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
/* Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "brave/components/containers/buildflags/buildflags.h"
|
||||
#include "chrome/browser/tab_contents/tab_util.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#define GetSiteInstanceForNewTab(profile, url) \
|
||||
GetSiteInstanceForNewTab(profile, url, std::nullopt)
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
|
||||
#include <chrome/browser/password_manager/password_change_delegate_impl.cc>
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#undef GetSiteInstanceForNewTab
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
@@ -0,0 +1,3 @@
|
||||
include_rules = [
|
||||
"+brave/components/containers/buildflags",
|
||||
]
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "chrome/browser/tab_contents/tab_util.h"
|
||||
|
||||
#include "brave/components/containers/buildflags/buildflags.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#define GetSiteInstanceForNewTab(...) \
|
||||
GetSiteInstanceForNewTab( \
|
||||
__VA_ARGS__, \
|
||||
std::optional<content::StoragePartitionConfig> storage_partition_config)
|
||||
|
||||
#define BRAVE_GET_SITE_INSTANCE_FOR_NEW_TAB \
|
||||
if (storage_partition_config) { \
|
||||
return SiteInstance::CreateForFixedStoragePartition( \
|
||||
profile, url, *storage_partition_config); \
|
||||
}
|
||||
#else
|
||||
#define BRAVE_GET_SITE_INSTANCE_FOR_NEW_TAB
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
|
||||
#include <chrome/browser/tab_contents/tab_util.cc> // IWYU pragma: export
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#undef GetSiteInstanceForNewTab
|
||||
#undef BRAVE_GET_SITE_INSTANCE_FOR_NEW_TAB
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef BRAVE_CHROMIUM_SRC_CHROME_BROWSER_TAB_CONTENTS_TAB_UTIL_H_
|
||||
#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_TAB_CONTENTS_TAB_UTIL_H_
|
||||
|
||||
#include "brave/components/containers/buildflags/buildflags.h"
|
||||
#include "content/public/browser/storage_partition_config.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#define GetSiteInstanceForNewTab(...) \
|
||||
GetSiteInstanceForNewTab( \
|
||||
__VA_ARGS__, \
|
||||
std::optional<content::StoragePartitionConfig> storage_partition_config)
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
|
||||
#include <chrome/browser/tab_contents/tab_util.h> // IWYU pragma: export
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#undef GetSiteInstanceForNewTab
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
|
||||
#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_TAB_CONTENTS_TAB_UTIL_H_
|
||||
@@ -5,6 +5,7 @@ include_rules += [
|
||||
"+brave/components/vector_icons",
|
||||
"+brave/components/commander/common",
|
||||
"+brave/components/constants",
|
||||
"+brave/components/containers/buildflags",
|
||||
"+brave/components/omnibox/browser",
|
||||
"+brave/components/tor/buildflags",
|
||||
]
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "brave/components/containers/buildflags/buildflags.h"
|
||||
#include "chrome/browser/tab_contents/tab_util.h"
|
||||
#include "chrome/browser/ui/browser_navigator_params.h"
|
||||
#include "content/public/common/url_constants.h"
|
||||
#include "url/gurl.h"
|
||||
@@ -22,5 +24,16 @@ void UpdateBraveScheme(NavigateParams* params) {
|
||||
} // namespace
|
||||
|
||||
#define BRAVE_ADJUST_NAVIGATE_PARAMS_FOR_URL UpdateBraveScheme(params);
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#define GetSiteInstanceForNewTab(...) \
|
||||
GetSiteInstanceForNewTab(__VA_ARGS__, params.storage_partition_config)
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
|
||||
#include <chrome/browser/ui/browser_navigator.cc>
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#undef GetSiteInstanceForNewTab
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
|
||||
#undef BRAVE_ADJUST_NAVIGATE_PARAMS_FOR_URL
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_BROWSER_NAVIGATOR_PARAMS_H_
|
||||
#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_BROWSER_NAVIGATOR_PARAMS_H_
|
||||
|
||||
#include "brave/components/containers/buildflags/buildflags.h"
|
||||
#include "content/public/browser/storage_partition_config.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#define blob_url_loader_factory \
|
||||
blob_url_loader_factory; \
|
||||
std::optional<content::StoragePartitionConfig> storage_partition_config
|
||||
#endif
|
||||
|
||||
#include <chrome/browser/ui/browser_navigator_params.h> // IWYU pragma: export
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#undef blob_url_loader_factory
|
||||
#endif
|
||||
|
||||
#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_BROWSER_NAVIGATOR_PARAMS_H_
|
||||
@@ -9,16 +9,29 @@
|
||||
#include "brave/browser/ui/tabs/brave_tab_strip_model.h"
|
||||
#include "brave/browser/ui/tabs/features.h"
|
||||
#include "brave/browser/ui/tabs/public/constants.h"
|
||||
#include "brave/components/containers/buildflags/buildflags.h"
|
||||
#include "chrome/browser/ui/tab_ui_helper.h"
|
||||
#include "chrome/browser/ui/tabs/public/tab_features.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#include "chrome/browser/tab_contents/tab_util.h"
|
||||
|
||||
#define AddRestoredTab AddRestoredTab_ChromiumImpl
|
||||
#define ReplaceRestoredTab ReplaceRestoredTab_ChromiumImpl
|
||||
|
||||
#define GetSiteInstanceForNewTab(...) \
|
||||
GetSiteInstanceForNewTab(__VA_ARGS__, std::nullopt)
|
||||
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
|
||||
#include <chrome/browser/ui/browser_tabrestore.cc>
|
||||
|
||||
#undef ReplaceRestoredTab
|
||||
#undef AddRestoredTab
|
||||
#if BUILDFLAG(ENABLE_CONTAINERS)
|
||||
#undef GetSiteInstanceForNewTab
|
||||
#endif // BUILDFLAG(ENABLE_CONTAINERS)
|
||||
|
||||
namespace chrome {
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
diff --git a/chrome/browser/tab_contents/tab_util.cc b/chrome/browser/tab_contents/tab_util.cc
|
||||
index 4ccf096e97dafd9add0bb46c01397f294d4a6b84..209abdfe6cda1a01eb425a27af3a2aaf375918d7 100644
|
||||
--- a/chrome/browser/tab_contents/tab_util.cc
|
||||
+++ b/chrome/browser/tab_contents/tab_util.cc
|
||||
@@ -48,6 +48,7 @@ scoped_refptr<SiteInstance> GetSiteInstanceForNewTab(Profile* profile,
|
||||
if (!SiteInstance::ShouldAssignSiteForURL(url))
|
||||
return nullptr;
|
||||
|
||||
+ BRAVE_GET_SITE_INSTANCE_FOR_NEW_TAB
|
||||
return SiteInstance::CreateForURL(profile, url);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
|
||||
index f4531197ae5e1438c35a101d2c86c9b6edd1953f..e103798ae941c3e810611122c7d3cab5b0173551 100644
|
||||
index f4531197ae5e1438c35a101d2c86c9b6edd1953f..bf350e756272986f853eb42b9de8f64445f65b43 100644
|
||||
--- a/chrome/browser/ui/BUILD.gn
|
||||
+++ b/chrome/browser/ui/BUILD.gn
|
||||
@@ -769,6 +769,7 @@ static_library("ui") {
|
||||
@@ -38,3 +38,11 @@ index f4531197ae5e1438c35a101d2c86c9b6edd1953f..e103798ae941c3e810611122c7d3cab5
|
||||
}
|
||||
|
||||
source_set("url_identity") {
|
||||
@@ -5515,6 +5521,7 @@ source_set("browser_navigator_params_headers") {
|
||||
"//url",
|
||||
]
|
||||
deps = []
|
||||
+ public_deps += [ "//brave/browser/ui:browser_navigator_params_headers_public_dependencies" ]
|
||||
}
|
||||
|
||||
if (!is_android) {
|
||||
|
||||
@@ -1109,6 +1109,10 @@ test("brave_browser_tests") {
|
||||
deps += [ "//chrome/app/theme:chrome_unscaled_resources_grit" ]
|
||||
}
|
||||
|
||||
if (enable_containers) {
|
||||
deps += [ "//brave/browser/containers:browser_tests" ]
|
||||
}
|
||||
|
||||
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
|
||||
|
||||
if (toolkit_views) {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Container Service Worker Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Container Service Worker Test Page</h1>
|
||||
<p>This page is used to test service worker isolation in containers.</p>
|
||||
<div id="status">Loading...</div>
|
||||
|
||||
<script>
|
||||
// Display current page info
|
||||
document.getElementById('status').textContent =
|
||||
'Page loaded at: ' + new Date().toISOString()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2025 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 https://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Service worker for container isolation testing
|
||||
self.addEventListener('install', (event) => {
|
||||
console.log('Container service worker installing')
|
||||
self.skipWaiting()
|
||||
})
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
console.log('Container service worker activated')
|
||||
event.waitUntil(self.clients.claim())
|
||||
})
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
// Simple pass-through for testing
|
||||
event.respondWith(fetch(event.request))
|
||||
})
|
||||
Reference in New Issue
Block a user