Commit ff81f7f4 authored by Giovanni Ortuño Urquidi's avatar Giovanni Ortuño Urquidi Committed by Commit Bot

webui: Extract TestWebUIControllerFactory into shared file

TestWebUIController is used by tests to create WebUIControllers with
specific CSPs and headers. Extract it into web_ui_browsertest_util.h
so that it can be shared by all WebUI tests.

Also rewrites tests to use the common TestWebUIController.

Bug: 1012150
Change-Id: I009c26534a7da37698c9a17ae22f2756ba3a4717
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1921017
Commit-Queue: Giovanni Ortuño Urquidi <ortuno@chromium.org>
Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#716961}
parent 9dfff6a5
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/webui/web_ui_browsertest_util.h"
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/hash/hash.h"
#include "base/memory/ref_counted_memory.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/url_constants.h"
#include "net/base/url_util.h"
#include "url/gurl.h"
namespace content {
namespace {
void GetResource(const std::string& id,
const WebUIDataSource::GotDataCallback& callback) {
base::ScopedAllowBlockingForTesting allow_blocking;
if (id == "error") {
callback.Run(nullptr);
return;
}
std::string contents;
base::FilePath path;
CHECK(base::PathService::Get(content::DIR_TEST_DATA, &path));
path = path.AppendASCII(id.substr(0, id.find("?")));
CHECK(base::ReadFileToString(path, &contents)) << path.value();
base::RefCountedString* ref_contents = new base::RefCountedString;
ref_contents->data() = contents;
callback.Run(ref_contents);
}
struct WebUIControllerConfig {
int bindings = BINDINGS_POLICY_WEB_UI;
std::string child_src = "child-src 'self' chrome://web-ui-subframe/;";
bool disable_xfo = false;
};
class TestWebUIController : public WebUIController {
public:
TestWebUIController(WebUI* web_ui,
const GURL& base_url,
const WebUIControllerConfig& config)
: WebUIController(web_ui) {
web_ui->SetBindings(config.bindings);
WebUIDataSource* data_source = WebUIDataSource::Create(base_url.host());
data_source->SetRequestFilter(
base::BindRepeating([](const std::string& path) { return true; }),
base::BindRepeating(&GetResource));
data_source->OverrideContentSecurityPolicyChildSrc(config.child_src);
if (config.disable_xfo)
data_source->DisableDenyXFrameOptions();
WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
data_source);
}
TestWebUIController(const TestWebUIController&) = delete;
void operator=(const TestWebUIController&) = delete;
};
} // namespace
TestWebUIControllerFactory::TestWebUIControllerFactory() = default;
std::unique_ptr<WebUIController>
TestWebUIControllerFactory::CreateWebUIControllerForURL(WebUI* web_ui,
const GURL& url) {
if (!url.SchemeIs(kChromeUIScheme))
return nullptr;
WebUIControllerConfig config;
config.disable_xfo = disable_xfo_;
if (url.has_query()) {
std::string value;
bool has_value = net::GetValueForKeyInQuery(url, "bindings", &value);
if (has_value)
CHECK(base::StringToInt(value, &(config.bindings)));
has_value = net::GetValueForKeyInQuery(url, "noxfo", &value);
if (has_value && value == "true")
config.disable_xfo = true;
has_value = net::GetValueForKeyInQuery(url, "childsrc", &value);
if (has_value)
config.child_src = value;
}
return std::make_unique<TestWebUIController>(web_ui, url, config);
}
WebUI::TypeID TestWebUIControllerFactory::GetWebUIType(
BrowserContext* browser_context,
const GURL& url) {
if (!url.SchemeIs(kChromeUIScheme))
return WebUI::kNoWebUI;
return reinterpret_cast<WebUI::TypeID>(base::FastHash(url.host()));
}
bool TestWebUIControllerFactory::UseWebUIForURL(BrowserContext* browser_context,
const GURL& url) {
return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
}
bool TestWebUIControllerFactory::UseWebUIBindingsForURL(
BrowserContext* browser_context,
const GURL& url) {
return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
}
} // namespace content
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_UTIL_H_
#define CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_UTIL_H_
#include <memory>
#include "content/browser/webui/content_web_ui_controller_factory.h"
namespace content {
// Returns WebUIControllers whose CSPs and headers can be controlled through
// query parameters.
// - "bindings" controls the bindings e.g. Mojo, chrome.send() or both, with
// which the WebUIController will be created.
// - "noxfo" controls whether the "X-Frame-Options: DENY" header, which is
// added by default, will be removed. Set to true to remove the header.
// - "childsrc" controls the child-src CSP. It's value is
// "child-src 'self' chrome://web-ui-subframe/;" by default.
class TestWebUIControllerFactory : public WebUIControllerFactory {
public:
TestWebUIControllerFactory();
TestWebUIControllerFactory(const TestWebUIControllerFactory&) = delete;
void operator=(const TestWebUIControllerFactory&) = delete;
// Set to true to remove the "X-Frame-Options: DENY" header from all new
// WebUIControllers.
void set_disable_xfo(bool disable) { disable_xfo_ = disable; }
// WebUIControllerFactory
std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
WebUI* web_ui,
const GURL& url) override;
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
const GURL& url) override;
bool UseWebUIForURL(BrowserContext* browser_context,
const GURL& url) override;
bool UseWebUIBindingsForURL(BrowserContext* browser_context,
const GURL& url) override;
private:
bool disable_xfo_ = false;
};
} // namespace content
#endif // CONTENT_BROWSER_WEBUI_WEB_UI_BROWSERTEST_UTIL_H_
......@@ -7,6 +7,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/webui/web_ui_browsertest_util.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_switches.h"
......@@ -14,8 +15,10 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_frame_navigation_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "url/url_constants.h"
......@@ -24,7 +27,12 @@ namespace content {
class WebUINavigationBrowserTest : public ContentBrowserTest {
public:
WebUINavigationBrowserTest() {}
WebUINavigationBrowserTest() {
WebUIControllerFactory::RegisterFactory(&factory_);
}
~WebUINavigationBrowserTest() override {
WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
}
protected:
void SetUpOnMainThread() override {
......@@ -73,67 +81,69 @@ class WebUINavigationBrowserTest : public ContentBrowserTest {
// Verify that a WebUI document in a subframe is allowed to target a new
// window and navigate it to web content.
void TestWebUISubframeNewWindowToWebAllowed(int bindings) {
GURL main_frame_url(
GetWebUIURL("web-ui/page_with_blank_iframe.html?bindings=" +
base::NumberToString(bindings)));
EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
EXPECT_EQ(1U, root->child_count());
FrameTreeNode* child = root->child_at(0);
// TODO(nasko): Replace this URL with one with a custom WebUI object that
// doesn't have restrictive CSP, so the test can successfully add an
// iframe which gets WebUI bindings in the renderer process.
GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIBlobInternalsHost));
EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
EXPECT_EQ(bindings, root->current_frame_host()->GetEnabledBindings());
EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
child->current_frame_host()->GetSiteInstance());
RenderFrameHost* webui_rfh = root->current_frame_host();
scoped_refptr<SiteInstance> webui_site_instance =
webui_rfh->GetSiteInstance();
ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
webui_rfh->GetProcess()->GetID(), bindings);
EXPECT_EQ(chrome_url, webui_rfh->GetLastCommittedURL());
EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
webui_rfh->GetProcess()->GetID()));
// Create a subframe with a WebUI document in it.
// Navigate the subframe to the same WebUI.
{
std::string script = base::StringPrintf(
"var frame = document.createElement('iframe');\n"
"frame.src = '%s';\n"
"document.body.appendChild(frame);\n",
chrome_url.spec().c_str());
TestFrameNavigationObserver observer(root->child_at(0));
GURL subframe_url(GetWebUIURL("web-ui/title1.html?noxfo=true&bindings=" +
base::NumberToString(bindings)));
NavigateFrameToURL(root->child_at(0), subframe_url);
TestNavigationObserver navigation_observer(shell()->web_contents());
EXPECT_TRUE(ExecuteScript(shell(), script));
navigation_observer.Wait();
EXPECT_EQ(1U, root->child_count());
EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(subframe_url, observer.last_committed_url());
}
// Add a link that targets a new window and click it.
GURL web_url(embedded_test_server()->GetURL("/title2.html"));
std::string script = base::StringPrintf(
std::string script = JsReplace(
"var a = document.createElement('a');"
"a.href = '%s'; a.target = '_blank'; a.click()",
"a.href = $1; a.target = '_blank'; a.click()",
web_url.spec().c_str());
ShellAddedObserver new_shell_observer;
EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
EXPECT_TRUE(ExecJs(root->child_at(0)->current_frame_host(), script,
EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
Shell* new_shell = new_shell_observer.GetShell();
WaitForLoadStop(new_shell->web_contents());
EXPECT_EQ(web_url, new_shell->web_contents()->GetLastCommittedURL());
// TODO(nasko): Verify the SiteInstance is different once
// https://crbug.com/776900 is fixed.
// Without a WebUI object which requires WebUI bindings, the RenderFrame is
// not notified that it has WebUI bindings. This in turn causes link clicks
// to use the BeginNavigation path, where otherwise the WebUI bindings will
// cause the OpenURL path to be taken. When using BeginNavigation, the
// navigation is committed same process, since it is renderer initiated.
WebContents* new_web_contents = new_shell->web_contents();
WaitForLoadStop(new_web_contents);
EXPECT_EQ(web_url, new_web_contents->GetLastCommittedURL());
FrameTreeNode* new_root =
static_cast<WebContentsImpl*>(new_web_contents)->GetFrameTree()->root();
EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
new_root->current_frame_host()->GetSiteInstance());
EXPECT_NE(root->current_frame_host()->GetProcess(),
new_root->current_frame_host()->GetProcess());
EXPECT_NE(root->current_frame_host()->web_ui(),
new_root->current_frame_host()->web_ui());
EXPECT_NE(root->current_frame_host()->GetEnabledBindings(),
new_root->current_frame_host()->GetEnabledBindings());
EXPECT_FALSE(
root->current_frame_host()->GetSiteInstance()->IsRelatedSiteInstance(
new_root->current_frame_host()->GetSiteInstance()));
}
private:
TestWebUIControllerFactory factory_;
DISALLOW_COPY_AND_ASSIGN(WebUINavigationBrowserTest);
};
......@@ -141,51 +151,39 @@ class WebUINavigationBrowserTest : public ContentBrowserTest {
// See https://crbug.com/683418.
IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
WebFrameInChromeSchemeDisallowed) {
// Serve a WebUI with no iframe restrictions.
GURL main_frame_url(GetWebUIURL("web-ui/title1.html?noxfo=true&childsrc="));
EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
EXPECT_EQ(BINDINGS_POLICY_WEB_UI,
root->current_frame_host()->GetEnabledBindings());
// TODO(nasko): Replace this URL with one with a custom WebUI object that
// doesn't have restrictive CSP, so the test can successfully add an
// iframe and test the actual throttle blocking. The default CSP policy
// on WebUI objects will just block the navigation prior to the throttle
// being even invoked. For now use the blob-internals URL, which is not
// backed by WebUI and does not have CSP policy attached to it.
// See http://crbug.com/776900.
GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIBlobInternalsHost));
EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
EXPECT_EQ(chrome_url, root->current_frame_host()->GetLastCommittedURL());
std::string add_iframe_script =
"var frame = document.createElement('iframe');\n"
"frame.src = $1;\n"
"document.body.appendChild(frame);\n";
// Navigate to a Web URL and verify that the navigation was blocked.
{
TestNavigationObserver observer(shell()->web_contents());
GURL web_url(embedded_test_server()->GetURL("/title2.html"));
std::string script = base::StringPrintf(
"var frame = document.createElement('iframe');\n"
"frame.src = '%s';\n"
"document.body.appendChild(frame);\n",
web_url.spec().c_str());
TestNavigationObserver navigation_observer(shell()->web_contents());
EXPECT_TRUE(ExecuteScript(shell(), script));
navigation_observer.Wait();
EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
EXPECT_TRUE(ExecJs(shell(), JsReplace(add_iframe_script, web_url),
EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
observer.Wait();
EXPECT_FALSE(observer.last_navigation_succeeded());
}
// Verify data: URLs are also not allowed.
// Navigate to a data URL and verify that the navigation was blocked.
{
TestNavigationObserver observer(shell()->web_contents());
GURL data_url("data:text/html,foo");
std::string script = base::StringPrintf(
"var frame = document.createElement('iframe');\n"
"frame.src = '%s';\n"
"document.body.appendChild(frame);\n",
data_url.spec().c_str());
TestNavigationObserver navigation_observer(shell()->web_contents());
EXPECT_TRUE(ExecuteScript(shell(), script));
navigation_observer.Wait();
EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
EXPECT_TRUE(ExecJs(shell(), JsReplace(add_iframe_script, data_url),
EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
observer.Wait();
EXPECT_FALSE(observer.last_navigation_succeeded());
}
// Verify that an iframe with "about:blank" URL is actually allowed. Not
......@@ -193,18 +191,12 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
// only host content coming from the parent document, so it effectively
// has the same security context.
{
TestNavigationObserver observer(shell()->web_contents());
GURL about_blank_url("about:blank");
std::string script = base::StringPrintf(
"var frame = document.createElement('iframe');\n"
"frame.src = '%s';\n"
"document.body.appendChild(frame);\n",
about_blank_url.spec().c_str());
TestNavigationObserver navigation_observer(shell()->web_contents());
EXPECT_TRUE(ExecuteScript(shell(), script));
navigation_observer.Wait();
EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
EXPECT_TRUE(ExecJs(shell(), JsReplace(add_iframe_script, about_blank_url),
EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
observer.Wait();
EXPECT_TRUE(observer.last_navigation_succeeded());
}
}
......@@ -213,23 +205,24 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
// See https://crbug.com/944086.
IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
WebFrameInChromeSchemeDisallowedByCSP) {
// Use the chrome://gpu WebUI, which has a restrictive CSP disallowing
// subframes. This will cause the navigation to fail due to the CSP check
// and ensure this behaves the same way as the repros steps in
// https://crbug.com/944086.
GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
EXPECT_EQ(chrome_url, shell()->web_contents()->GetLastCommittedURL());
// Use a WebUI with restrictive CSP that disallows subframes. This will cause
// the navigation to fail due to the CSP check and ensure this behaves the
// same way as the repro steps in https://crbug.com/944086.
GURL main_frame_url(
GetWebUIURL("web-ui/title1.html?childsrc=child-src 'none'"));
EXPECT_TRUE(NavigateToURL(shell(), main_frame_url));
EXPECT_EQ(main_frame_url, shell()->web_contents()->GetLastCommittedURL());
{
GURL web_url(embedded_test_server()->GetURL("/title2.html"));
TestNavigationObserver navigation_observer(shell()->web_contents());
EXPECT_TRUE(ExecJs(
shell(), JsReplace("var frame = document.createElement('iframe');\n"
"frame.src = $1;\n"
"document.body.appendChild(frame);\n",
web_url)));
EXPECT_TRUE(
ExecJs(shell(),
JsReplace("var frame = document.createElement('iframe');\n"
"frame.src = $1;\n"
"document.body.appendChild(frame);\n",
web_url),
EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */));
navigation_observer.Wait();
EXPECT_FALSE(navigation_observer.last_navigation_succeeded());
......@@ -239,12 +232,12 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
// Verify that a WebUI document in the main frame is allowed to navigate to
// web content and it properly does cross-process navigation.
IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest, WebUIMainFrameToWebAllowed) {
GURL chrome_url(GetWebUIURL("web-ui/title1.html"));
EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
->GetFrameTree()
->root();
GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
EXPECT_TRUE(NavigateToURL(shell(), chrome_url));
RenderFrameHost* webui_rfh = root->current_frame_host();
scoped_refptr<SiteInstance> webui_site_instance =
webui_rfh->GetSiteInstance();
......@@ -310,11 +303,12 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
WebUIOriginsRequireDedicatedProcess) {
GURL chrome_url(GetWebUIURL("web-ui/title1.html"));
GURL expected_site_url(GetWebUIURL("web-ui"));
// chrome:// URLs should require a dedicated process.
WebContents* web_contents = shell()->web_contents();
BrowserContext* browser_context = web_contents->GetBrowserContext();
GURL chrome_url = GURL(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
IsolationContext(browser_context), chrome_url));
......@@ -323,7 +317,7 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
// Verify that the "hostname" is also part of the site URL.
GURL site_url = web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL();
EXPECT_EQ(chrome_url, site_url);
EXPECT_EQ(expected_site_url, site_url);
// Ask the page to create a blob URL and return back the blob URL.
const char* kScript = R"(
......@@ -331,14 +325,17 @@ IN_PROC_BROWSER_TEST_F(WebUINavigationBrowserTest,
var url = URL.createObjectURL(blob);
url;
)";
GURL blob_url(EvalJs(shell(), kScript).ExtractString());
GURL blob_url(
EvalJs(shell(), kScript, EXECUTE_SCRIPT_DEFAULT_OPTIONS, 1 /* world_id */)
.ExtractString());
EXPECT_EQ(url::kBlobScheme, blob_url.scheme());
// Verify that the blob also requires a dedicated process and that it would
// use the same site url as the original page.
EXPECT_TRUE(SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
IsolationContext(browser_context), blob_url));
EXPECT_EQ(chrome_url, SiteInstance::GetSiteForURL(browser_context, blob_url));
EXPECT_EQ(expected_site_url,
SiteInstance::GetSiteForURL(browser_context, blob_url));
}
} // namespace content
......@@ -12,6 +12,7 @@
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/webui/web_ui_browsertest_util.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_ui.h"
......@@ -32,115 +33,6 @@
namespace content {
namespace {
void GetResource(const std::string& id,
const WebUIDataSource::GotDataCallback& callback) {
base::ScopedAllowBlockingForTesting allow_blocking;
if (id == "error") {
callback.Run(nullptr);
return;
}
std::string contents;
base::FilePath path;
CHECK(base::PathService::Get(content::DIR_TEST_DATA, &path));
path = path.AppendASCII(id.substr(0, id.find("?")));
CHECK(base::ReadFileToString(path, &contents)) << path.value();
base::RefCountedString* ref_contents = new base::RefCountedString;
ref_contents->data() = contents;
callback.Run(ref_contents);
}
struct WebUIControllerConfig {
int bindings = BINDINGS_POLICY_WEB_UI;
std::string child_src = "child-src 'self' chrome://web-ui-subframe/;";
bool disable_xfo = false;
};
class TestWebUIController : public WebUIController {
public:
TestWebUIController(WebUI* web_ui,
const GURL& base_url,
const WebUIControllerConfig& config)
: WebUIController(web_ui) {
web_ui->SetBindings(config.bindings);
WebUIDataSource* data_source = WebUIDataSource::Create(base_url.host());
data_source->SetRequestFilter(
base::BindRepeating([](const std::string& path) { return true; }),
base::BindRepeating(&GetResource));
if (!config.child_src.empty())
data_source->OverrideContentSecurityPolicyChildSrc(config.child_src);
if (config.disable_xfo)
data_source->DisableDenyXFrameOptions();
WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
data_source);
}
private:
DISALLOW_COPY_AND_ASSIGN(TestWebUIController);
};
class TestWebUIControllerFactory : public WebUIControllerFactory {
public:
TestWebUIControllerFactory() {}
std::unique_ptr<WebUIController> CreateWebUIControllerForURL(
WebUI* web_ui,
const GURL& url) override {
if (!url.SchemeIs(kChromeUIScheme))
return nullptr;
WebUIControllerConfig config;
config.disable_xfo = disable_xfo_;
if (url.has_query()) {
std::string value;
bool has_value = net::GetValueForKeyInQuery(url, "bindings", &value);
if (has_value)
EXPECT_TRUE(base::StringToInt(value, &(config.bindings)));
has_value = net::GetValueForKeyInQuery(url, "noxfo", &value);
if (has_value && value == "true")
config.disable_xfo = true;
}
return std::make_unique<TestWebUIController>(web_ui, url, config);
}
WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
const GURL& url) override {
if (!url.SchemeIs(kChromeUIScheme))
return WebUI::kNoWebUI;
return reinterpret_cast<WebUI::TypeID>(base::FastHash(url.host()));
}
bool UseWebUIForURL(BrowserContext* browser_context,
const GURL& url) override {
return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
}
bool UseWebUIBindingsForURL(BrowserContext* browser_context,
const GURL& url) override {
return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
}
void set_disable_xfo(bool disable) { disable_xfo_ = disable; }
private:
bool disable_xfo_ = false;
DISALLOW_COPY_AND_ASSIGN(TestWebUIControllerFactory);
};
} // namespace
class WebUISecurityTest : public ContentBrowserTest {
public:
WebUISecurityTest() { WebUIControllerFactory::RegisterFactory(&factory_); }
......
......@@ -1031,6 +1031,8 @@ test("content_browsertests") {
"../browser/webrtc/webrtc_webcam_browsertest.cc",
"../browser/webrtc/webrtc_webcam_browsertest.h",
"../browser/webui/web_ui_browsertest.cc",
"../browser/webui/web_ui_browsertest_util.cc",
"../browser/webui/web_ui_browsertest_util.h",
"../browser/webui/web_ui_mojo_browsertest.cc",
"../browser/webui/web_ui_navigation_browsertest.cc",
"../browser/webui/web_ui_security_browsertest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment