blob: 8d883cf06bf298cade8bf4147b8eadae409ec9f6 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/path_service.h"
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/view_ids.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_launcher_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/browsing_data/content/cookie_helper.h"
#include "components/browsing_data/content/local_storage_helper.h"
#include "components/content_settings/browser/page_specific_content_settings.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/nacl/common/buildflags.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_access_details.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_paths.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/commit_message_delayer.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/ppapi_test_utils.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "net/cookies/canonical_cookie_test_helpers.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/url_request/url_request_mock_http_job.h"
#include "pdf/buildflags.h"
#include "ppapi/buildflags/buildflags.h"
#include "services/network/public/cpp/features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/widevine/cdm/buildflags.h"
#if BUILDFLAG(IS_MAC)
#include "base/apple/scoped_nsautorelease_pool.h"
#endif
#if BUILDFLAG(ENABLE_PDF)
#include "chrome/browser/pdf/pdf_extension_test_base.h"
#include "components/pdf/browser/pdf_frame_util.h"
#endif
#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/public/browser/plugin_service.h"
#endif
using content::BrowserThread;
using content_settings::PageSpecificContentSettings;
using net::URLRequestMockHTTPJob;
namespace {
BrowsingDataModel* GetSiteSettingsAllowedBrowsingDataModel(Browser* browser) {
PageSpecificContentSettings* settings =
PageSpecificContentSettings::GetForFrame(browser->tab_strip_model()
->GetActiveWebContents()
->GetPrimaryMainFrame());
return settings->allowed_browsing_data_model();
}
BrowsingDataModel* GetSiteSettingsBlockedBrowsingDataModel(Browser* browser) {
PageSpecificContentSettings* settings =
PageSpecificContentSettings::GetForFrame(browser->tab_strip_model()
->GetActiveWebContents()
->GetPrimaryMainFrame());
return settings->blocked_browsing_data_model();
}
net::CookieList ExtractCookiesFromModel(BrowsingDataModel* model) {
net::CookieList result;
for (const auto& [owner, key, details] : *model) {
if (const net::CanonicalCookie* cookie =
absl::get_if<net::CanonicalCookie>(&key.get())) {
result.push_back(*cookie);
}
}
return result;
}
size_t GetRenderFrameHostCount(content::RenderFrameHost* starting_frame) {
size_t count = 0;
starting_frame->ForEachRenderFrameHost(
[&](content::RenderFrameHost*) { ++count; });
return count;
}
class MockWebContentsLoadFailObserver : public content::WebContentsObserver {
public:
explicit MockWebContentsLoadFailObserver(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {}
~MockWebContentsLoadFailObserver() override = default;
MOCK_METHOD1(DidFinishNavigation,
void(content::NavigationHandle* navigation_handle));
};
MATCHER(IsErrorTooManyRedirects, "") {
return arg->GetNetErrorCode() == net::ERR_TOO_MANY_REDIRECTS;
}
// Return the active RenderFrameHost loaded in the last iframe in |parent_rfh|.
content::RenderFrameHost* LastChild(content::RenderFrameHost* parent_rfh) {
int child_end = 0;
while (ChildFrameAt(parent_rfh, child_end)) {
child_end++;
}
if (child_end == 0) {
return nullptr;
}
return ChildFrameAt(parent_rfh, child_end - 1);
}
// Create an <iframe> inside |parent_rfh|, and navigate it toward |url|.
// |permission_policy| can be used to set permission policy to the iframe.
// For instance:
// ```
// child = CreateIframe(parent, url, "geolocation *; camera *");
// ```
// This returns the new RenderFrameHost associated with new document created in
// the iframe.
content::RenderFrameHost* CreateIframe(
content::RenderFrameHost* parent_rfh,
const GURL& url,
const std::string& permission_policy = "") {
EXPECT_EQ(
"iframe loaded",
content::EvalJs(parent_rfh, content::JsReplace(R"(
new Promise((resolve) => {
const iframe = document.createElement("iframe");
iframe.src = $1;
iframe.allow = $2;
iframe.onload = _ => { resolve("iframe loaded"); };
document.body.appendChild(iframe);
}))",
url, permission_policy)));
return LastChild(parent_rfh);
}
size_t GetModelCookieCount(const BrowsingDataModel* model) {
size_t cookie_count = 0;
for (const auto& [owner, key, details] : *model) {
cookie_count += details->cookie_count;
}
return cookie_count;
}
} // namespace
class ContentSettingsTest : public InProcessBrowserTest {
public:
ContentSettingsTest() {
https_server_.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");
}
net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
};
// Test the combination of different ways of accessing cookies --- JS, HTML,
// or the new async cookie-store API.
enum class CookieMode {
kDocumentCookieJS,
kHttp,
kCookieStoreJS,
};
class CookieSettingsTest
: public ContentSettingsTest,
public testing::WithParamInterface<std::pair<CookieMode, CookieMode>> {
public:
CookieMode ReadMode() const { return GetParam().first; }
CookieMode WriteMode() const { return GetParam().second; }
void SetUpOnMainThread() override {
RegisterDefaultHandlers(embedded_test_server());
embedded_test_server()->RegisterRequestMonitor(base::BindRepeating(
&CookieSettingsTest::MonitorRequest, base::Unretained(this)));
RegisterDefaultHandlers(&https_server_);
https_server_.RegisterRequestMonitor(base::BindRepeating(
&CookieSettingsTest::MonitorRequest, base::Unretained(this)));
ASSERT_TRUE(embedded_test_server()->Start());
ASSERT_TRUE(https_server_.Start());
host_resolver()->AddRule("*", "127.0.0.1");
// CookieStore API is for https only.
if (ReadMode() == CookieMode::kCookieStoreJS ||
WriteMode() == CookieMode::kCookieStoreJS)
set_secure_scheme();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
ContentSettingsTest::SetUpCommandLine(command_line);
}
void set_secure_scheme() { secure_scheme_ = true; }
std::string ReadCookie(Browser* browser) {
switch (ReadMode()) {
case CookieMode::kDocumentCookieJS:
return JSReadCookie(browser);
case CookieMode::kHttp:
return HttpReadCookie(browser);
case CookieMode::kCookieStoreJS:
return JSAsyncReadCookie(browser);
}
}
void WriteCookie(Browser* browser) {
switch (WriteMode()) {
case CookieMode::kDocumentCookieJS:
return JSWriteCookie(browser);
case CookieMode::kHttp:
return HttpWriteCookie(browser);
case CookieMode::kCookieStoreJS:
return JSAsyncWriteCookie(browser);
}
}
// Check the cookie in an incognito window.
void CookieCheckIncognitoWindow(bool cookies_enabled) {
ASSERT_TRUE(ReadCookie(browser()).empty());
Browser* incognito = CreateIncognitoBrowser();
ASSERT_TRUE(ui_test_utils::NavigateToURL(incognito, GetPageURL()));
ASSERT_TRUE(ReadCookie(incognito).empty());
WriteCookie(incognito);
ASSERT_EQ(cookies_enabled, !ReadCookie(incognito).empty());
// Ensure incognito cookies don't leak to regular profile.
ASSERT_TRUE(ReadCookie(browser()).empty());
// Ensure cookies get wiped after last incognito window closes.
CloseBrowserSynchronously(incognito);
incognito = CreateIncognitoBrowser();
ASSERT_TRUE(ui_test_utils::NavigateToURL(incognito, GetPageURL()));
ASSERT_TRUE(ReadCookie(incognito).empty());
CloseBrowserSynchronously(incognito);
}
void PreBasic() {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
ASSERT_TRUE(ReadCookie(browser()).empty());
CookieCheckIncognitoWindow(true);
WriteCookie(browser());
ASSERT_FALSE(ReadCookie(browser()).empty());
}
void Basic() {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
ASSERT_FALSE(ReadCookie(browser()).empty());
}
GURL GetPageURL() { return GetServer()->GetURL("/simple.html"); }
GURL GetSetCookieURL() {
return GetServer()->GetURL("/set_cookie_header.html");
}
net::EmbeddedTestServer* GetOtherServer() {
return secure_scheme_ ? embedded_test_server() : &https_server_;
}
net::EmbeddedTestServer* GetServer() {
return secure_scheme_ ? &https_server_ : embedded_test_server();
}
// Read a cookie by fetching a url and checking what Cookie header (if any) it
// saw.
std::string HttpReadCookieWithURL(Browser* browser, const GURL& url) {
{
base::AutoLock auto_lock(cookies_seen_lock_);
cookies_seen_.clear();
}
auto* network_context =
browser->profile()->GetDefaultStoragePartition()->GetNetworkContext();
content::LoadBasicRequest(network_context, url);
{
base::AutoLock auto_lock(cookies_seen_lock_);
return cookies_seen_[url];
}
}
// Set a cookie by visiting a page that has a Set-Cookie header.
void HttpWriteCookieWithURL(Browser* browser, const GURL& url) {
auto* frame = browser->tab_strip_model()
->GetActiveWebContents()
->GetPrimaryMainFrame();
// Need to load via |frame| for the accessed/blocked cookies lists to be
// updated properly.
content::LoadBasicRequest(frame, url);
}
private:
// Read a cookie via JavaScript.
std::string JSReadCookie(Browser* browser) {
return content::EvalJs(browser->tab_strip_model()->GetActiveWebContents(),
"document.cookie")
.ExtractString();
}
// Read a cookie with JavaScript cookie-store API
std::string JSAsyncReadCookie(Browser* browser) {
return content::EvalJs(
browser->tab_strip_model()->GetActiveWebContents(),
"async function doGet() {"
" const cookies = await window.cookieStore.getAll();"
" let cookie_str = '';"
" for (const cookie of cookies)"
" cookie_str += `${cookie.name}=${cookie.value};`;"
" return cookie_str;"
"}"
"doGet()")
.ExtractString();
}
// Read a cookie by fetching the page url (which we should have just navigated
// to) and checking what Cookie header (if any) it saw.
std::string HttpReadCookie(Browser* browser) {
GURL url = browser->tab_strip_model()
->GetActiveWebContents()
->GetLastCommittedURL();
EXPECT_EQ(GetPageURL(), url);
return HttpReadCookieWithURL(browser, url);
}
// Set a cookie with JavaScript.
void JSWriteCookie(Browser* browser) {
bool rv =
content::ExecJs(browser->tab_strip_model()->GetActiveWebContents(),
"document.cookie = 'name=Good;Max-Age=3600'");
CHECK(rv);
}
// Set a cookie with JavaScript cookie-store api.
void JSAsyncWriteCookie(Browser* browser) {
content::EvalJsResult result =
content::EvalJs(browser->tab_strip_model()->GetActiveWebContents(),
"async function doSet() {"
" await window.cookieStore.set("
" { name: 'name',"
" value: 'Good',"
" expires: Date.now() + 3600*1000,"
" sameSite: 'none' });"
" return true;"
"}"
"doSet()");
// Failure ignored here since some tests purposefully try to set disallowed
// cookies.
}
// Set a cookie by visiting a page that has a Set-Cookie header.
void HttpWriteCookie(Browser* browser) {
HttpWriteCookieWithURL(browser, GetSetCookieURL());
}
void MonitorRequest(const net::test_server::HttpRequest& request) {
base::AutoLock auto_lock(cookies_seen_lock_);
auto it = request.headers.find("Cookie");
if (it != request.headers.end())
cookies_seen_[request.GetURL()] = it->second;
}
base::test::ScopedFeatureList scoped_feature_list_;
bool secure_scheme_ = false;
base::Lock cookies_seen_lock_;
std::map<GURL, std::string> cookies_seen_;
};
// Sanity check on cookies before we do other tests. While these can be written
// in content_browsertests, we want to verify Chrome's cookie storage and how it
// handles incognito windows.
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, PRE_BasicCookies) {
PreBasic();
}
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, BasicCookies) {
Basic();
}
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, PRE_BasicCookiesHttps) {
set_secure_scheme();
PreBasic();
}
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, BasicCookiesHttps) {
set_secure_scheme();
Basic();
}
// Verify that cookies are being blocked.
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, PRE_BlockCookies) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
WriteCookie(browser());
ASSERT_TRUE(ReadCookie(browser()).empty());
CookieCheckIncognitoWindow(false);
}
// Ensure that the setting persists.
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, BlockCookies) {
ASSERT_EQ(CONTENT_SETTING_BLOCK,
CookieSettingsFactory::GetForProfile(browser()->profile())
->GetDefaultCookieSetting());
}
// Verify that cookies can be allowed and set using exceptions for particular
// website(s) when all others are blocked.
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, AllowCookiesUsingExceptions) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
content::CookieChangeObserver observer1(
browser()->tab_strip_model()->GetActiveWebContents());
WriteCookie(browser());
ASSERT_TRUE(ReadCookie(browser()).empty());
observer1.Wait();
auto* allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
auto* blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
net::CookieList blocked_cookies;
ASSERT_EQ(0u, GetModelCookieCount(allowed_model));
ASSERT_EQ(1u, GetModelCookieCount(blocked_model));
blocked_cookies = ExtractCookiesFromModel(blocked_model);
EXPECT_THAT(blocked_cookies, net::MatchesCookieLine("name=Good"));
settings->SetCookieSetting(GetPageURL(), CONTENT_SETTING_ALLOW);
content::CookieChangeObserver observer2(
browser()->tab_strip_model()->GetActiveWebContents());
WriteCookie(browser());
ASSERT_FALSE(ReadCookie(browser()).empty());
observer2.Wait();
net::CookieList accepted_cookies;
allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
ASSERT_EQ(GetModelCookieCount(allowed_model), 1u);
// No navigation, so there should still be one blocked cookie.
ASSERT_EQ(GetModelCookieCount(blocked_model), 1u);
accepted_cookies = ExtractCookiesFromModel(allowed_model);
EXPECT_THAT(accepted_cookies, net::MatchesCookieLine("name=Good"));
}
// Verify that cookies can be blocked for a specific website using exceptions.
//
// TODO(crbug.com/41440775): Re-enable test once flakiness is fixed.
IN_PROC_BROWSER_TEST_P(CookieSettingsTest,
DISABLED_BlockCookiesUsingExceptions) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetCookieSetting(GetPageURL(), CONTENT_SETTING_BLOCK);
WriteCookie(browser());
ASSERT_TRUE(ReadCookie(browser()).empty());
auto* allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
auto* blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
net::CookieList blocked_cookies;
EXPECT_EQ(GetModelCookieCount(allowed_model), 0u);
EXPECT_EQ(GetModelCookieCount(blocked_model), 1u);
blocked_cookies = ExtractCookiesFromModel(blocked_model);
EXPECT_THAT(blocked_cookies, net::MatchesCookieLine("name=Good"));
GURL unblocked_url = GetOtherServer()->GetURL("/cookie1.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), unblocked_url));
ASSERT_FALSE(GetCookies(browser()->profile(), unblocked_url).empty());
net::CookieList accepted_cookies;
EXPECT_EQ(GetModelCookieCount(blocked_model), 0u);
EXPECT_EQ(GetModelCookieCount(allowed_model), 1u);
accepted_cookies = ExtractCookiesFromModel(allowed_model);
EXPECT_THAT(accepted_cookies, net::MatchesCookieLine("foo=baz"));
}
// Test that cookies that are considered "blocked" are excluded only due to the
// content settings blocking (i.e. not for other reasons like domain or path not
// matching). See https://crbug.com/1104451.
IN_PROC_BROWSER_TEST_P(CookieSettingsTest,
BlockedCookiesOnlyExcludedDueToBlocking) {
// This test only runs in HTTP mode, not with the full parameterized test
// suite.
if (ReadMode() != CookieMode::kHttp || WriteMode() != CookieMode::kHttp)
return;
// URLs to get cookies from:
GURL cookies_present_url(GetServer()->GetURL("a.test", "/simple.html"));
GURL cookies_blocked_url(
GetServer()->GetURL("sub.a.test", "/echoheader?Cookie"));
// URLs to set cookies on:
GURL set_host_cookie_url(
GetServer()->GetURL("a.test", "/set-cookie?host_cookie=1"));
GURL set_path_cookie_url(GetServer()->GetURL(
"sub.a.test",
"/set-cookie?path_cookie=1;domain=a.test;path=/simple.html"));
GURL set_included_cookie_url(GetServer()->GetURL(
"sub.a.test", "/set-cookie?included_cookie=1;domain=a.test"));
// No cookies are present prior to setting them.
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), cookies_present_url));
ASSERT_TRUE(HttpReadCookieWithURL(browser(), cookies_present_url).empty());
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), cookies_blocked_url));
ASSERT_TRUE(HttpReadCookieWithURL(browser(), cookies_blocked_url).empty());
// Set the cookies.
HttpWriteCookieWithURL(browser(), set_host_cookie_url);
HttpWriteCookieWithURL(browser(), set_path_cookie_url);
HttpWriteCookieWithURL(browser(), set_included_cookie_url);
// Verify all cookies are present on |cookies_present_url|.
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), cookies_present_url));
HttpReadCookieWithURL(browser(), cookies_present_url);
auto* allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
auto* blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
net::CookieList accepted_cookies;
EXPECT_EQ(GetModelCookieCount(allowed_model), 3u);
EXPECT_EQ(GetModelCookieCount(blocked_model), 0u);
accepted_cookies = ExtractCookiesFromModel(allowed_model);
EXPECT_THAT(accepted_cookies,
net::MatchesCookieLine(
"host_cookie=1; included_cookie=1; path_cookie=1"));
// Verify there is only one included cookie for |cookies_blocked_url|.
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), cookies_blocked_url));
HttpReadCookieWithURL(browser(), cookies_blocked_url);
allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
EXPECT_EQ(GetModelCookieCount(allowed_model), 1u);
EXPECT_EQ(GetModelCookieCount(blocked_model), 0u);
accepted_cookies = ExtractCookiesFromModel(allowed_model);
EXPECT_THAT(accepted_cookies, net::MatchesCookieLine("included_cookie=1"));
// Set content settings to block cookies for |cookies_blocked_url|.
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), cookies_blocked_url));
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetCookieSetting(cookies_blocked_url, CONTENT_SETTING_BLOCK);
// Verify all cookies are still present on |cookies_present_url|.
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), cookies_present_url));
HttpReadCookieWithURL(browser(), cookies_present_url);
allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
EXPECT_EQ(GetModelCookieCount(allowed_model), 3u);
EXPECT_EQ(GetModelCookieCount(blocked_model), 0u);
accepted_cookies = ExtractCookiesFromModel(allowed_model);
EXPECT_THAT(accepted_cookies,
net::MatchesCookieLine(
"host_cookie=1; included_cookie=1; path_cookie=1"));
// Verify there is only one blocked cookie on |cookies_blocked_url|.
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), cookies_blocked_url));
allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
net::CookieList blocked_cookies;
EXPECT_EQ(GetModelCookieCount(allowed_model), 0u);
EXPECT_EQ(GetModelCookieCount(blocked_model), 1u);
blocked_cookies = ExtractCookiesFromModel(blocked_model);
EXPECT_THAT(blocked_cookies, net::MatchesCookieLine("included_cookie=1"));
}
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, BlockCookiesAlsoBlocksCacheStorage) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetCookieSetting(GetPageURL(), CONTENT_SETTING_BLOCK);
const char kBaseExpected[] =
"%s - SecurityError: Failed to execute '%s' on 'CacheStorage': An "
"attempt was made to break through the security "
"policy of the user agent.";
const char kBaseScript[] =
"(async function() {"
" const name = `%s`;"
" try {"
" await %s;"
" } catch(e) {"
" return `${name} - ${e.toString()}`;"
" }"
" return `${name} - success`;"
"}())";
struct TestOp {
const char* cmd;
const char* name;
};
const TestOp kTestOps[] = {
{.cmd = "caches.open('foo')", .name = "open"},
{.cmd = "caches.has('foo')", .name = "has"},
{.cmd = "caches.keys()", .name = "keys"},
{.cmd = "caches.delete('foo')", .name = "delete"},
{.cmd = "caches.match('/')", .name = "match"},
};
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
for (auto& op : kTestOps) {
EXPECT_EQ(EvalJs(tab, base::StringPrintf(kBaseScript, op.cmd, op.cmd)),
base::StringPrintf(kBaseExpected, op.cmd, op.name));
}
}
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, BlockCookiesAlsoBlocksIndexedDB) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetCookieSetting(GetPageURL(), CONTENT_SETTING_BLOCK);
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
const char kBaseScript[] =
"(async function() {"
" const name = `%s`;"
" function wrap(req) {"
" return new Promise((resolve, reject) => {"
" req.onerror = function() { reject(req.error); };"
" req.onsuccess = function() { resolve(); };"
" });"
" }"
" try {"
" await wrap(indexedDB.%s%s);"
" } catch(e) {"
" return `${name} - ${e.toString()}`;"
" }"
" return `${name} - success`;"
"}())";
struct TestOp {
const char* cmd;
const char* args;
};
const TestOp kTestOps[] = {
{.cmd = "open", .args = "('foo', 1)"},
{.cmd = "deleteDatabase", .args = "('foo')"},
};
const char kBaseExpected[] =
"%s - UnknownError: The user denied permission to access the database.";
for (auto& op : kTestOps) {
EXPECT_EQ(
EvalJs(tab, base::StringPrintf(kBaseScript, op.cmd, op.cmd, op.args)),
base::StringPrintf(kBaseExpected, op.cmd));
}
}
IN_PROC_BROWSER_TEST_P(CookieSettingsTest,
BlockCookiesAlsoBlocksIndexedDBPromiseBased) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetCookieSetting(GetPageURL(), CONTENT_SETTING_BLOCK);
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
const char kPromiseBaseScript[] =
"(async function() {"
" const name = `%s`;"
" try {"
" await indexedDB.%s%s;"
" } catch(e) {"
" return `${name} - ${e.toString()}`;"
" }"
" return `${name} - success`;"
"}())";
struct TestOp {
const char* cmd;
const char* args;
};
const TestOp kPromiseTestOps[] = {
{.cmd = "databases", .args = "()"},
};
const char kBaseExpected[] =
"%s - UnknownError: The user denied permission to access the database.";
for (auto& op : kPromiseTestOps) {
EXPECT_EQ(EvalJs(tab, base::StringPrintf(kPromiseBaseScript, op.cmd, op.cmd,
op.args)),
base::StringPrintf(kBaseExpected, op.cmd));
}
}
IN_PROC_BROWSER_TEST_P(CookieSettingsTest, BlockCookiesAlsoBlocksFileSystem) {
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetPageURL()));
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetCookieSetting(GetPageURL(), CONTENT_SETTING_BLOCK);
const char kBaseExpected[] = "%s - %s";
const char kBaseScript[] = R"(
(async function() {
const name = `%s`;
try {
await %s;
} catch(e) {
return `${name} - ${e.toString()}`;
}
return `${name} - success`;
}())
)";
struct TestOp {
const char* name;
const char* code;
const char* error;
};
const TestOp kTestOps[] = {
{.name = "navigator.storage.getDirectory()",
.code = "navigator.storage.getDirectory()",
.error = "SecurityError: Storage directory access is denied."},
{.name = "window.webkitRequestFileSystem()",
.code = "new Promise((resolve, reject) => { "
" window.webkitRequestFileSystem(window.TEMPORARY,"
" 5*1024, () => resolve(),"
" (e) => reject(e));"
"});",
.error = "AbortError: An ongoing operation was aborted, typically with "
"a call to abort()."},
};
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
for (auto& op : kTestOps) {
EXPECT_EQ(EvalJs(tab, base::StringPrintf(kBaseScript, op.name, op.code)),
base::StringPrintf(kBaseExpected, op.name, op.error));
}
}
INSTANTIATE_TEST_SUITE_P(
All,
CookieSettingsTest,
::testing::Values(
std::make_pair(CookieMode::kDocumentCookieJS,
CookieMode::kDocumentCookieJS),
std::make_pair(CookieMode::kDocumentCookieJS, CookieMode::kHttp),
std::make_pair(CookieMode::kHttp, CookieMode::kDocumentCookieJS),
std::make_pair(CookieMode::kHttp, CookieMode::kHttp),
std::make_pair(CookieMode::kHttp, CookieMode::kCookieStoreJS),
std::make_pair(CookieMode::kCookieStoreJS,
CookieMode::kDocumentCookieJS)));
// This fails on ChromeOS because kRestoreOnStartup is ignored and the startup
// preference is always "continue where I left off.
#if !BUILDFLAG(IS_CHROMEOS)
// Verify that cookies can be allowed and set using exceptions for particular
// website(s) only for a session when all others are blocked.
IN_PROC_BROWSER_TEST_F(ContentSettingsTest,
PRE_AllowCookiesForASessionUsingExceptions) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/setcookie.html");
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
settings->SetCookieSetting(url, CONTENT_SETTING_SESSION_ONLY);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
ASSERT_FALSE(GetCookies(browser()->profile(), url).empty());
}
IN_PROC_BROWSER_TEST_F(ContentSettingsTest,
AllowCookiesForASessionUsingExceptions) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL url = embedded_test_server()->GetURL("/setcookie.html");
// Cookies are shared between ports, so this will get cookies set in PRE.
ASSERT_TRUE(GetCookies(browser()->profile(), url).empty());
}
#endif // !CHROME_OS
// Regression test for http://crbug.com/63649.
IN_PROC_BROWSER_TEST_F(ContentSettingsTest, RedirectLoopCookies) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url = embedded_test_server()->GetURL("/redirect-loop.html");
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
MockWebContentsLoadFailObserver observer(web_contents);
EXPECT_CALL(observer, DidFinishNavigation(IsErrorTooManyRedirects()));
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url));
ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(&observer));
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
}
// Any cookie access during a navigation does not end up in a new document (e.g.
// due to the request returning HTTP 204) should not be tracked by the
// PageSpecificContentSettings.
IN_PROC_BROWSER_TEST_F(ContentSettingsTest, CookiesIgnoredFor204) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url =
embedded_test_server()->GetURL("/server-redirect-with-cookie?/nocontent");
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url));
EXPECT_FALSE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
}
class ContentSettingsBackForwardCacheBrowserTest : public ContentSettingsTest {
public:
void SetUpOnMainThread() override {
host_resolver()->AddRule("*", "127.0.0.1");
ContentSettingsTest ::SetUpOnMainThread();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
scoped_feature_list_.InitWithFeaturesAndParameters(
content::GetDefaultEnabledBackForwardCacheFeaturesForTesting(),
content::GetDefaultDisabledBackForwardCacheFeaturesForTesting());
ContentSettingsTest::SetUpCommandLine(command_line);
}
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(ContentSettingsBackForwardCacheBrowserTest,
StateRestoredWhenNavigatingBack) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url = embedded_test_server()->GetURL("a.com", "/setcookie.html");
GURL other_url = embedded_test_server()->GetURL("b.com", "/title1.html");
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
content::CookieChangeObserver observer(
browser()->tab_strip_model()->GetActiveWebContents());
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url));
observer.Wait();
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame();
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), other_url));
EXPECT_EQ(main_frame->GetLifecycleState(),
content::RenderFrameHost::LifecycleState::kInBackForwardCache);
EXPECT_FALSE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
web_contents->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(web_contents));
EXPECT_EQ(web_contents->GetPrimaryMainFrame(), main_frame);
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
}
IN_PROC_BROWSER_TEST_F(ContentSettingsBackForwardCacheBrowserTest,
SettingsUpdateWhileInCacheShouldBeProcessed) {
ASSERT_TRUE(embedded_test_server()->Start());
GURL test_url = embedded_test_server()->GetURL("a.com", "/setcookie.html");
GURL other_url = embedded_test_server()->GetURL("b.com", "/title1.html");
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
content::CookieChangeObserver observer(
browser()->tab_strip_model()->GetActiveWebContents());
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url));
observer.Wait();
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), other_url));
EXPECT_FALSE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
// This triggers a OnContentSettingChanged notification that should be
// processed by the page in the cache.
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_ALLOW);
web_contents->GetController().GoBack();
EXPECT_TRUE(WaitForLoadStop(web_contents));
EXPECT_FALSE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
}
IN_PROC_BROWSER_TEST_F(ContentSettingsTest, ContentSettingsBlockDataURLs) {
GURL url("data:text/html,<title>Data URL</title><script>alert(1)</script>");
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
->SetDefaultContentSetting(ContentSettingsType::JAVASCRIPT,
CONTENT_SETTING_BLOCK);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_EQ(u"Data URL", web_contents->GetTitle());
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
}
// Tests that if redirect across origins occurs, the new process still gets the
// content settings before the resource headers.
IN_PROC_BROWSER_TEST_F(ContentSettingsTest, RedirectCrossOrigin) {
ASSERT_TRUE(embedded_test_server()->Start());
net::HostPortPair host_port = embedded_test_server()->host_port_pair();
DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));
std::string redirect(base::StringPrintf(
"http://localhost:%d/redirect-cross-origin.html", host_port.port()));
GURL test_url =
embedded_test_server()->GetURL("/server-redirect?" + redirect);
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::COOKIES));
}
IN_PROC_BROWSER_TEST_F(ContentSettingsTest, SendRendererContentRules) {
ASSERT_TRUE(embedded_test_server()->Start());
const GURL url_1 = embedded_test_server()->GetURL("a.com", "/title1.html");
const GURL url_2 =
embedded_test_server()->GetURL("b.com", "/javaScriptTitle.html");
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url_1));
HostContentSettingsMap* map = HostContentSettingsMapFactory::GetForProfile(
Profile::FromBrowserContext(web_contents->GetBrowserContext()));
EXPECT_NE(map, nullptr);
EXPECT_FALSE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
map->SetContentSettingDefaultScope(url_2, url_2,
ContentSettingsType::JAVASCRIPT,
ContentSetting::CONTENT_SETTING_BLOCK);
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url_2));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
}
IN_PROC_BROWSER_TEST_F(ContentSettingsTest,
SpareRenderProcessHostRulesAreUpdated) {
// Make sure a spare RenderProcessHost exists during the test.
content::RenderProcessHost::WarmupSpareRenderProcessHost(
browser()->profile());
ASSERT_TRUE(embedded_test_server()->Start());
// URL to a page that loads a cross-site iframe which creates another iframe
// via JavaScript. We will count iframes to test if JavaScript is blocked or
// not.
const GURL url = embedded_test_server()->GetURL(
"a.test", "/iframe_cross_site_with_script.html");
// Disable JavaScript. A warmed-up spare renderer should get ContentSettings
// updates and disable JavaScript.
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
->SetDefaultContentSetting(ContentSettingsType::JAVASCRIPT,
CONTENT_SETTING_BLOCK);
// Navigate to the page.
content::RenderFrameHost* main_frame =
ui_test_utils::NavigateToURL(browser(), url);
ASSERT_TRUE(main_frame);
// Ensure 2 frames exist after the load (main frame and 'b.test' frame).
EXPECT_EQ(GetRenderFrameHostCount(main_frame), 2u);
}
IN_PROC_BROWSER_TEST_F(ContentSettingsTest, NonMainFrameRulesAreUpdated) {
ASSERT_TRUE(embedded_test_server()->Start());
// URL to a page that loads a cross-site iframe which creates another iframe
// via JavaScript. We will count iframes to test if JavaScript is blocked or
// not.
const GURL url = embedded_test_server()->GetURL(
"a.test", "/iframe_cross_site_with_script.html");
// Disable JavaScript.
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
->SetDefaultContentSetting(ContentSettingsType::JAVASCRIPT,
CONTENT_SETTING_BLOCK);
// Navigate to the page.
content::RenderFrameHost* main_frame =
ui_test_utils::NavigateToURL(browser(), url);
ASSERT_TRUE(main_frame);
// Ensure 2 frames exist after the load (main frame and 'b.test' frame).
EXPECT_EQ(GetRenderFrameHostCount(main_frame), 2u);
// Enable JavaScript and load the same page.
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
->SetDefaultContentSetting(ContentSettingsType::JAVASCRIPT,
CONTENT_SETTING_DEFAULT);
main_frame = ui_test_utils::NavigateToURLWithDisposition(
browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
ASSERT_TRUE(main_frame);
// Ensure 3 frames exist after the load (main frame, 'b.test' frame and
// JavaScript-created 'b.test' nested frame).
EXPECT_EQ(GetRenderFrameHostCount(main_frame), 3u);
// Disable JavaScript and reload the iframe which contains JavaScript.
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
->SetDefaultContentSetting(ContentSettingsType::JAVASCRIPT,
CONTENT_SETTING_BLOCK);
content::RenderFrameHost* iframe_to_reload =
content::ChildFrameAt(main_frame, 0);
content::TestFrameNavigationObserver iframe_nav_observer(iframe_to_reload);
iframe_to_reload->Reload();
iframe_nav_observer.Wait();
// Ensure 2 frames exist after iframe reload (main frame and 'b.test' frame).
EXPECT_EQ(GetRenderFrameHostCount(main_frame), 2u);
}
// Simulates script being blocked in the renderer and notifying the browser
// before DidCommitNavigation is sent to the browser (i.e. while the RFH is
// still pending commit).
IN_PROC_BROWSER_TEST_F(ContentSettingsTest, RendererUpdateWhilePendingCommit) {
ASSERT_TRUE(embedded_test_server()->Start());
const GURL initial_url =
embedded_test_server()->GetURL("a.test", "/title1.html");
const GURL second_url =
embedded_test_server()->GetURL("b.test", "/title1.html");
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), initial_url));
content::CommitMessageDelayer delayer(
web_contents, second_url,
base::BindOnce([](content::RenderFrameHost* rfh) {
auto global_frame_token = rfh->GetGlobalFrameToken();
// Call ContentBlocked while the RFH is pending commit.
PageSpecificContentSettings::ContentBlocked(
global_frame_token, ContentSettingsType::JAVASCRIPT);
}));
ui_test_utils::NavigateToURLWithDisposition(
browser(), second_url, WindowOpenDisposition::CURRENT_TAB,
ui_test_utils::BROWSER_TEST_NO_WAIT);
delayer.Wait();
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
}
// This test verifies that the site settings accurately reflect that an attempt
// to create a secure cookie by an insecure origin fails.
IN_PROC_BROWSER_TEST_F(ContentSettingsTest, SecureCookies) {
ASSERT_TRUE(embedded_test_server()->Start());
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
https_server.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
ASSERT_TRUE(https_server.Start());
GURL http_url =
embedded_test_server()->GetURL("a.test", "/setsecurecookie.html");
GURL https_url = https_server.GetURL("a.test", "/setsecurecookie.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), http_url));
EXPECT_EQ(
GetModelCookieCount(GetSiteSettingsAllowedBrowsingDataModel(browser())),
0u);
content::CookieChangeObserver observer(
browser()->tab_strip_model()->GetActiveWebContents());
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), https_url));
observer.Wait();
EXPECT_EQ(
GetModelCookieCount(GetSiteSettingsAllowedBrowsingDataModel(browser())),
1u);
}
class ContentSettingsWorkerModulesBrowserTest : public ContentSettingsTest {
public:
ContentSettingsWorkerModulesBrowserTest() = default;
ContentSettingsWorkerModulesBrowserTest(
const ContentSettingsWorkerModulesBrowserTest&) = delete;
ContentSettingsWorkerModulesBrowserTest& operator=(
const ContentSettingsWorkerModulesBrowserTest&) = delete;
~ContentSettingsWorkerModulesBrowserTest() override = default;
protected:
void RegisterStaticFile(net::EmbeddedTestServer* server,
const std::string& relative_url,
const std::string& content,
const std::string& content_type) {
server->RegisterRequestHandler(base::BindRepeating(
&ContentSettingsWorkerModulesBrowserTest::StaticRequestHandler,
base::Unretained(this), relative_url, content, content_type));
}
private:
std::unique_ptr<net::test_server::HttpResponse> StaticRequestHandler(
const std::string& relative_url,
const std::string& content,
const std::string& content_type,
const net::test_server::HttpRequest& request) const {
if (request.relative_url != relative_url)
return nullptr;
std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
std::make_unique<net::test_server::BasicHttpResponse>());
http_response->set_code(net::HTTP_OK);
http_response->set_content(content);
http_response->set_content_type(content_type);
return std::move(http_response);
}
};
IN_PROC_BROWSER_TEST_F(ContentSettingsWorkerModulesBrowserTest,
WorkerImportModule) {
// This test uses 2 servers, |https_server_| and |embedded_test_server|.
// These 3 files are served from them:
// - "worker_import_module.html" from |embedded_test_server|.
// - "worker_import_module_worker.js" from |embedded_test_server|.
// - "worker_import_module_imported.js" from |https_server_|.
// 1. worker_import_module.html starts a dedicated worker which type is
// 'module' using worker_import_module_worker.js.
// new Worker('worker_import_module_worker.js', { type: 'module' })
// 2. worker_import_module_worker.js imports worker_import_module_imported.js.
// - If succeeded to import, calls postMessage() with the exported |msg|
// constant value which is 'Imported'.
// - If failed, calls postMessage('Failed').
// 3. When the page receives the message from the worker, change the title
// to the message string.
// worker.onmessage = (event) => { document.title = event.data; };
ASSERT_TRUE(https_server_.Start());
GURL module_url = https_server_.GetURL("/worker_import_module_imported.js");
const std::string script = base::StringPrintf(
"import('%s')\n"
" .then(module => postMessage(module.msg), _ => postMessage('Failed'));",
module_url.spec().c_str());
RegisterStaticFile(embedded_test_server(), "/worker_import_module_worker.js",
script, "text/javascript");
ASSERT_TRUE(embedded_test_server()->Start());
GURL http_url = embedded_test_server()->GetURL("/worker_import_module.html");
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
std::u16string expected_title(u"Imported");
content::TitleWatcher title_watcher(web_contents, expected_title);
title_watcher.AlsoWaitForTitle(u"Failed");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), http_url));
// The import must be executed successfully.
EXPECT_EQ(title_watcher.WaitAndGetTitle(), expected_title);
}
IN_PROC_BROWSER_TEST_F(ContentSettingsWorkerModulesBrowserTest, CookieStore) {
const char kWorkerScript[] = R"(
async function cookieHandler(e) {
try {
await cookieStore.set(
{ name: e.data,
value: 'value',
expires: Date.now() + 3600*1000,
sameSite: 'none' });
} finally {
e.source.postMessage('set executed for ' + e.data);
}
}
self.addEventListener('message', cookieHandler);)";
RegisterStaticFile(&https_server_, "/sw.js", kWorkerScript,
"text/javascript");
ASSERT_TRUE(https_server_.Start());
// Install service worker and wait for it to be activated.
GURL setup_url =
https_server_.GetURL("/service_worker/create_service_worker.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), setup_url));
content::EvalJsResult result =
content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
"register('/sw.js')");
ASSERT_EQ("DONE", result);
// Navigate again, this time it should be active. Also add some JS helpers to
// message the service worker asking it to set cookies.
GURL page_url = https_server_.GetURL("/empty.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), page_url));
const char kClientScript[] = R"(
function requestCookieSet(name) {
return new Promise(resolve => {
navigator.serviceWorker.onmessage = e => {
resolve(e.data);
};
window.sw.postMessage(name);
});
}
async function lookupSw() {
const reg = await navigator.serviceWorker.ready;
window.sw = reg.active;
return !!window.sw;
}
lookupSw();)";
content::EvalJsResult result2 = content::EvalJs(
browser()->tab_strip_model()->GetActiveWebContents(), kClientScript);
EXPECT_EQ(result2, true);
{
content::CookieChangeObserver observer(
browser()->tab_strip_model()->GetActiveWebContents());
// Set a cookie, see that it's reported.
content::EvalJsResult result3 =
content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
"requestCookieSet('first')");
EXPECT_EQ(result3, "set executed for first");
observer.Wait();
auto* allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
auto* blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
net::CookieList accepted_cookies;
EXPECT_EQ(GetModelCookieCount(allowed_model), 1u);
EXPECT_EQ(GetModelCookieCount(blocked_model), 0u);
accepted_cookies = ExtractCookiesFromModel(allowed_model);
EXPECT_THAT(accepted_cookies, net::MatchesCookieLine("first=value"));
}
{
content::CookieChangeObserver observer(
browser()->tab_strip_model()->GetActiveWebContents());
// Now set with cookies blocked.
content_settings::CookieSettings* settings =
CookieSettingsFactory::GetForProfile(browser()->profile()).get();
settings->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
content::EvalJsResult result4 =
content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(),
"requestCookieSet('second')");
EXPECT_EQ(result4, "set executed for second");
observer.Wait();
auto* allowed_model = GetSiteSettingsAllowedBrowsingDataModel(browser());
auto* blocked_model = GetSiteSettingsBlockedBrowsingDataModel(browser());
net::CookieList blocked_cookies;
EXPECT_EQ(GetModelCookieCount(allowed_model), 1u);
EXPECT_EQ(GetModelCookieCount(blocked_model), 1u);
blocked_cookies = ExtractCookiesFromModel(blocked_model);
EXPECT_THAT(blocked_cookies, net::MatchesCookieLine("second=value"));
}
}
class ContentSettingsWithPrerenderingBrowserTest : public ContentSettingsTest {
public:
ContentSettingsWithPrerenderingBrowserTest()
: prerender_test_helper_(base::BindRepeating(
&ContentSettingsWithPrerenderingBrowserTest::GetWebContents,
base::Unretained(this))) {}
void SetUp() override {
prerender_test_helper().RegisterServerRequestMonitor(
embedded_test_server());
ContentSettingsTest::SetUp();
}
void SetUpOnMainThread() override {
ContentSettingsTest::SetUpOnMainThread();
ASSERT_TRUE(embedded_test_server()->Start());
}
content::test::PrerenderTestHelper& prerender_test_helper() {
return prerender_test_helper_;
}
content::WebContents* GetWebContents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
private:
content::test::PrerenderTestHelper prerender_test_helper_;
};
// Used to wait for non-primary pages to set a cookie (eg: prerendering pages or
// fenced frames).
class NonPrimaryPageCookieAccessObserver : public content::WebContentsObserver {
public:
explicit NonPrimaryPageCookieAccessObserver(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {}
~NonPrimaryPageCookieAccessObserver() override = default;
void OnCookiesAccessed(content::NavigationHandle* navigation_handle,
const content::CookieAccessDetails& details) override {
bool is_in_primary_frame =
navigation_handle->GetParentFrame()
? navigation_handle->GetParentFrame()->GetPage().IsPrimary()
: navigation_handle->IsInPrimaryMainFrame();
if (is_in_primary_frame) {
cookie_accessed_in_primary_page_ = true;
} else {
run_loop_.Quit();
}
}
void OnCookiesAccessed(content::RenderFrameHost* rfh,
const content::CookieAccessDetails& details) override {
if (rfh->GetPage().IsPrimary()) {
cookie_accessed_in_primary_page_ = true;
} else {
run_loop_.Quit();
}
}
bool CookieAccessedByPrimaryPage() const {
return cookie_accessed_in_primary_page_;
}
// Waits for the prerendering page to set a cookie.
void Wait() { run_loop_.Run(); }
private:
bool cookie_accessed_in_primary_page_ = false;
base::RunLoop run_loop_;
};
IN_PROC_BROWSER_TEST_F(ContentSettingsWithPrerenderingBrowserTest,
PrerenderingPageSetsCookie) {
const GURL main_url = embedded_test_server()->GetURL("/empty.html");
const GURL prerender_url =
embedded_test_server()->GetURL("/set_cookie_header.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
ASSERT_EQ(GetWebContents()->GetLastCommittedURL(), main_url);
auto* main_pscs = PageSpecificContentSettings::GetForFrame(
GetWebContents()->GetPrimaryMainFrame());
ASSERT_FALSE(main_pscs->IsContentAllowed(ContentSettingsType::COOKIES));
{
NonPrimaryPageCookieAccessObserver cookie_observer(GetWebContents());
prerender_test_helper().AddPrerender(prerender_url);
int host_id = prerender_test_helper().GetHostForUrl(prerender_url);
content::RenderFrameHost* prerender_frame =
prerender_test_helper().GetPrerenderedMainFrameHost(host_id);
EXPECT_NE(prerender_frame, nullptr);
// Ensure notification for cookie access by prerendering page has been sent.
cookie_observer.Wait();
auto* prerender_pscs =
PageSpecificContentSettings::GetForFrame(prerender_frame);
EXPECT_TRUE(prerender_pscs->IsContentAllowed(ContentSettingsType::COOKIES));
EXPECT_EQ(
GetModelCookieCount(prerender_pscs->allowed_browsing_data_model()), 1u);
// Between when the cookie was set by the prerendering page and now, the
// main page might have accessed the cookie (for instance, when sending a
// request for a favicon) - check for the appropriate value based on
// observed behavior.
EXPECT_EQ(GetModelCookieCount(main_pscs->allowed_browsing_data_model()),
cookie_observer.CookieAccessedByPrimaryPage() ? 1u : 0u);
}
prerender_test_helper().NavigatePrimaryPage(prerender_url);
main_pscs = PageSpecificContentSettings::GetForFrame(
GetWebContents()->GetPrimaryMainFrame());
EXPECT_TRUE(main_pscs->IsContentAllowed(ContentSettingsType::COOKIES));
EXPECT_EQ(GetModelCookieCount(main_pscs->allowed_browsing_data_model()), 1u);
}
IN_PROC_BROWSER_TEST_F(ContentSettingsWithPrerenderingBrowserTest,
PrerenderingPageIframeSetsCookie) {
const GURL main_url = embedded_test_server()->GetURL("/empty.html");
const GURL prerender_url = embedded_test_server()->GetURL("/title1.html");
const GURL iframe_url =
embedded_test_server()->GetURL("/set_cookie_header.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
ASSERT_EQ(GetWebContents()->GetLastCommittedURL(), main_url);
auto* main_pscs = PageSpecificContentSettings::GetForFrame(
GetWebContents()->GetPrimaryMainFrame());
ASSERT_FALSE(main_pscs->IsContentAllowed(ContentSettingsType::COOKIES));
prerender_test_helper().AddPrerender(prerender_url);
int host_id = prerender_test_helper().GetHostForUrl(prerender_url);
content::RenderFrameHost* prerender_frame =
prerender_test_helper().GetPrerenderedMainFrameHost(host_id);
EXPECT_NE(prerender_frame, nullptr);
content::TestNavigationManager navigation_manager(GetWebContents(),
iframe_url);
NonPrimaryPageCookieAccessObserver cookie_observer(GetWebContents());
EXPECT_TRUE(content::ExecJs(
prerender_frame,
content::JsReplace("const iframe = document.createElement('iframe');"
"iframe.src = $1;"
"document.body.appendChild(iframe);",
iframe_url)));
EXPECT_TRUE(navigation_manager.WaitForRequestStart());
navigation_manager.ResumeNavigation();
cookie_observer.Wait();
ASSERT_TRUE(navigation_manager.WaitForNavigationFinished());
auto* prerender_pscs =
PageSpecificContentSettings::GetForFrame(prerender_frame);
EXPECT_TRUE(prerender_pscs->IsContentAllowed(ContentSettingsType::COOKIES));
EXPECT_EQ(GetModelCookieCount(prerender_pscs->allowed_browsing_data_model()),
1u);
// Between when the cookie was set by the prerendering page and now, the
// main page might have accessed the cookie (for instance, when sending a
// request for a favicon) - check for the appropriate value based on
// observed behavior.
EXPECT_EQ(GetModelCookieCount(main_pscs->allowed_browsing_data_model()),
cookie_observer.CookieAccessedByPrimaryPage() ? 1u : 0u);
}
class ContentSettingsWithFencedFrameBrowserTest : public ContentSettingsTest {
public:
ContentSettingsWithFencedFrameBrowserTest() = default;
~ContentSettingsWithFencedFrameBrowserTest() override = default;
void SetUpOnMainThread() override {
ContentSettingsTest::SetUpOnMainThread();
base::FilePath path;
base::PathService::Get(content::DIR_TEST_DATA, &path);
https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
https_server_.ServeFilesFromDirectory(path);
ASSERT_TRUE(https_server_.Start());
}
content::test::FencedFrameTestHelper& fenced_frame_test_helper() {
return fenced_frame_test_helper_;
}
content::WebContents* GetWebContents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
private:
content::test::FencedFrameTestHelper fenced_frame_test_helper_;
};
IN_PROC_BROWSER_TEST_F(ContentSettingsWithFencedFrameBrowserTest,
StorageAccessInFencedFrame) {
const GURL main_url = https_server_.GetURL("a.test", "/empty.html");
const GURL fenced_frame_url =
https_server_.GetURL("b.test", "/browsing_data/site_data.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
ASSERT_FALSE(GetWebContents()->GetPrimaryMainFrame()->IsErrorDocument());
ASSERT_EQ(GetWebContents()->GetLastCommittedURL(), main_url);
auto* main_pscs = PageSpecificContentSettings::GetForFrame(
GetWebContents()->GetPrimaryMainFrame());
content::RenderFrameHost* fenced_frame =
fenced_frame_test_helper().CreateFencedFrame(
GetWebContents()->GetPrimaryMainFrame(), fenced_frame_url);
ASSERT_NE(fenced_frame, nullptr);
auto* ff_pscs = PageSpecificContentSettings::GetForFrame(fenced_frame);
std::vector<std::string> storage_types_to_test{
"LocalStorage", "SessionStorage", "CacheStorage", "FileSystem",
"FileSystemAccess", "IndexedDb", "SharedWorker", "ServiceWorker"};
for (auto storage_type : storage_types_to_test) {
EXPECT_TRUE(content::EvalJs(fenced_frame, "set" + storage_type + "();")
.ExtractBool());
}
std::vector<PageSpecificContentSettings*> pscs_list;
pscs_list.push_back(main_pscs);
pscs_list.push_back(ff_pscs);
for (auto* pscs : pscs_list) {
EXPECT_TRUE(pscs->IsContentAllowed(ContentSettingsType::COOKIES));
EXPECT_EQ(pscs->allowed_browsing_data_model()->size(), 1u);
}
}
IN_PROC_BROWSER_TEST_F(ContentSettingsWithFencedFrameBrowserTest,
RendererContentSettings) {
const GURL main_url = https_server_.GetURL("a.test", "/empty.html");
const GURL fenced_frame_url =
https_server_.GetURL("b.test", "/fenced_frames/page_with_script.html");
const GURL other_main_url = https_server_.GetURL("c.test", "/empty.html");
auto NavigatePrimaryPageAndAddFencedFrame =
[&]() -> content::RenderFrameHost* {
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
EXPECT_FALSE(GetWebContents()->GetPrimaryMainFrame()->IsErrorDocument());
EXPECT_EQ(GetWebContents()->GetLastCommittedURL(), main_url);
content::RenderFrameHost* fenced_frame =
fenced_frame_test_helper().CreateFencedFrame(
GetWebContents()->GetPrimaryMainFrame(), fenced_frame_url);
EXPECT_NE(fenced_frame, nullptr);
return fenced_frame;
};
auto ExpectScriptBlocked = [&](content::RenderFrameHost* fenced_frame) {
ui_test_utils::WaitForViewVisibility(
browser(), VIEW_ID_CONTENT_SETTING_JAVASCRIPT, true);
auto* main_pscs = PageSpecificContentSettings::GetForFrame(
GetWebContents()->GetPrimaryMainFrame());
auto* ff_pscs = PageSpecificContentSettings::GetForFrame(fenced_frame);
// Script should have been blocked in the fenced frame (and reflected in
// the PSCS of the primary page as well).
EXPECT_TRUE(ff_pscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
EXPECT_TRUE(main_pscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
};
auto ExpectScriptAllowed = [&](content::RenderFrameHost* fenced_frame) {
EXPECT_EQ(EvalJs(fenced_frame, "(async () => { return 1; })();"), 1);
auto* ff_pscs = PageSpecificContentSettings::GetForFrame(fenced_frame);
EXPECT_FALSE(ff_pscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
};
// Block script in (a.test, b.test).
auto* map =
HostContentSettingsMapFactory::GetForProfile(browser()->profile());
map->SetContentSettingCustomScope(
ContentSettingsPattern::FromURL(main_url),
ContentSettingsPattern::FromURL(fenced_frame_url),
ContentSettingsType::JAVASCRIPT, ContentSetting::CONTENT_SETTING_BLOCK);
content::RenderFrameHost* fenced_frame =
NavigatePrimaryPageAndAddFencedFrame();
ExpectScriptBlocked(fenced_frame);
// Allow script in (a.test, b.test).
map->SetContentSettingCustomScope(
ContentSettingsPattern::FromURL(main_url),
ContentSettingsPattern::FromURL(fenced_frame_url),
ContentSettingsType::JAVASCRIPT, ContentSetting::CONTENT_SETTING_ALLOW);
fenced_frame = NavigatePrimaryPageAndAddFencedFrame();
ExpectScriptAllowed(fenced_frame);
// Block script in (c.test, b.test).
map->SetContentSettingCustomScope(
ContentSettingsPattern::FromURL(other_main_url),
ContentSettingsPattern::FromURL(fenced_frame_url),
ContentSettingsType::JAVASCRIPT, ContentSetting::CONTENT_SETTING_BLOCK);
fenced_frame = NavigatePrimaryPageAndAddFencedFrame();
ExpectScriptAllowed(fenced_frame);
// Block script in (*, b.test) - this should not have any effect as the
// (a.test, b.test) rule is a narrower rule and should have precedence.
map->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(),
ContentSettingsPattern::FromURL(fenced_frame_url),
ContentSettingsType::JAVASCRIPT, ContentSetting::CONTENT_SETTING_BLOCK);
fenced_frame = NavigatePrimaryPageAndAddFencedFrame();
ExpectScriptAllowed(fenced_frame);
// Remove (a.test, b.test) rule - (*, b.test) rule should now be the narrowest
// and will be applied.
map->SetContentSettingCustomScope(
ContentSettingsPattern::FromURL(main_url),
ContentSettingsPattern::FromURL(fenced_frame_url),
ContentSettingsType::JAVASCRIPT, ContentSetting::CONTENT_SETTING_DEFAULT);
fenced_frame = NavigatePrimaryPageAndAddFencedFrame();
ExpectScriptBlocked(fenced_frame);
}
IN_PROC_BROWSER_TEST_F(ContentSettingsWithFencedFrameBrowserTest,
NestedFramesRendererContentSettings) {
// a.com embeds b.com, b.com embeds c.com.
const GURL main_url = https_server_.GetURL("a.test", "/empty.html");
const GURL nested_url = https_server_.GetURL("b.test", "/empty.html");
const GURL fenced_frame_url =
https_server_.GetURL("c.test", "/fenced_frames/page_with_script.html");
content::RenderFrameHost* crossorigin_subframe;
auto NavigatePrimaryPageAndAddNestedFrames =
[&]() -> content::RenderFrameHost* {
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
EXPECT_FALSE(GetWebContents()->GetPrimaryMainFrame()->IsErrorDocument());
EXPECT_EQ(GetWebContents()->GetLastCommittedURL(), main_url);
crossorigin_subframe =
CreateIframe(GetWebContents()->GetPrimaryMainFrame(), nested_url);
EXPECT_NE(crossorigin_subframe, nullptr);
content::RenderFrameHost* fenced_frame =
fenced_frame_test_helper().CreateFencedFrame(crossorigin_subframe,
fenced_frame_url);
EXPECT_NE(fenced_frame, nullptr);
return fenced_frame;
};
auto ExpectScriptAllowed = [&](content::RenderFrameHost* fenced_frame) {
EXPECT_EQ(EvalJs(fenced_frame, "(async () => { return 1; })();"), 1);
auto* ff_pscs = PageSpecificContentSettings::GetForFrame(fenced_frame);
EXPECT_FALSE(ff_pscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
};
auto ExpectScriptBlocked = [&](content::RenderFrameHost* fenced_frame) {
ui_test_utils::WaitForViewVisibility(
browser(), VIEW_ID_CONTENT_SETTING_JAVASCRIPT, true);
auto* main_pscs = PageSpecificContentSettings::GetForFrame(
GetWebContents()->GetPrimaryMainFrame());
auto* ff_pscs = PageSpecificContentSettings::GetForFrame(fenced_frame);
// Script should have been blocked in the fenced frame (and reflected
// in the PSCS of the primary page as well).
EXPECT_TRUE(ff_pscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
EXPECT_TRUE(main_pscs->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
};
content::RenderFrameHost* fenced_frame =
NavigatePrimaryPageAndAddNestedFrames();
ASSERT_TRUE(fenced_frame);
// Script is allowed by default in iframes.
ExpectScriptAllowed(fenced_frame);
// Block script in (a.test, c.test).
auto* map =
HostContentSettingsMapFactory::GetForProfile(browser()->profile());
map->SetContentSettingCustomScope(
ContentSettingsPattern::FromURL(main_url),
ContentSettingsPattern::FromURL(fenced_frame_url),
ContentSettingsType::JAVASCRIPT, ContentSetting::CONTENT_SETTING_BLOCK);
fenced_frame = NavigatePrimaryPageAndAddNestedFrames();
ASSERT_TRUE(fenced_frame);
// Script should blocked (a.com, b.com).
ExpectScriptBlocked(fenced_frame);
}
IN_PROC_BROWSER_TEST_F(ContentSettingsWithFencedFrameBrowserTest,
FencedFrameSetsCookie) {
const GURL main_url = https_server_.GetURL("a.test", "/empty.html");
const GURL fenced_frame_url =
https_server_.GetURL("b.test", "/fenced_frames/set_cookie_header.html");
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
ASSERT_EQ(GetWebContents()->GetLastCommittedURL(), main_url);
auto* main_pscs = PageSpecificContentSettings::GetForFrame(
GetWebContents()->GetPrimaryMainFrame());
ASSERT_FALSE(main_pscs->IsContentAllowed(ContentSettingsType::COOKIES));
std::unique_ptr<content::RenderFrameHostWrapper> fenced_frame;
{
NonPrimaryPageCookieAccessObserver cookie_observer(GetWebContents());
fenced_frame = std::make_unique<content::RenderFrameHostWrapper>(
fenced_frame_test_helper().CreateFencedFrame(
GetWebContents()->GetPrimaryMainFrame(), fenced_frame_url));
EXPECT_NE(fenced_frame, nullptr);
// Ensure notification for cookie access by fenced frame has been sent.
cookie_observer.Wait();
}
auto* ff_pscs = PageSpecificContentSettings::GetForFrame(fenced_frame->get());
EXPECT_TRUE(ff_pscs->IsContentAllowed(ContentSettingsType::COOKIES));
EXPECT_TRUE(main_pscs->IsContentAllowed(ContentSettingsType::COOKIES));
EXPECT_EQ(GetModelCookieCount(main_pscs->allowed_browsing_data_model()), 1u);
EXPECT_EQ(GetModelCookieCount(ff_pscs->allowed_browsing_data_model()), 1u);
CookieSettingsFactory::GetForProfile(browser()->profile())
->SetCookieSetting((*fenced_frame)->GetLastCommittedURL(),
CONTENT_SETTING_BLOCK);
{
NonPrimaryPageCookieAccessObserver cookie_observer(GetWebContents());
ASSERT_TRUE(content::ExecJs(fenced_frame->get(), "document.cookie"));
cookie_observer.Wait();
}
EXPECT_TRUE(ff_pscs->IsContentBlocked(ContentSettingsType::COOKIES));
EXPECT_TRUE(main_pscs->IsContentBlocked(ContentSettingsType::COOKIES));
EXPECT_EQ(GetModelCookieCount(main_pscs->blocked_browsing_data_model()), 1u);
EXPECT_EQ(GetModelCookieCount(ff_pscs->blocked_browsing_data_model()), 1u);
ASSERT_TRUE(
content::ExecJs(GetWebContents()->GetPrimaryMainFrame(),
"const ff = document.querySelector('fencedframe'); "
"ff.remove();"));
ASSERT_TRUE(fenced_frame->WaitUntilRenderFrameDeleted());
EXPECT_TRUE(main_pscs->IsContentBlocked(ContentSettingsType::COOKIES));
EXPECT_EQ(GetModelCookieCount(main_pscs->allowed_browsing_data_model()), 1u);
EXPECT_EQ(GetModelCookieCount(main_pscs->blocked_browsing_data_model()), 1u);
}
class ContentSettingsWorkerModulesWithFencedFrameBrowserTest
: public ContentSettingsWorkerModulesBrowserTest {
public:
ContentSettingsWorkerModulesWithFencedFrameBrowserTest() = default;
~ContentSettingsWorkerModulesWithFencedFrameBrowserTest() override = default;
content::test::FencedFrameTestHelper& fenced_frame_test_helper() {
return fenced_frame_test_helper_;
}
private:
content::test::FencedFrameTestHelper fenced_frame_test_helper_;
};
IN_PROC_BROWSER_TEST_F(ContentSettingsWorkerModulesWithFencedFrameBrowserTest,
WorkerImportModuleBlocked) {
const std::string script = base::StringPrintf(
"import('%s')\n"
" .then(module => postMessage(module.msg), _ => postMessage('Failed'));",
"/worker_import_module_imported.js");
RegisterStaticFile(&https_server_, "/worker_import_module_worker.js", script,
"text/javascript");
https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
ASSERT_TRUE(https_server_.Start());
GURL main_url = https_server_.GetURL("a.test", "/title1.html");
GURL module_url =
https_server_.GetURL("b.test", "/worker_import_module_imported.js");
GURL fenced_frame_url =
https_server_.GetURL("b.test", "/worker_import_module.html");
// Change the settings to block the script loading of
// worker_import_module_imported.js from worker_import_module.html.
auto* content_settings_map =
HostContentSettingsMapFactory::GetForProfile(browser()->profile());
content_settings_map->SetWebsiteSettingCustomScope(
ContentSettingsPattern::FromURLNoWildcard(main_url),
ContentSettingsPattern::FromURLNoWildcard(module_url),
ContentSettingsType::JAVASCRIPT, base::Value(CONTENT_SETTING_BLOCK));
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
ASSERT_FALSE(web_contents->GetPrimaryMainFrame()->IsErrorDocument());
content::RenderFrameHost* fenced_frame =
fenced_frame_test_helper().CreateFencedFrame(
web_contents->GetPrimaryMainFrame(), fenced_frame_url);
ASSERT_NE(nullptr, fenced_frame);
// The import must be blocked.
ui_test_utils::WaitForViewVisibility(
browser(), VIEW_ID_CONTENT_SETTING_JAVASCRIPT, true);
EXPECT_TRUE(PageSpecificContentSettings::GetForFrame(
web_contents->GetPrimaryMainFrame())
->IsContentBlocked(ContentSettingsType::JAVASCRIPT));
}
#if BUILDFLAG(ENABLE_PDF)
class ContentSettingsPdfTest : public PDFExtensionTestBase {
public:
bool UseOopif() const override { return true; }
testing::AssertionResult IsJavaScriptEnabled(content::RenderFrameHost* host) {
return content::ExecJs(host, "");
}
};
// Test that only PDF frames are allowed to use JavaScript.
IN_PROC_BROWSER_TEST_F(ContentSettingsPdfTest, JavaScriptAllowedForPdfFrames) {
HostContentSettingsMapFactory::GetForProfile(browser()->profile())
->SetDefaultContentSetting(ContentSettingsType::JAVASCRIPT,
CONTENT_SETTING_BLOCK);
content::RenderFrameHost* extension_host =
LoadPdfGetExtensionHost(embedded_test_server()->GetURL("/pdf/test.pdf"));
ASSERT_TRUE(extension_host);
// Arbitrary frames shouldn't be able to execute JavaScript.
EXPECT_FALSE(
IsJavaScriptEnabled(GetActiveWebContents()->GetPrimaryMainFrame()));
// The PDF extension frame should be able to execute JavaScript.
EXPECT_TRUE(IsJavaScriptEnabled(extension_host));
content::RenderFrameHost* content_host =
pdf_frame_util::FindPdfChildFrame(extension_host);
ASSERT_TRUE(content_host);
// The PDF content frame should be able to execute JavaScript.
EXPECT_TRUE(IsJavaScriptEnabled(content_host));
}
#endif // BUILDFLAG(ENABLE_PDF)