Commit e917f7b2 authored by David Dorwin's avatar David Dorwin Committed by Chromium LUCI CQ

[fuchsia] Implement fuchsia.web.CreateFrameParams.explicit_sites_filter_error_page

When explicit_sites_filter_error_page is present in CreateFrameParams,
use SafeSitesNavigationThrottle to filter explicit pages.

Bug: 1147231
Change-Id: Ie722d9e409ed480fe1956f0aacc7198d7076d4ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2531653Reviewed-by: default avatarWez <wez@chromium.org>
Reviewed-by: default avatarMichael Giuffrida <michaelpg@chromium.org>
Reviewed-by: default avatarSergey Poromov <poromov@chromium.org>
Reviewed-by: default avatarColin Blundell <blundell@chromium.org>
Reviewed-by: default avatarSergey Ulanov <sergeyu@chromium.org>
Commit-Queue: David Dorwin <ddorwin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835799}
parent 1fc7d7cf
......@@ -9,6 +9,7 @@
#include <lib/zx/vmo.h>
#include <string>
#include "base/check.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
......@@ -65,6 +66,25 @@ bool StringFromMemBuffer(const fuchsia::mem::Buffer& buffer,
return true;
}
bool StringFromMemData(const fuchsia::mem::Data& data, std::string* output) {
switch (data.Which()) {
case fuchsia::mem::Data::kBytes: {
const std::vector<uint8_t>& bytes = data.bytes();
output->assign(bytes.begin(), bytes.end());
return true;
}
case fuchsia::mem::Data::kBuffer:
return StringFromMemBuffer(data.buffer(), output);
case fuchsia::mem::Data::kUnknown:
case fuchsia::mem::Data::Invalid:
// TODO(fxbug.dev/66155): Determine whether to use a default case instead.
break;
}
NOTREACHED();
return false;
}
fuchsia::mem::Buffer MemBufferFromFile(base::File file) {
if (!file.IsValid())
return {};
......
......@@ -14,6 +14,8 @@
namespace cr_fuchsia {
// TODO(crbug.com/1156780): Replace bool returns with base::Optional.
// Reads the contents of |buffer|, encoded in UTF-8, to a UTF-16 string.
// Returns |false| if |buffer| is not valid UTF-8.
bool ReadUTF8FromVMOAsUTF16(const fuchsia::mem::Buffer& buffer,
......@@ -32,6 +34,10 @@ fuchsia::mem::Buffer MemBufferFromString16(const base::StringPiece16& data,
bool StringFromMemBuffer(const fuchsia::mem::Buffer& buffer,
std::string* output);
// Reads the contents of |data| into |output|.
// Returns true if the read operation succeeded.
bool StringFromMemData(const fuchsia::mem::Data& data, std::string* output);
// Creates a memory-mapped, read-only Buffer with the contents of |file|.
// Will return an empty Buffer if the file could not be opened.
fuchsia::mem::Buffer MemBufferFromFile(base::File file);
......
......@@ -52,6 +52,7 @@ void TestNavigationListener::RunUntilNavigationStateMatches(
void TestNavigationListener::RunUntilLoaded() {
fuchsia::web::NavigationState state;
state.set_page_type(fuchsia::web::PageType::NORMAL);
state.set_is_main_document_loaded(true);
RunUntilNavigationStateMatches(state);
}
......@@ -59,6 +60,7 @@ void TestNavigationListener::RunUntilLoaded() {
void TestNavigationListener::RunUntilUrlEquals(const GURL& expected_url) {
fuchsia::web::NavigationState state;
state.set_url(expected_url.spec());
state.set_page_type(fuchsia::web::PageType::NORMAL);
state.set_is_main_document_loaded(true);
RunUntilNavigationStateMatches(state);
}
......@@ -67,6 +69,7 @@ void TestNavigationListener::RunUntilTitleEquals(
const base::StringPiece expected_title) {
fuchsia::web::NavigationState state;
state.set_title(expected_title.as_string());
state.set_page_type(fuchsia::web::PageType::NORMAL);
RunUntilNavigationStateMatches(state);
}
......@@ -76,6 +79,16 @@ void TestNavigationListener::RunUntilUrlAndTitleEquals(
fuchsia::web::NavigationState state;
state.set_url(expected_url.spec());
state.set_title(expected_title.as_string());
state.set_page_type(fuchsia::web::PageType::NORMAL);
RunUntilNavigationStateMatches(state);
}
void TestNavigationListener::RunUntilErrorPageIsLoadedAndTitleEquals(
base::StringPiece expected_title) {
fuchsia::web::NavigationState state;
state.set_title(expected_title.as_string());
state.set_page_type(fuchsia::web::PageType::ERROR);
state.set_is_main_document_loaded(true);
RunUntilNavigationStateMatches(state);
}
......@@ -87,6 +100,7 @@ void TestNavigationListener::RunUntilUrlTitleBackForwardEquals(
fuchsia::web::NavigationState state;
state.set_url(expected_url.spec());
state.set_title(expected_title.as_string());
state.set_page_type(fuchsia::web::PageType::NORMAL);
state.set_can_go_back(expected_can_go_back);
state.set_can_go_forward(expected_can_go_forward);
RunUntilNavigationStateMatches(state);
......
......@@ -31,24 +31,29 @@ class TestNavigationListener : public fuchsia::web::NavigationEventListener {
const fuchsia::web::NavigationState& expected_state);
// Calls RunUntilNavigationStateMatches with a NavigationState that has
// loaded.
// the main document loaded and the normal page type.
void RunUntilLoaded();
// Calls RunUntilNavigationStateMatches with a NavigationState that has
// |expected_url|.
// |expected_url|, the normal page type, and the main document loaded.
void RunUntilUrlEquals(const GURL& expected_url);
// Calls RunUntilNavigationStateMatches with a NavigationState that has
// |expected_title|.
// |expected_title| and the normal page type.
void RunUntilTitleEquals(const base::StringPiece expected_title);
// Calls RunUntilNavigationStateMatches with a NavigationState that has
// |expected_url| and |expected_title|.
// |expected_url|, |expected_title|, and the normal page type.
void RunUntilUrlAndTitleEquals(const GURL& expected_url,
base::StringPiece expected_title);
// Calls RunUntilNavigationStateMatches with a NavigationState that has
// all the expected fields.
// the error page type, |expected_title|, and the main document loaded.
void RunUntilErrorPageIsLoadedAndTitleEquals(
base::StringPiece expected_title);
// Calls RunUntilNavigationStateMatches with a NavigationState that has
// all the expected fields and the normal page type.
void RunUntilUrlTitleBackForwardEquals(const GURL& expected_url,
base::StringPiece expected_title,
bool expected_can_go_back,
......
......@@ -74,10 +74,12 @@ component("web_engine_core") {
"//base:base_static",
"//base/util/memory_pressure",
"//components/cdm/renderer",
"//components/keyed_service/content",
"//components/media_control/browser",
"//components/media_control/renderer",
"//components/on_load_script_injector/browser",
"//components/on_load_script_injector/renderer",
"//components/policy/content:safe_sites_navigation_throttle",
"//components/version_info",
"//content/public/app",
"//content/public/browser",
......@@ -305,6 +307,7 @@ test("web_engine_browsertests") {
"browser/cast_streaming_browsertest.cc",
"browser/content_directory_browsertest.cc",
"browser/context_impl_browsertest.cc",
"browser/explicit_sites_filter_browsertest.cc",
"browser/fake_navigation_policy_provider.cc",
"browser/fake_navigation_policy_provider.h",
"browser/fake_semantic_tree.cc",
......@@ -325,6 +328,9 @@ test("web_engine_browsertests") {
":switches",
":web_engine_core",
"//base/test:test_support",
"//components/policy/content:safe_sites_navigation_throttle",
"//components/safe_search_api:safe_search_api",
"//components/safe_search_api:test_support",
"//content/public/browser",
"//content/test:test_support",
"//fuchsia/base",
......
include_rules = [
"+components/keyed_service/content",
"+components/keyed_service/core",
"+components/on_load_script_injector/browser",
"+components/policy/content",
"+content/public/common",
"+content/public/browser",
"+media/base",
......@@ -33,4 +35,7 @@ specific_include_rules = {
"+content/public/test",
"+services/network",
],
"explicit_sites_filter_browsertest.cc": [
"+components/safe_search_api",
],
}
......@@ -14,6 +14,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/cast_streaming/public/cast_streaming_session.h"
#include "fuchsia/cast_streaming/public/network_context_getter.h"
#include "fuchsia/engine/browser/frame_impl.h"
......@@ -89,6 +90,20 @@ void ContextImpl::CreateFrameForWebContents(
blink::web_pref::WebPreferences web_preferences =
web_contents->GetOrCreateWebPreferences();
// Register the new Frame with the DevTools controller. The controller will
// reject registration if user-debugging is requested, but it is not enabled
// in the controller.
const bool user_debugging_requested =
params.has_enable_remote_debugging() && params.enable_remote_debugging();
if (!devtools_controller_->OnFrameCreated(web_contents.get(),
user_debugging_requested)) {
frame_request.Close(ZX_ERR_INVALID_ARGS);
return;
}
// |params.debug_name| is not currently supported.
// TODO(crbug.com/1051533): Determine whether it is still needed.
// REQUIRE_USER_ACTIVATION is the default per the FIDL API.
web_preferences.autoplay_policy =
blink::mojom::AutoplayPolicy::kDocumentUserActivationRequired;
......@@ -107,13 +122,27 @@ void ContextImpl::CreateFrameForWebContents(
}
web_contents->SetWebPreferences(web_preferences);
// Register the new Frame with the DevTools controller. The controller will
// reject registration if user-debugging is requested, but it is not enabled
// in the controller.
const bool user_debugging_requested =
params.has_enable_remote_debugging() && params.enable_remote_debugging();
if (!devtools_controller_->OnFrameCreated(web_contents.get(),
user_debugging_requested)) {
// Verify the explicit sites filter error page content. If the parameter is
// present, it will be provided to the FrameImpl after it is created below.
base::Optional<std::string> explicit_sites_filter_error_page;
if (params.has_explicit_sites_filter_error_page()) {
explicit_sites_filter_error_page.emplace();
if (!cr_fuchsia::StringFromMemData(
params.explicit_sites_filter_error_page(),
&explicit_sites_filter_error_page.value())) {
frame_request.Close(ZX_ERR_INVALID_ARGS);
return;
}
}
// FrameImpl clones the params used to create it when creating popup Frames.
// Ensure the params can be cloned to avoid problems when creating popups.
// TODO(http://fxbug.dev/65750): Remove this limitation once a soft migration
// to a new solution has been completed.
fuchsia::web::CreateFrameParams cloned_params;
zx_status_t status = params.Clone(&cloned_params);
if (status != ZX_OK) {
ZX_LOG(ERROR, status) << "CreateFrameParams clone failed";
frame_request.Close(ZX_ERR_INVALID_ARGS);
return;
}
......@@ -122,6 +151,12 @@ void ContextImpl::CreateFrameForWebContents(
auto frame_impl =
std::make_unique<FrameImpl>(std::move(web_contents), this,
std::move(params), std::move(frame_request));
if (explicit_sites_filter_error_page) {
frame_impl->EnableExplicitSitesFilter(
std::move(*explicit_sites_filter_error_page));
}
frames_.insert(std::move(frame_impl));
}
......
// Copyright 2020 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 <fuchsia/web/cpp/fidl.h>
#include <string>
#include "components/policy/content/safe_search_service.h"
#include "components/safe_search_api/stub_url_checker.h"
#include "components/safe_search_api/url_checker.h"
#include "content/public/test/browser_test.h"
#include "fuchsia/base/frame_test_util.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/engine/browser/frame_impl.h"
#include "fuchsia/engine/browser/frame_impl_browser_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
constexpr char kPage1Path[] = "/title1.html";
constexpr char kPage1Title[] = "title 1";
constexpr char kCustomErrorPageTitle[] = "Custom Error Page Title";
constexpr char kCustomExplicitSitesErrorPage[] = R"(<html>
<head><title>Custom Error Page Title</title></head>
<body>
<b>This is a custom error</b>
</body>
</html>)";
// Creates a Fuchsia memory data from |data|.
// |data| should be a short string to avoid exceeding Zircon channel limits.
fuchsia::mem::Data MemDataBytesFromShortString(base::StringPiece data) {
return fuchsia::mem::Data::WithBytes(
std::vector<uint8_t>(data.begin(), data.end()));
}
} // namespace
// Defines a suite of tests that exercise Frame-level functionality, such as
// navigation commands and page events.
class ExplicitSitesFilterTest : public FrameImplTestBaseWithServer {
public:
ExplicitSitesFilterTest() = default;
~ExplicitSitesFilterTest() override = default;
ExplicitSitesFilterTest(const ExplicitSitesFilterTest&) = delete;
ExplicitSitesFilterTest& operator=(const ExplicitSitesFilterTest&) = delete;
void SetUpOnMainThread() override {
FrameImplTestBaseWithServer::SetUpOnMainThread();
SafeSearchFactory::GetInstance()
->GetForBrowserContext(context_impl()->browser_context_for_test())
->SetSafeSearchURLCheckerForTest(
stub_url_checker_.BuildURLChecker(kUrlCheckerCacheSize));
}
protected:
const size_t kUrlCheckerCacheSize = 1;
void SetPageIsNotExplicit() {
stub_url_checker_.SetUpValidResponse(false /* is_porn */);
}
void SetPageIsExplicit() {
stub_url_checker_.SetUpValidResponse(true /* is_porn */);
}
std::string GetPage1UrlSpec() const {
return embedded_test_server()->GetURL(kPage1Path).spec();
}
safe_search_api::StubURLChecker stub_url_checker_;
};
IN_PROC_BROWSER_TEST_F(ExplicitSitesFilterTest, FilterDisabled_SiteAllowed) {
fuchsia::web::CreateFrameParams params;
fuchsia::web::FramePtr frame = WebEngineBrowserTest::CreateFrameWithParams(
&navigation_listener_, std::move(params));
SetPageIsNotExplicit();
fuchsia::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(controller.get(), {},
GetPage1UrlSpec()));
navigation_listener_.RunUntilTitleEquals(kPage1Title);
}
IN_PROC_BROWSER_TEST_F(ExplicitSitesFilterTest, FilterDisabled_SiteBlocked) {
fuchsia::web::CreateFrameParams params;
fuchsia::web::FramePtr frame = WebEngineBrowserTest::CreateFrameWithParams(
&navigation_listener_, std::move(params));
SetPageIsExplicit();
fuchsia::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(controller.get(), {},
GetPage1UrlSpec()));
navigation_listener_.RunUntilTitleEquals(kPage1Title);
}
IN_PROC_BROWSER_TEST_F(ExplicitSitesFilterTest, DefaultErrorPage_SiteAllowed) {
fuchsia::web::CreateFrameParams params;
params.set_explicit_sites_filter_error_page(
fuchsia::mem::Data::WithBytes({}));
fuchsia::web::FramePtr frame = WebEngineBrowserTest::CreateFrameWithParams(
&navigation_listener_, std::move(params));
SetPageIsNotExplicit();
fuchsia::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(controller.get(), {},
GetPage1UrlSpec()));
navigation_listener_.RunUntilTitleEquals(kPage1Title);
}
IN_PROC_BROWSER_TEST_F(ExplicitSitesFilterTest, DefaultErrorPage_SiteBlocked) {
fuchsia::web::CreateFrameParams params;
params.set_explicit_sites_filter_error_page(
fuchsia::mem::Data::WithBytes({}));
fuchsia::web::FramePtr frame = WebEngineBrowserTest::CreateFrameWithParams(
&navigation_listener_, std::move(params));
SetPageIsExplicit();
fuchsia::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(controller.get(), {},
GetPage1UrlSpec()));
// The page title is the URL for which navigation failed without the scheme
// part ("http://");
std::string expected_title = GetPage1UrlSpec().erase(0, 7);
navigation_listener_.RunUntilErrorPageIsLoadedAndTitleEquals(expected_title);
}
IN_PROC_BROWSER_TEST_F(ExplicitSitesFilterTest, CustomErrorPage_SiteAllowed) {
fuchsia::web::CreateFrameParams params;
params.set_explicit_sites_filter_error_page(
MemDataBytesFromShortString(kCustomExplicitSitesErrorPage));
fuchsia::web::FramePtr frame = WebEngineBrowserTest::CreateFrameWithParams(
&navigation_listener_, std::move(params));
SetPageIsNotExplicit();
fuchsia::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(controller.get(), {},
GetPage1UrlSpec()));
navigation_listener_.RunUntilTitleEquals(kPage1Title);
}
IN_PROC_BROWSER_TEST_F(ExplicitSitesFilterTest, CustomErrorPage_SiteBlocked) {
fuchsia::web::CreateFrameParams params;
params.set_explicit_sites_filter_error_page(
MemDataBytesFromShortString(kCustomExplicitSitesErrorPage));
fuchsia::web::FramePtr frame = WebEngineBrowserTest::CreateFrameWithParams(
&navigation_listener_, std::move(params));
SetPageIsExplicit();
fuchsia::web::NavigationControllerPtr controller;
frame->GetNavigationController(controller.NewRequest());
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(controller.get(), {},
GetPage1UrlSpec()));
navigation_listener_.RunUntilErrorPageIsLoadedAndTitleEquals(
kCustomErrorPageTitle);
}
......@@ -1135,3 +1135,8 @@ void FrameImpl::ResourceLoadComplete(
base::StringPrintf("WebEngine.ResourceRequestError:%d", net_error));
}
}
// TODO(crbug.com/1136681#c6): Move below GetBindingChannelForTest when fixed.
void FrameImpl::EnableExplicitSitesFilter(std::string error_page) {
explicit_sites_filter_error_page_ = std::move(error_page);
}
......@@ -19,6 +19,7 @@
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/optional.h"
#include "components/media_control/browser/media_blocker.h"
#include "components/on_load_script_injector/browser/on_load_script_injector_host.h"
#include "content/public/browser/web_contents_delegate.h"
......@@ -99,6 +100,14 @@ class FrameImpl : public fuchsia::web::Frame,
return cast_streaming_session_client_.get();
}
// Enables explicit sites filtering and set the error page. If |error_page| is
// empty, the default error page will be used.
void EnableExplicitSitesFilter(std::string error_page);
const base::Optional<std::string>& explicit_sites_filter_error_page() const {
return explicit_sites_filter_error_page_;
}
private:
FRIEND_TEST_ALL_PREFIXES(FrameImplTest, DelayedNavigationEventAck);
FRIEND_TEST_ALL_PREFIXES(FrameImplTest, NavigationObserverDisconnected);
......@@ -298,6 +307,11 @@ class FrameImpl : public fuchsia::web::Frame,
ThemeManager theme_manager_;
// The error page to be displayed when a navigation to an explicit site is
// filtered. Explicit sites are filtered if it has a value. If set to the
// empty string, the default error page will be displayed.
base::Optional<std::string> explicit_sites_filter_error_page_;
base::WeakPtrFactory<FrameImpl> weak_factory_{this};
};
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/web/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
......
......@@ -13,6 +13,7 @@
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/system/sys_info.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/keyed_service/core/simple_key_map.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
......@@ -99,6 +100,9 @@ WebEngineBrowserContext::~WebEngineBrowserContext() {
FROM_HERE, std::move(resource_context_));
}
BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
this);
ShutdownStoragePartitions();
}
......
......@@ -10,6 +10,7 @@
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "components/policy/content/safe_sites_navigation_throttle.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/devtools_manager_delegate.h"
#include "content/public/browser/navigation_handle.h"
......@@ -198,6 +199,17 @@ WebEngineContentBrowserClient::CreateThrottlesForNavigation(
throttles.push_back(std::make_unique<NavigationPolicyThrottle>(
navigation_handle, frame_impl->navigation_policy_handler()));
}
const base::Optional<std::string>& explicit_sites_filter_error_page =
frame_impl->explicit_sites_filter_error_page();
if (explicit_sites_filter_error_page) {
throttles.push_back(std::make_unique<SafeSitesNavigationThrottle>(
navigation_handle,
navigation_handle->GetWebContents()->GetBrowserContext(),
*explicit_sites_filter_error_page));
}
return throttles;
}
......
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