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_
......@@ -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