Commit 62e19745 authored by Wez's avatar Wez Committed by Commit Bot

[fuchsia] Implement fuchsia.web.Frame/SetUrlRequestRewriteRules.

* Implement the fuchsia.web.Frame/SetUrlRequestRewriteRules API.
* Add a mojo interface to provide the renderers with new rules.
  * This interface is implemented in the browser in
    UrlRequestRewriteRulesManager, which also takes care of validating
    and converting the rules from FIDL to Mojo, and providing them to
    the WebEngineURLLoaderThrottles in the browser.
  * In the renderer, there is one rules receiver per RenderFrame,
    implemented in UrlRequestRulesReceiver. They cache the rules and
    provide them to the WebEngineURLLoaderThrottles in the renderer.
* Add unit tests and browser tests for the new API.

Bug: 976975
Change-Id: I446ea4838d50e65c568e7e2cbcd32c23d64af426
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1659677
Commit-Queue: Wez <wez@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#695298}
parent 9e470ebe
...@@ -1122,6 +1122,8 @@ _BANNED_CPP_FUNCTIONS = ( ...@@ -1122,6 +1122,8 @@ _BANNED_CPP_FUNCTIONS = (
), ),
False, False,
( (
r'^fuchsia/engine/browser/url_request_rewrite_rules_manager\.cc$',
r'^fuchsia/engine/url_request_rewrite_type_converters\.cc$',
r'^third_party/blink/.*\.(cc|h)$', r'^third_party/blink/.*\.(cc|h)$',
r'^content/renderer/.*\.(cc|h)$', r'^content/renderer/.*\.(cc|h)$',
), ),
......
...@@ -73,6 +73,8 @@ source_set("test_support") { ...@@ -73,6 +73,8 @@ source_set("test_support") {
"test_devtools_list_fetcher.h", "test_devtools_list_fetcher.h",
"test_navigation_listener.cc", "test_navigation_listener.cc",
"test_navigation_listener.h", "test_navigation_listener.h",
"url_request_rewrite_test_util.cc",
"url_request_rewrite_test_util.h",
] ]
public_deps = [ public_deps = [
":base", ":base",
......
// 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 "fuchsia/base/url_request_rewrite_test_util.h"
#include "fuchsia/base/string_util.h"
namespace cr_fuchsia {
fuchsia::web::UrlRequestRewrite CreateRewriteAddHeaders(
base::StringPiece header_name,
base::StringPiece header_value) {
fuchsia::net::http::Header header;
header.name = cr_fuchsia::StringToBytes(header_name);
header.value = cr_fuchsia::StringToBytes(header_value);
std::vector<fuchsia::net::http::Header> response_headers;
response_headers.push_back(std::move(header));
fuchsia::web::UrlRequestRewriteAddHeaders add_headers;
add_headers.set_headers(std::move(response_headers));
fuchsia::web::UrlRequestRewrite rewrite;
rewrite.set_add_headers(std::move(add_headers));
return rewrite;
}
fuchsia::web::UrlRequestRewrite CreateRewriteRemoveHeader(
base::Optional<base::StringPiece> query_pattern,
base::StringPiece header_name) {
fuchsia::web::UrlRequestRewriteRemoveHeader remove_header;
if (query_pattern)
remove_header.set_query_pattern(query_pattern.value().as_string());
remove_header.set_header_name(cr_fuchsia::StringToBytes(header_name));
fuchsia::web::UrlRequestRewrite rewrite;
rewrite.set_remove_header(std::move(remove_header));
return rewrite;
}
fuchsia::web::UrlRequestRewrite CreateRewriteSubstituteQueryPattern(
base::StringPiece pattern,
base::StringPiece substitution) {
fuchsia::web::UrlRequestRewriteSubstituteQueryPattern
substitute_query_pattern;
substitute_query_pattern.set_pattern(pattern.as_string());
substitute_query_pattern.set_substitution(substitution.as_string());
fuchsia::web::UrlRequestRewrite rewrite;
rewrite.set_substitute_query_pattern(std::move(substitute_query_pattern));
return rewrite;
}
fuchsia::web::UrlRequestRewrite CreateRewriteReplaceUrl(
base::StringPiece url_ends_with,
base::StringPiece new_url) {
fuchsia::web::UrlRequestRewriteReplaceUrl replace_url;
replace_url.set_url_ends_with(url_ends_with.as_string());
replace_url.set_new_url(new_url.as_string());
fuchsia::web::UrlRequestRewrite rewrite;
rewrite.set_replace_url(std::move(replace_url));
return rewrite;
}
} // namespace cr_fuchsia
// 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 FUCHSIA_BASE_URL_REQUEST_REWRITE_TEST_UTIL_H_
#define FUCHSIA_BASE_URL_REQUEST_REWRITE_TEST_UTIL_H_
#include <fuchsia/web/cpp/fidl.h>
#include "base/optional.h"
#include "base/strings/string_piece.h"
namespace cr_fuchsia {
// Utility functions to create a fuchsia.web.UrlRequestRewrite in one line.
fuchsia::web::UrlRequestRewrite CreateRewriteAddHeaders(
base::StringPiece header_name,
base::StringPiece header_value);
fuchsia::web::UrlRequestRewrite CreateRewriteRemoveHeader(
base::Optional<base::StringPiece> query_pattern,
base::StringPiece header_name);
fuchsia::web::UrlRequestRewrite CreateRewriteSubstituteQueryPattern(
base::StringPiece pattern,
base::StringPiece substitution);
fuchsia::web::UrlRequestRewrite CreateRewriteReplaceUrl(
base::StringPiece url_ends_with,
base::StringPiece new_url);
} // namespace cr_fuchsia
#endif // FUCHSIA_BASE_URL_REQUEST_REWRITE_TEST_UTIL_H_
...@@ -17,9 +17,11 @@ config("web_engine_implementation") { ...@@ -17,9 +17,11 @@ config("web_engine_implementation") {
mojom("mojom") { mojom("mojom") {
sources = [ sources = [
"on_load_script_injector.mojom", "on_load_script_injector.mojom",
"url_request_rewrite.mojom",
] ]
public_deps = [ public_deps = [
"//mojo/public/mojom/base", "//mojo/public/mojom/base",
"//services/network/public/mojom",
] ]
visibility = [ ":*" ] visibility = [ ":*" ]
} }
...@@ -123,6 +125,8 @@ component("web_engine_core") { ...@@ -123,6 +125,8 @@ component("web_engine_core") {
"browser/frame_impl.h", "browser/frame_impl.h",
"browser/navigation_controller_impl.cc", "browser/navigation_controller_impl.cc",
"browser/navigation_controller_impl.h", "browser/navigation_controller_impl.h",
"browser/url_request_rewrite_rules_manager.cc",
"browser/url_request_rewrite_rules_manager.h",
"browser/web_engine_browser_context.cc", "browser/web_engine_browser_context.cc",
"browser/web_engine_browser_context.h", "browser/web_engine_browser_context.h",
"browser/web_engine_browser_main.cc", "browser/web_engine_browser_main.cc",
...@@ -145,14 +149,22 @@ component("web_engine_core") { ...@@ -145,14 +149,22 @@ component("web_engine_core") {
"browser/web_engine_screen.h", "browser/web_engine_screen.h",
"common.cc", "common.cc",
"common.h", "common.h",
"common/web_engine_url_loader_throttle.cc",
"common/web_engine_url_loader_throttle.h",
"context_provider_impl.cc", "context_provider_impl.cc",
"context_provider_impl.h", "context_provider_impl.h",
"context_provider_main.cc", "context_provider_main.cc",
"context_provider_main.h", "context_provider_main.h",
"renderer/on_load_script_injector.cc", "renderer/on_load_script_injector.cc",
"renderer/on_load_script_injector.h", "renderer/on_load_script_injector.h",
"renderer/url_request_rules_receiver.cc",
"renderer/url_request_rules_receiver.h",
"renderer/web_engine_content_renderer_client.cc", "renderer/web_engine_content_renderer_client.cc",
"renderer/web_engine_content_renderer_client.h", "renderer/web_engine_content_renderer_client.h",
"renderer/web_engine_url_loader_throttle_provider.cc",
"renderer/web_engine_url_loader_throttle_provider.h",
"url_request_rewrite_type_converters.cc",
"url_request_rewrite_type_converters.h",
"web_engine_content_client.cc", "web_engine_content_client.cc",
"web_engine_content_client.h", "web_engine_content_client.h",
"web_engine_export.h", "web_engine_export.h",
...@@ -253,6 +265,7 @@ test("web_engine_unittests") { ...@@ -253,6 +265,7 @@ test("web_engine_unittests") {
sources = [ sources = [
"browser/cookie_manager_impl_unittest.cc", "browser/cookie_manager_impl_unittest.cc",
"browser/frame_impl_unittest.cc", "browser/frame_impl_unittest.cc",
"browser/url_request_rewrite_rules_manager_unittest.cc",
"context_provider_impl_unittest.cc", "context_provider_impl_unittest.cc",
"fake_context.cc", "fake_context.cc",
"fake_context.h", "fake_context.h",
......
...@@ -3,6 +3,7 @@ include_rules = [ ...@@ -3,6 +3,7 @@ include_rules = [
"+content/public/app", "+content/public/app",
"+gpu/command_buffer/service", "+gpu/command_buffer/service",
"+media/base", "+media/base",
"+mojo/public",
"+services/service_manager", "+services/service_manager",
"+third_party/widevine/cdm/widevine_cdm_common.h", "+third_party/widevine/cdm/widevine_cdm_common.h",
"+ui/base", "+ui/base",
......
per-file *.mojom=set noparent per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS per-file *.mojom=file://ipc/SECURITY_OWNERS
per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
...@@ -184,6 +184,7 @@ FrameImpl::FrameImpl(std::unique_ptr<content::WebContents> web_contents, ...@@ -184,6 +184,7 @@ FrameImpl::FrameImpl(std::unique_ptr<content::WebContents> web_contents,
context_(context), context_(context),
navigation_controller_(web_contents_.get()), navigation_controller_(web_contents_.get()),
log_level_(kLogSeverityNone), log_level_(kLogSeverityNone),
url_request_rewrite_rules_manager_(web_contents_.get()),
binding_(this, std::move(frame_request)) { binding_(this, std::move(frame_request)) {
web_contents_->SetDelegate(this); web_contents_->SetDelegate(this);
Observe(web_contents_.get()); Observe(web_contents_.get());
...@@ -344,6 +345,12 @@ void FrameImpl::AddNewContents( ...@@ -344,6 +345,12 @@ void FrameImpl::AddNewContents(
case WindowOpenDisposition::NEW_BACKGROUND_TAB: case WindowOpenDisposition::NEW_BACKGROUND_TAB:
case WindowOpenDisposition::NEW_POPUP: case WindowOpenDisposition::NEW_POPUP:
case WindowOpenDisposition::NEW_WINDOW: { case WindowOpenDisposition::NEW_WINDOW: {
if (url_request_rewrite_rules_manager_.GetCachedRules()) {
// There is no support for URL request rules rewriting with popups.
*was_blocked = true;
return;
}
PopupFrameCreationInfoUserData* popup_creation_info = PopupFrameCreationInfoUserData* popup_creation_info =
reinterpret_cast<PopupFrameCreationInfoUserData*>( reinterpret_cast<PopupFrameCreationInfoUserData*>(
new_contents->GetUserData(kPopupCreationInfo)); new_contents->GetUserData(kPopupCreationInfo));
...@@ -620,6 +627,15 @@ void FrameImpl::SetPopupFrameCreationListener( ...@@ -620,6 +627,15 @@ void FrameImpl::SetPopupFrameCreationListener(
fit::bind_member(this, &FrameImpl::OnPopupListenerDisconnected)); fit::bind_member(this, &FrameImpl::OnPopupListenerDisconnected));
} }
void FrameImpl::SetUrlRequestRewriteRules(
std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
SetUrlRequestRewriteRulesCallback callback) {
zx_status_t error = url_request_rewrite_rules_manager_.OnRulesUpdated(
std::move(rules), std::move(callback));
if (error != ZX_OK)
binding_.Close(error);
}
void FrameImpl::CloseContents(content::WebContents* source) { void FrameImpl::CloseContents(content::WebContents* source) {
DCHECK_EQ(source, web_contents_.get()); DCHECK_EQ(source, web_contents_.get());
context_->DestroyFrame(this); context_->DestroyFrame(this);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <fuchsia/web/cpp/fidl.h> #include <fuchsia/web/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h> #include <lib/fidl/cpp/binding_set.h>
#include <lib/zx/channel.h> #include <lib/zx/channel.h>
#include <list> #include <list>
#include <map> #include <map>
#include <memory> #include <memory>
...@@ -21,6 +22,7 @@ ...@@ -21,6 +22,7 @@
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "fuchsia/engine/browser/discarding_event_filter.h" #include "fuchsia/engine/browser/discarding_event_filter.h"
#include "fuchsia/engine/browser/navigation_controller_impl.h" #include "fuchsia/engine/browser/navigation_controller_impl.h"
#include "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
#include "fuchsia/engine/on_load_script_injector.mojom.h" #include "fuchsia/engine/on_load_script_injector.mojom.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
#include "ui/wm/core/focus_controller.h" #include "ui/wm/core/focus_controller.h"
...@@ -126,6 +128,9 @@ class FrameImpl : public fuchsia::web::Frame, ...@@ -126,6 +128,9 @@ class FrameImpl : public fuchsia::web::Frame,
void SetPopupFrameCreationListener( void SetPopupFrameCreationListener(
fidl::InterfaceHandle<fuchsia::web::PopupFrameCreationListener> listener) fidl::InterfaceHandle<fuchsia::web::PopupFrameCreationListener> listener)
override; override;
void SetUrlRequestRewriteRules(
std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
SetUrlRequestRewriteRulesCallback callback) override;
// content::WebContentsDelegate implementation. // content::WebContentsDelegate implementation.
void CloseContents(content::WebContents* source) override; void CloseContents(content::WebContents* source) override;
...@@ -177,6 +182,7 @@ class FrameImpl : public fuchsia::web::Frame, ...@@ -177,6 +182,7 @@ class FrameImpl : public fuchsia::web::Frame,
std::map<uint64_t, OriginScopedScript> before_load_scripts_; std::map<uint64_t, OriginScopedScript> before_load_scripts_;
std::vector<uint64_t> before_load_scripts_order_; std::vector<uint64_t> before_load_scripts_order_;
base::RepeatingCallback<void(base::StringPiece)> console_log_message_hook_; base::RepeatingCallback<void(base::StringPiece)> console_log_message_hook_;
UrlRequestRewriteRulesManager url_request_rewrite_rules_manager_;
// Used for receiving and dispatching popup created by this Frame. // Used for receiving and dispatching popup created by this Frame.
fuchsia::web::PopupFrameCreationListenerPtr popup_listener_; fuchsia::web::PopupFrameCreationListenerPtr popup_listener_;
...@@ -188,5 +194,4 @@ class FrameImpl : public fuchsia::web::Frame, ...@@ -188,5 +194,4 @@ class FrameImpl : public fuchsia::web::Frame,
DISALLOW_COPY_AND_ASSIGN(FrameImpl); DISALLOW_COPY_AND_ASSIGN(FrameImpl);
}; };
#endif // FUCHSIA_ENGINE_BROWSER_FRAME_IMPL_H_ #endif // FUCHSIA_ENGINE_BROWSER_FRAME_IMPL_H_
// 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 "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
#include "fuchsia/base/string_util.h"
#include "fuchsia/engine/url_request_rewrite_type_converters.h"
#include "net/http/http_util.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
namespace {
using RoutingIdRewriterMap =
std::unordered_map<int, UrlRequestRewriteRulesManager*>;
RoutingIdRewriterMap& GetRewriterMap() {
static base::NoDestructor<RoutingIdRewriterMap> rewriter_map;
return *rewriter_map;
}
bool ValidateAddHeaders(
const fuchsia::web::UrlRequestRewriteAddHeaders& add_headers) {
if (!add_headers.has_headers())
return false;
for (const auto& header : add_headers.headers()) {
base::StringPiece header_name = cr_fuchsia::BytesAsString(header.name);
base::StringPiece header_value = cr_fuchsia::BytesAsString(header.value);
if (!net::HttpUtil::IsValidHeaderName(header_name) ||
!net::HttpUtil::IsValidHeaderValue(header_value))
return false;
}
return true;
}
bool ValidateRemoveHeader(
const fuchsia::web::UrlRequestRewriteRemoveHeader& remove_header) {
if (!remove_header.has_header_name())
return false;
if (!net::HttpUtil::IsValidHeaderName(
cr_fuchsia::BytesAsString(remove_header.header_name())))
return false;
return true;
}
bool ValidateSubstituteQueryPattern(
const fuchsia::web::UrlRequestRewriteSubstituteQueryPattern&
substitute_query_pattern) {
if (!substitute_query_pattern.has_pattern() ||
!substitute_query_pattern.has_substitution())
return false;
return true;
}
bool ValidateReplaceUrl(
const fuchsia::web::UrlRequestRewriteReplaceUrl& replace_url) {
if (!replace_url.has_url_ends_with() || !replace_url.has_new_url())
return false;
if (!GURL("http://site.com/" + replace_url.url_ends_with()).is_valid())
return false;
if (!GURL(replace_url.new_url()).is_valid())
return false;
return true;
}
bool ValidateRewrite(const fuchsia::web::UrlRequestRewrite& rewrite) {
switch (rewrite.Which()) {
case fuchsia::web::UrlRequestRewrite::Tag::kAddHeaders:
return ValidateAddHeaders(rewrite.add_headers());
case fuchsia::web::UrlRequestRewrite::Tag::kRemoveHeader:
return ValidateRemoveHeader(rewrite.remove_header());
case fuchsia::web::UrlRequestRewrite::Tag::kSubstituteQueryPattern:
return ValidateSubstituteQueryPattern(rewrite.substitute_query_pattern());
case fuchsia::web::UrlRequestRewrite::Tag::kReplaceUrl:
return ValidateReplaceUrl(rewrite.replace_url());
default:
// This is to prevent build breakage when adding new rewrites to the FIDL
// definition. This can also happen if the client sends an empty rewrite,
// which is invalid.
return false;
}
}
bool ValidateRules(
const std::vector<fuchsia::web::UrlRequestRewriteRule>& rules) {
for (const auto& rule : rules) {
if (rule.has_hosts_filter() && rule.hosts_filter().empty())
return false;
if (rule.has_schemes_filter() && rule.schemes_filter().empty())
return false;
if (!rule.has_rewrites())
return false;
for (const auto& rewrite : rule.rewrites()) {
if (!ValidateRewrite(rewrite))
return false;
}
}
return true;
}
} // namespace
// static
UrlRequestRewriteRulesManager*
UrlRequestRewriteRulesManager::ForFrameTreeNodeId(int frame_tree_node_id) {
auto iter = GetRewriterMap().find(frame_tree_node_id);
if (iter == GetRewriterMap().end())
return nullptr;
return iter->second;
}
// static
std::unique_ptr<UrlRequestRewriteRulesManager>
UrlRequestRewriteRulesManager::CreateForTesting() {
return base::WrapUnique(new UrlRequestRewriteRulesManager());
}
UrlRequestRewriteRulesManager::UrlRequestRewriteRulesManager(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {}
UrlRequestRewriteRulesManager::~UrlRequestRewriteRulesManager() = default;
zx_status_t UrlRequestRewriteRulesManager::OnRulesUpdated(
std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
fuchsia::web::Frame::SetUrlRequestRewriteRulesCallback callback) {
if (!ValidateRules(rules)) {
base::AutoLock auto_lock(lock_);
cached_rules_ = nullptr;
return ZX_ERR_INVALID_ARGS;
}
base::AutoLock auto_lock(lock_);
cached_rules_ =
base::MakeRefCounted<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>(
mojo::ConvertTo<std::vector<mojom::UrlRequestRewriteRulePtr>>(
std::move(rules)));
// Send the updated rules to the receivers.
for (const auto& receiver_pair : rules_receivers_per_frame_id_) {
receiver_pair.second->OnRulesUpdated(mojo::Clone(cached_rules_->data));
}
// TODO(crbug.com/976975): Only call the callback when there are pending
// throttles.
std::move(callback)();
return ZX_OK;
}
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
UrlRequestRewriteRulesManager::GetCachedRules() {
base::AutoLock auto_lock(lock_);
return cached_rules_;
}
UrlRequestRewriteRulesManager::UrlRequestRewriteRulesManager() {}
void UrlRequestRewriteRulesManager::RenderFrameCreated(
content::RenderFrameHost* render_frame_host) {
int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
if (rules_receivers_per_frame_id_.find(frame_tree_node_id) !=
rules_receivers_per_frame_id_.end()) {
// This happens on cross-process navigations. It is not necessary to refresh
// the global map in this case as RenderFrameDeleted will not have been
// called for this RenderFrameHost.
size_t deleted = rules_receivers_per_frame_id_.erase(frame_tree_node_id);
DCHECK(deleted == 1);
} else {
// Register this instance of UrlRequestRewriteRulesManager as the URL
// request rewriter handler for this RenderFrameHost ID.
auto iter =
GetRewriterMap().emplace(std::make_pair(frame_tree_node_id, this));
DCHECK(iter.second);
}
// Register the frame rules receiver.
mojom::UrlRequestRulesReceiverAssociatedPtr rules_receiver;
render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(
&rules_receiver);
auto iter = rules_receivers_per_frame_id_.emplace(frame_tree_node_id,
std::move(rules_receiver));
DCHECK(iter.second);
base::AutoLock auto_lock(lock_);
if (cached_rules_) {
// Send an initial set of rules.
iter.first->second->OnRulesUpdated(mojo::Clone(cached_rules_->data));
}
}
void UrlRequestRewriteRulesManager::RenderFrameDeleted(
content::RenderFrameHost* render_frame_host) {
int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
size_t deleted = GetRewriterMap().erase(frame_tree_node_id);
DCHECK(deleted == 1);
deleted = rules_receivers_per_frame_id_.erase(frame_tree_node_id);
DCHECK(deleted == 1);
}
// 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 FUCHSIA_ENGINE_BROWSER_URL_REQUEST_REWRITE_RULES_MANAGER_H_
#define FUCHSIA_ENGINE_BROWSER_URL_REQUEST_REWRITE_RULES_MANAGER_H_
#include <fuchsia/web/cpp/fidl.h>
#include "base/synchronization/lock.h"
#include "content/public/browser/web_contents_binding_set.h"
#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
#include "fuchsia/engine/url_request_rewrite.mojom.h"
namespace content {
class RenderFrameHost;
class WebContents;
} // namespace content
// Adapts the UrlRequestRewrite FIDL API to be sent to the renderers over the
// over the UrlRequestRewrite Mojo API.
class UrlRequestRewriteRulesManager
: public content::WebContentsObserver,
public WebEngineURLLoaderThrottle::CachedRulesProvider {
public:
static UrlRequestRewriteRulesManager* ForFrameTreeNodeId(
int frame_tree_node_id);
static std::unique_ptr<UrlRequestRewriteRulesManager> CreateForTesting();
explicit UrlRequestRewriteRulesManager(content::WebContents* web_contents);
~UrlRequestRewriteRulesManager() final;
// Signals |rules| have been updated. Actual implementation for
// fuchsia.web.Frame/SetUrlRequestRewriteRules.
// Return ZX_OK on success and an error code otherwise.
zx_status_t OnRulesUpdated(
std::vector<fuchsia::web::UrlRequestRewriteRule> rules,
fuchsia::web::Frame::SetUrlRequestRewriteRulesCallback callback);
// WebEngineURLLoaderThrottle::CachedRulesProvider implementation.
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
GetCachedRules() override;
private:
// Test-only constructor.
explicit UrlRequestRewriteRulesManager();
// content::WebContentsObserver implementation.
void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
base::Lock lock_;
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
cached_rules_ GUARDED_BY(lock_);
// Map of frames rules receivers per FrameTreeNode ID.
std::map<int, mojom::UrlRequestRulesReceiverAssociatedPtr>
rules_receivers_per_frame_id_;
DISALLOW_COPY_AND_ASSIGN(UrlRequestRewriteRulesManager);
};
#endif // FUCHSIA_ENGINE_BROWSER_URL_REQUEST_REWRITE_RULES_MANAGER_H_
// 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 "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
#include <lib/fidl/cpp/binding.h>
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "fuchsia/base/url_request_rewrite_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
class UrlRequestRewriteRulesManagerTest : public testing::Test {
public:
UrlRequestRewriteRulesManagerTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
url_request_rewrite_rules_manager_(
UrlRequestRewriteRulesManager::CreateForTesting()) {}
~UrlRequestRewriteRulesManagerTest() override = default;
protected:
zx_status_t UpdateRulesFromRewrite(fuchsia::web::UrlRequestRewrite rewrite) {
std::vector<fuchsia::web::UrlRequestRewrite> rewrites;
rewrites.push_back(std::move(rewrite));
fuchsia::web::UrlRequestRewriteRule rule;
rule.set_rewrites(std::move(rewrites));
std::vector<fuchsia::web::UrlRequestRewriteRule> rules;
rules.push_back(std::move(rule));
return url_request_rewrite_rules_manager_->OnRulesUpdated(std::move(rules),
[]() {});
}
base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<UrlRequestRewriteRulesManager>
url_request_rewrite_rules_manager_;
DISALLOW_COPY_AND_ASSIGN(UrlRequestRewriteRulesManagerTest);
};
// Tests AddHeaders rewrites are properly converted to their Mojo equivalent.
TEST_F(UrlRequestRewriteRulesManagerTest, ConvertAddHeader) {
EXPECT_EQ(UpdateRulesFromRewrite(
cr_fuchsia::CreateRewriteAddHeaders("Test", "Value")),
ZX_OK);
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
ASSERT_EQ(cached_rules->data.size(), 1u);
ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_add_headers());
const net::HttpRequestHeaders& headers =
cached_rules->data[0]->rewrites[0]->get_add_headers()->headers;
ASSERT_EQ(headers.GetHeaderVector().size(), 1u);
std::string value;
ASSERT_TRUE(headers.GetHeader("Test", &value));
ASSERT_EQ(value.compare("Value"), 0);
}
// Tests RemoveHeader rewrites are properly converted to their Mojo equivalent.
TEST_F(UrlRequestRewriteRulesManagerTest, ConvertRemoveHeader) {
EXPECT_EQ(UpdateRulesFromRewrite(cr_fuchsia::CreateRewriteRemoveHeader(
base::make_optional("Test"), "Header")),
ZX_OK);
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
ASSERT_EQ(cached_rules->data.size(), 1u);
ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_remove_header());
const mojom::UrlRequestRewriteRemoveHeaderPtr& remove_header1 =
cached_rules->data[0]->rewrites[0]->get_remove_header();
ASSERT_TRUE(remove_header1->query_pattern);
ASSERT_EQ(remove_header1->query_pattern.value().compare("Test"), 0);
ASSERT_EQ(remove_header1->header_name.compare("Header"), 0);
// Create a RemoveHeader rewrite with no pattern.
EXPECT_EQ(UpdateRulesFromRewrite(
cr_fuchsia::CreateRewriteRemoveHeader(base::nullopt, "Header")),
ZX_OK);
cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
ASSERT_EQ(cached_rules->data.size(), 1u);
ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_remove_header());
const mojom::UrlRequestRewriteRemoveHeaderPtr& remove_header2 =
cached_rules->data[0]->rewrites[0]->get_remove_header();
ASSERT_FALSE(remove_header2->query_pattern);
ASSERT_EQ(remove_header2->header_name.compare("Header"), 0);
}
// Tests SubstituteQueryPattern rewrites are properly converted to their Mojo
// equivalent.
TEST_F(UrlRequestRewriteRulesManagerTest, ConvertSubstituteQueryPattern) {
EXPECT_EQ(
UpdateRulesFromRewrite(cr_fuchsia::CreateRewriteSubstituteQueryPattern(
"Pattern", "Substitution")),
ZX_OK);
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
ASSERT_EQ(cached_rules->data.size(), 1u);
ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
ASSERT_TRUE(
cached_rules->data[0]->rewrites[0]->is_substitute_query_pattern());
const mojom::UrlRequestRewriteSubstituteQueryPatternPtr&
substitute_query_pattern =
cached_rules->data[0]->rewrites[0]->get_substitute_query_pattern();
ASSERT_EQ(substitute_query_pattern->pattern.compare("Pattern"), 0);
ASSERT_EQ(substitute_query_pattern->substitution.compare("Substitution"), 0);
}
// Tests ReplaceUrl rewrites are properly converted to their Mojo equivalent.
TEST_F(UrlRequestRewriteRulesManagerTest, ConvertReplaceUrl) {
GURL url("http://site.xyz");
EXPECT_EQ(UpdateRulesFromRewrite(
cr_fuchsia::CreateRewriteReplaceUrl("/something", url.spec())),
ZX_OK);
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
ASSERT_EQ(cached_rules->data.size(), 1u);
ASSERT_FALSE(cached_rules->data[0]->hosts_filter);
ASSERT_FALSE(cached_rules->data[0]->schemes_filter);
ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_replace_url());
const mojom::UrlRequestRewriteReplaceUrlPtr& replace_url =
cached_rules->data[0]->rewrites[0]->get_replace_url();
ASSERT_EQ(replace_url->url_ends_with.compare("/something"), 0);
ASSERT_EQ(replace_url->new_url.spec().compare(url.spec()), 0);
}
// Tests validation is working as expected.
TEST_F(UrlRequestRewriteRulesManagerTest, Validation) {
// Empty rewrite.
EXPECT_EQ(UpdateRulesFromRewrite(fuchsia::web::UrlRequestRewrite()),
ZX_ERR_INVALID_ARGS);
// Invalid AddHeaders header name.
EXPECT_EQ(UpdateRulesFromRewrite(
cr_fuchsia::CreateRewriteAddHeaders("Te\nst1", "Value")),
ZX_ERR_INVALID_ARGS);
// Invalid AddHeaders header value.
EXPECT_EQ(UpdateRulesFromRewrite(
cr_fuchsia::CreateRewriteAddHeaders("Test1", "Val\nue")),
ZX_ERR_INVALID_ARGS);
// Empty AddHeaders.
{
fuchsia::web::UrlRequestRewrite rewrite;
rewrite.set_add_headers(fuchsia::web::UrlRequestRewriteAddHeaders());
EXPECT_EQ(UpdateRulesFromRewrite(std::move(rewrite)), ZX_ERR_INVALID_ARGS);
}
// Invalid RemoveHeader header name.
EXPECT_EQ(UpdateRulesFromRewrite(
cr_fuchsia::CreateRewriteRemoveHeader("Query", "Head\ner")),
ZX_ERR_INVALID_ARGS);
// Empty RemoveHeader.
{
fuchsia::web::UrlRequestRewrite rewrite;
rewrite.set_add_headers(fuchsia::web::UrlRequestRewriteAddHeaders());
EXPECT_EQ(UpdateRulesFromRewrite(std::move(rewrite)), ZX_ERR_INVALID_ARGS);
}
// Empty SubstituteQueryPattern.
{
fuchsia::web::UrlRequestRewrite rewrite;
rewrite.set_substitute_query_pattern(
fuchsia::web::UrlRequestRewriteSubstituteQueryPattern());
EXPECT_EQ(UpdateRulesFromRewrite(std::move(rewrite)), ZX_ERR_INVALID_ARGS);
}
// Invalid ReplaceUrl url_ends_with.
EXPECT_EQ(UpdateRulesFromRewrite(cr_fuchsia::CreateRewriteReplaceUrl(
"some%00thing", GURL("http://site.xyz").spec())),
ZX_ERR_INVALID_ARGS);
// Invalid ReplaceUrl new_url.
EXPECT_EQ(UpdateRulesFromRewrite(cr_fuchsia::CreateRewriteReplaceUrl(
"/something", "http:site:xyz")),
ZX_ERR_INVALID_ARGS);
// Empty ReplaceUrl.
{
fuchsia::web::UrlRequestRewrite rewrite;
rewrite.set_replace_url(fuchsia::web::UrlRequestRewriteReplaceUrl());
EXPECT_EQ(UpdateRulesFromRewrite(std::move(rewrite)), ZX_ERR_INVALID_ARGS);
}
}
// Tests rules are properly renewed after new rules are sent.
TEST_F(UrlRequestRewriteRulesManagerTest, RuleRenewal) {
EXPECT_EQ(UpdateRulesFromRewrite(
cr_fuchsia::CreateRewriteAddHeaders("Test1", "Value")),
ZX_OK);
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
ASSERT_EQ(cached_rules->data.size(), 1u);
ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_add_headers());
ASSERT_TRUE(
cached_rules->data[0]->rewrites[0]->get_add_headers()->headers.HasHeader(
"Test1"));
EXPECT_EQ(UpdateRulesFromRewrite(
cr_fuchsia::CreateRewriteAddHeaders("Test2", "Value")),
ZX_OK);
// We should have the new rules.
cached_rules = url_request_rewrite_rules_manager_->GetCachedRules();
ASSERT_EQ(cached_rules->data.size(), 1u);
ASSERT_EQ(cached_rules->data[0]->rewrites.size(), 1u);
ASSERT_TRUE(cached_rules->data[0]->rewrites[0]->is_add_headers());
ASSERT_TRUE(
cached_rules->data[0]->rewrites[0]->get_add_headers()->headers.HasHeader(
"Test2"));
}
...@@ -11,10 +11,12 @@ ...@@ -11,10 +11,12 @@
#include "components/version_info/version_info.h" #include "components/version_info/version_info.h"
#include "content/public/common/user_agent.h" #include "content/public/common/user_agent.h"
#include "content/public/common/web_preferences.h" #include "content/public/common/web_preferences.h"
#include "fuchsia/engine/browser/url_request_rewrite_rules_manager.h"
#include "fuchsia/engine/browser/web_engine_browser_context.h" #include "fuchsia/engine/browser/web_engine_browser_context.h"
#include "fuchsia/engine/browser/web_engine_browser_main_parts.h" #include "fuchsia/engine/browser/web_engine_browser_main_parts.h"
#include "fuchsia/engine/browser/web_engine_devtools_manager_delegate.h" #include "fuchsia/engine/browser/web_engine_devtools_manager_delegate.h"
#include "fuchsia/engine/common.h" #include "fuchsia/engine/common.h"
#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
#include "fuchsia/engine/switches.h" #include "fuchsia/engine/switches.h"
WebEngineContentBrowserClient::WebEngineContentBrowserClient( WebEngineContentBrowserClient::WebEngineContentBrowserClient(
...@@ -104,3 +106,28 @@ void WebEngineContentBrowserClient::AppendExtraCommandLineSwitches( ...@@ -104,3 +106,28 @@ void WebEngineContentBrowserClient::AppendExtraCommandLineSwitches(
command_line->AppendSwitch(switches::kDisableSoftwareVideoDecoders); command_line->AppendSwitch(switches::kDisableSoftwareVideoDecoders);
} }
} }
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
WebEngineContentBrowserClient::CreateURLLoaderThrottles(
const network::ResourceRequest& request,
content::BrowserContext* browser_context,
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id) {
if (frame_tree_node_id == content::RenderFrameHost::kNoFrameTreeNodeId) {
// TODO(crbug.com/976975): Add support for service workers.
return {};
}
UrlRequestRewriteRulesManager* adapter =
UrlRequestRewriteRulesManager::ForFrameTreeNodeId(frame_tree_node_id);
if (!adapter) {
// No popup support for rules rewriter.
return {};
}
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
throttles.emplace_back(std::make_unique<WebEngineURLLoaderThrottle>(
UrlRequestRewriteRulesManager::ForFrameTreeNodeId(frame_tree_node_id)));
return throttles;
}
...@@ -48,6 +48,13 @@ class WebEngineContentBrowserClient : public content::ContentBrowserClient { ...@@ -48,6 +48,13 @@ class WebEngineContentBrowserClient : public content::ContentBrowserClient {
NonNetworkURLLoaderFactoryMap* factories) final; NonNetworkURLLoaderFactoryMap* factories) final;
void AppendExtraCommandLineSwitches(base::CommandLine* command_line, void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
int child_process_id) final; int child_process_id) final;
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
CreateURLLoaderThrottles(
const network::ResourceRequest& request,
content::BrowserContext* browser_context,
const base::RepeatingCallback<content::WebContents*()>& wc_getter,
content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id) final;
private: private:
fidl::InterfaceRequest<fuchsia::web::Context> request_; fidl::InterfaceRequest<fuchsia::web::Context> request_;
......
include_rules = [
"+third_party/blink/public/common/loader",
]
// 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 "fuchsia/engine/common/web_engine_url_loader_throttle.h"
#include "base/strings/string_util.h"
namespace {
// Returnns a string representing the URL stripped of query and ref.
std::string ClearUrlQueryRef(const GURL& url) {
GURL::Replacements replacements;
replacements.ClearQuery();
replacements.ClearRef();
return url.ReplaceComponents(replacements).spec();
}
void ApplyAddHeaders(network::ResourceRequest* request,
const mojom::UrlRequestRewriteAddHeadersPtr& add_headers) {
request->headers.MergeFrom(add_headers->headers);
}
void ApplyRemoveHeader(
network::ResourceRequest* request,
const mojom::UrlRequestRewriteRemoveHeaderPtr& remove_header) {
base::Optional<std::string> query_pattern = remove_header->query_pattern;
if (query_pattern &&
request->url.query().find(query_pattern.value()) == std::string::npos) {
return;
}
request->headers.RemoveHeader(remove_header->header_name);
}
void ApplySubstituteQueryPattern(
network::ResourceRequest* request,
const mojom::UrlRequestRewriteSubstituteQueryPatternPtr&
substitute_query_pattern) {
std::string url_query = request->url.query();
base::ReplaceSubstringsAfterOffset(&url_query, 0,
substitute_query_pattern->pattern,
substitute_query_pattern->substitution);
GURL::Replacements replacements;
replacements.SetQueryStr(url_query);
request->url = request->url.ReplaceComponents(replacements);
}
void ApplyReplaceUrl(network::ResourceRequest* request,
const mojom::UrlRequestRewriteReplaceUrlPtr& replace_url) {
if (!base::EndsWith(ClearUrlQueryRef(request->url),
replace_url->url_ends_with, base::CompareCase::SENSITIVE))
return;
GURL new_url = replace_url->new_url;
if (new_url.has_scheme() &&
new_url.scheme().compare(request->url.scheme()) != 0) {
// No cross-scheme redirect allowed.
return;
}
GURL::Replacements replacements;
std::string host = new_url.host();
replacements.SetHostStr(host);
std::string port = new_url.port();
replacements.SetPortStr(port);
std::string path = new_url.path();
replacements.SetPathStr(path);
request->url = request->url.ReplaceComponents(replacements);
}
void ApplyRewrite(network::ResourceRequest* request,
const mojom::UrlRequestRewritePtr& rewrite) {
switch (rewrite->which()) {
case mojom::UrlRequestRewrite::Tag::ADD_HEADERS:
ApplyAddHeaders(request, rewrite->get_add_headers());
break;
case mojom::UrlRequestRewrite::Tag::REMOVE_HEADER:
ApplyRemoveHeader(request, rewrite->get_remove_header());
break;
case mojom::UrlRequestRewrite::Tag::SUBSTITUTE_QUERY_PATTERN:
ApplySubstituteQueryPattern(request,
rewrite->get_substitute_query_pattern());
break;
case mojom::UrlRequestRewrite::Tag::REPLACE_URL:
ApplyReplaceUrl(request, rewrite->get_replace_url());
break;
}
}
void ApplyRule(network::ResourceRequest* request,
const mojom::UrlRequestRewriteRulePtr& rule) {
const GURL& url = request->url;
if (rule->hosts_filter) {
bool found = false;
for (const auto& host : rule->hosts_filter.value()) {
if (url.host().compare(host) == 0) {
found = true;
break;
}
}
if (!found)
return;
}
if (rule->schemes_filter) {
bool found = false;
for (const auto& scheme : rule->schemes_filter.value()) {
if (url.scheme().compare(scheme) == 0) {
found = true;
break;
}
}
if (!found)
return;
}
for (const auto& rewrite : rule->rewrites) {
ApplyRewrite(request, rewrite);
}
}
void ApplyRules(network::ResourceRequest* request,
const std::vector<mojom::UrlRequestRewriteRulePtr>& rules) {
for (const auto& rule : rules) {
ApplyRule(request, rule);
}
}
} // namespace
WebEngineURLLoaderThrottle::WebEngineURLLoaderThrottle(
CachedRulesProvider* cached_rules_provider)
: cached_rules_provider_(cached_rules_provider) {
DCHECK(cached_rules_provider);
}
WebEngineURLLoaderThrottle::~WebEngineURLLoaderThrottle() = default;
void WebEngineURLLoaderThrottle::DetachFromCurrentSequence() {}
void WebEngineURLLoaderThrottle::WillStartRequest(
network::ResourceRequest* request,
bool* defer) {
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
cached_rules = cached_rules_provider_->GetCachedRules();
// |cached_rules| may be empty if no rule was ever sent to WebEngine.
if (cached_rules)
ApplyRules(request, cached_rules->data);
*defer = false;
}
bool WebEngineURLLoaderThrottle::makes_unsafe_redirect() {
// WillStartRequest() does not make cross-scheme redirects.
return false;
}
// 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 FUCHSIA_ENGINE_COMMON_WEB_ENGINE_URL_LOADER_THROTTLE_H_
#define FUCHSIA_ENGINE_COMMON_WEB_ENGINE_URL_LOADER_THROTTLE_H_
#include <vector>
#include "base/memory/ref_counted.h"
#include "fuchsia/engine/url_request_rewrite.mojom.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
// Implements a URLLoaderThrottle for the WebEngine. Applies network request
// rewrites provided through the fuchsia.web.SetUrlRequestRewriteRules FIDL API.
class WebEngineURLLoaderThrottle : public blink::URLLoaderThrottle {
public:
using UrlRequestRewriteRules =
base::RefCountedData<std::vector<mojom::UrlRequestRewriteRulePtr>>;
// An interface to provide rewrite rules to the throttle. Its
// implementation must outlive the WebEngineURLLoaderThrottle.
class CachedRulesProvider {
public:
virtual ~CachedRulesProvider() = default;
// Gets cached rules. This call can be made on any sequence, as
// URLLoaderThrottles are not guaranteed to stay on the same sequence.
virtual scoped_refptr<UrlRequestRewriteRules> GetCachedRules() = 0;
};
explicit WebEngineURLLoaderThrottle(
CachedRulesProvider* cached_rules_provider);
~WebEngineURLLoaderThrottle() override;
private:
// blink::URLLoaderThrottle implementation.
void DetachFromCurrentSequence() override;
void WillStartRequest(network::ResourceRequest* request,
bool* defer) override;
bool makes_unsafe_redirect() override;
CachedRulesProvider* const cached_rules_provider_;
DISALLOW_COPY_AND_ASSIGN(WebEngineURLLoaderThrottle);
};
#endif // FUCHSIA_ENGINE_COMMON_WEB_ENGINE_URL_LOADER_THROTTLE_H_
// 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 "fuchsia/engine/renderer/url_request_rules_receiver.h"
#include "content/public/renderer/render_frame.h"
#include "fuchsia/engine/renderer/web_engine_content_renderer_client.h"
#include "fuchsia/engine/url_request_rewrite.mojom.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
UrlRequestRulesReceiver::UrlRequestRulesReceiver(
content::RenderFrame* render_frame,
base::OnceCallback<void(int)> on_render_frame_deleted_callback)
: content::RenderFrameObserver(render_frame),
associated_binding_(this),
on_render_frame_deleted_callback_(
std::move(on_render_frame_deleted_callback)) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(on_render_frame_deleted_callback_);
DCHECK(render_frame);
// It is fine to use an unretained pointer to |this| here as the
// AssociatedInterfaceRegistry, owned by |render_frame| will be torn-down at
// the same time as |this|.
render_frame->GetAssociatedInterfaceRegistry()->AddInterface(
base::BindRepeating(
&UrlRequestRulesReceiver::OnUrlRequestRulesReceiverAssociatedRequest,
base::Unretained(this)));
}
UrlRequestRulesReceiver::~UrlRequestRulesReceiver() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void UrlRequestRulesReceiver::OnUrlRequestRulesReceiverAssociatedRequest(
mojom::UrlRequestRulesReceiverAssociatedRequest request) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!associated_binding_.is_bound());
associated_binding_.Bind(std::move(request));
}
void UrlRequestRulesReceiver::OnRulesUpdated(
std::vector<mojom::UrlRequestRewriteRulePtr> rules) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
base::AutoLock auto_lock(lock_);
cached_rules_ =
base::MakeRefCounted<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>(
std::move(rules));
}
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
UrlRequestRulesReceiver::GetCachedRules() {
base::AutoLock auto_lock(lock_);
return cached_rules_;
}
void UrlRequestRulesReceiver::OnDestruct() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// The RenderFrame corresponding to this object was destroyed, which means
// the AssociatedInterfaceRegsitry is also gone. It is expected that
// |on_render_frame_deleted_callback_| will delete |this|.
std::move(on_render_frame_deleted_callback_).Run(routing_id());
}
// 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 FUCHSIA_ENGINE_RENDERER_URL_REQUEST_RULES_RECEIVER_H_
#define FUCHSIA_ENGINE_RENDERER_URL_REQUEST_RULES_RECEIVER_H_
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "content/public/renderer/render_frame_observer.h"
#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
#include "fuchsia/engine/url_request_rewrite.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "services/service_manager/public/cpp/binder_registry.h"
namespace content {
class RenderFrame;
} // namespace content
// Provides rewriting rules for network requests. UrlRequestRulesReceiver
// objects are owned by their respective WebEngineContentRendererClient and they
// will be destroyed on RenderFrame destruction. This is guaranteed to outlive
// any WebEngineURLLoaderThrottle that uses it as the RenderFrame destruction
// will have triggered the destruction of all pending
// WebEngineURLLoaderThrottles.
// This class should only be used on the IO thread, with the exception of the
// GetCachedRules() implementation, which can be called from any sequence.
class UrlRequestRulesReceiver
: public mojom::UrlRequestRulesReceiver,
public WebEngineURLLoaderThrottle::CachedRulesProvider,
public content::RenderFrameObserver {
public:
UrlRequestRulesReceiver(
content::RenderFrame* render_frame,
base::OnceCallback<void(int)> on_render_frame_deleted_callback);
~UrlRequestRulesReceiver() override;
private:
void OnUrlRequestRulesReceiverAssociatedRequest(
mojom::UrlRequestRulesReceiverAssociatedRequest request);
// mojom::UrlRequestRulesReceiver implementation.
void OnRulesUpdated(
std::vector<mojom::UrlRequestRewriteRulePtr> rules) override;
// WebEngineURLLoaderThrottle::CachedRulesProvider implementation.
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
GetCachedRules() override;
// content::RenderFrameObserver implementation.
void OnDestruct() override;
base::Lock lock_;
// This is accessed by WebEngineURLLoaderThrottles, which can be off-sequence
// in the case of synchronous network requests.
scoped_refptr<WebEngineURLLoaderThrottle::UrlRequestRewriteRules>
cached_rules_ GUARDED_BY(lock_);
mojo::AssociatedBinding<mojom::UrlRequestRulesReceiver> associated_binding_;
base::OnceCallback<void(int)> on_render_frame_deleted_callback_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(UrlRequestRulesReceiver);
};
#endif // FUCHSIA_ENGINE_RENDERER_URL_REQUEST_RULES_RECEIVER_H_
...@@ -4,13 +4,16 @@ ...@@ -4,13 +4,16 @@
#include "fuchsia/engine/renderer/web_engine_content_renderer_client.h" #include "fuchsia/engine/renderer/web_engine_content_renderer_client.h"
#include "base/feature_list.h"
#include "base/macros.h" #include "base/macros.h"
#include "components/cdm/renderer/widevine_key_system_properties.h" #include "components/cdm/renderer/widevine_key_system_properties.h"
#include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_frame.h"
#include "fuchsia/engine/renderer/on_load_script_injector.h" #include "fuchsia/engine/renderer/on_load_script_injector.h"
#include "fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.h"
#include "fuchsia/engine/switches.h" #include "fuchsia/engine/switches.h"
#include "media/base/eme_constants.h" #include "media/base/eme_constants.h"
#include "media/base/video_codecs.h" #include "media/base/video_codecs.h"
#include "services/network/public/cpp/features.h"
#include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/binder_registry.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/widevine/cdm/widevine_cdm_common.h" #include "third_party/widevine/cdm/widevine_cdm_common.h"
...@@ -19,11 +22,45 @@ WebEngineContentRendererClient::WebEngineContentRendererClient() = default; ...@@ -19,11 +22,45 @@ WebEngineContentRendererClient::WebEngineContentRendererClient() = default;
WebEngineContentRendererClient::~WebEngineContentRendererClient() = default; WebEngineContentRendererClient::~WebEngineContentRendererClient() = default;
UrlRequestRulesReceiver*
WebEngineContentRendererClient::GetUrlRequestRulesReceiverForRenderFrameId(
int render_frame_id) const {
auto iter = url_request_receivers_by_id_.find(render_frame_id);
DCHECK(iter != url_request_receivers_by_id_.end());
return iter->second.get();
}
void WebEngineContentRendererClient::OnRenderFrameDeleted(int render_frame_id) {
size_t count = url_request_receivers_by_id_.erase(render_frame_id);
DCHECK_EQ(count, 1u);
}
void WebEngineContentRendererClient::RenderFrameCreated( void WebEngineContentRendererClient::RenderFrameCreated(
content::RenderFrame* render_frame) { content::RenderFrame* render_frame) {
// Add WebEngine services to the new RenderFrame. // Add WebEngine services to the new RenderFrame.
// The objects' lifetimes are bound to the RenderFrame's lifetime. // The objects' lifetimes are bound to the RenderFrame's lifetime.
new OnLoadScriptInjector(render_frame); new OnLoadScriptInjector(render_frame);
int render_frame_id = render_frame->GetRoutingID();
auto rules_receiver = std::make_unique<UrlRequestRulesReceiver>(
content::RenderFrame::FromRoutingID(render_frame_id),
base::BindOnce(&WebEngineContentRendererClient::OnRenderFrameDeleted,
base::Unretained(this)));
auto iter = url_request_receivers_by_id_.emplace(render_frame_id,
std::move(rules_receiver));
DCHECK(iter.second);
}
std::unique_ptr<content::URLLoaderThrottleProvider>
WebEngineContentRendererClient::CreateURLLoaderThrottleProvider(
content::URLLoaderThrottleProviderType type) {
DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
// TODO(crbug.com/976975): Add support for service workers.
if (type == content::URLLoaderThrottleProviderType::kWorker)
return nullptr;
return std::make_unique<WebEngineURLLoaderThrottleProvider>(this);
} }
void WebEngineContentRendererClient::AddSupportedKeySystems( void WebEngineContentRendererClient::AddSupportedKeySystems(
......
...@@ -7,20 +7,36 @@ ...@@ -7,20 +7,36 @@
#include "base/macros.h" #include "base/macros.h"
#include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/content_renderer_client.h"
#include "fuchsia/engine/renderer/url_request_rules_receiver.h"
class WebEngineContentRendererClient : public content::ContentRendererClient { class WebEngineContentRendererClient : public content::ContentRendererClient {
public: public:
WebEngineContentRendererClient(); WebEngineContentRendererClient();
~WebEngineContentRendererClient() override; ~WebEngineContentRendererClient() override;
// Returns the UrlRequestRulesReceiver corresponding to |render_frame_id|.
UrlRequestRulesReceiver* GetUrlRequestRulesReceiverForRenderFrameId(
int render_frame_id) const;
private:
// Called by UrlRequestRulesReceivers when their corresponding RenderFrame is
// in the process of being deleted.
void OnRenderFrameDeleted(int render_frame_id);
// content::ContentRendererClient overrides. // content::ContentRendererClient overrides.
void RenderFrameCreated(content::RenderFrame* render_frame) override; void RenderFrameCreated(content::RenderFrame* render_frame) override;
void AddSupportedKeySystems( void AddSupportedKeySystems(
std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems)
override; override;
bool IsSupportedVideoType(const media::VideoType& type) override; bool IsSupportedVideoType(const media::VideoType& type) override;
std::unique_ptr<content::URLLoaderThrottleProvider>
CreateURLLoaderThrottleProvider(
content::URLLoaderThrottleProviderType type) override;
// Map of rules receivers per RenderFrame ID.
std::map<int, std::unique_ptr<UrlRequestRulesReceiver>>
url_request_receivers_by_id_;
private:
DISALLOW_COPY_AND_ASSIGN(WebEngineContentRendererClient); DISALLOW_COPY_AND_ASSIGN(WebEngineContentRendererClient);
}; };
......
// 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 "fuchsia/engine/renderer/web_engine_url_loader_throttle_provider.h"
#include "content/public/renderer/render_frame.h"
#include "fuchsia/engine/common/web_engine_url_loader_throttle.h"
#include "fuchsia/engine/renderer/web_engine_content_renderer_client.h"
WebEngineURLLoaderThrottleProvider::WebEngineURLLoaderThrottleProvider(
WebEngineContentRendererClient* content_renderer_client)
: content_renderer_client_(content_renderer_client) {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
WebEngineURLLoaderThrottleProvider::~WebEngineURLLoaderThrottleProvider() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
std::unique_ptr<content::URLLoaderThrottleProvider>
WebEngineURLLoaderThrottleProvider::Clone() {
// This should only happen for service workers, which we do not support here.
NOTREACHED();
return nullptr;
}
std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
WebEngineURLLoaderThrottleProvider::CreateThrottles(
int render_frame_id,
const blink::WebURLRequest& request,
content::ResourceType resource_type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
throttles.emplace_back(std::make_unique<WebEngineURLLoaderThrottle>(
content_renderer_client_->GetUrlRequestRulesReceiverForRenderFrameId(
render_frame_id)));
return throttles;
}
void WebEngineURLLoaderThrottleProvider::SetOnline(bool is_online) {}
// 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 FUCHSIA_ENGINE_RENDERER_WEB_ENGINE_URL_LOADER_THROTTLE_PROVIDER_H_
#define FUCHSIA_ENGINE_RENDERER_WEB_ENGINE_URL_LOADER_THROTTLE_PROVIDER_H_
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "content/public/renderer/url_loader_throttle_provider.h"
class WebEngineContentRendererClient;
// Implements a URLLoaderThrottleProvider for the WebEngine. Creates
// URLLoaderThrottles, implemented as WebEngineURLLoaderThrottles for network
// requests.
class WebEngineURLLoaderThrottleProvider
: public content::URLLoaderThrottleProvider {
public:
explicit WebEngineURLLoaderThrottleProvider(
WebEngineContentRendererClient* content_renderer_client);
~WebEngineURLLoaderThrottleProvider() override;
// content::URLLoaderThrottleProvider implementation.
std::unique_ptr<content::URLLoaderThrottleProvider> Clone() override;
std::vector<std::unique_ptr<blink::URLLoaderThrottle>> CreateThrottles(
int render_frame_id,
const blink::WebURLRequest& request,
content::ResourceType resource_type) override;
void SetOnline(bool is_online) override;
private:
const WebEngineContentRendererClient* const content_renderer_client_;
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(WebEngineURLLoaderThrottleProvider);
};
#endif // FUCHSIA_ENGINE_RENDERER_WEB_ENGINE_URL_LOADER_THROTTLE_PROVIDER_H_
<html>
<head><title>Image</title></head>
<body><img src="/img.png"></body>
</html>
// 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.
module mojom;
import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/http_request_headers.mojom";
import "url/mojom/url.mojom";
// Used by the browser to push URL rewrite rules to renderers. There will be
// one receiver per web frame.
// TODO(https://crbug.com/976975): Support URL rewriting for service workers.
interface UrlRequestRulesReceiver {
// Receives a set of rules to apply to URL requests.
OnRulesUpdated(array<UrlRequestRewriteRule> rules);
};
// A URL request rewrite rule.
struct UrlRequestRewriteRule {
// Set of hosts to apply the rewrites to. If empty, the rule will apply to
// every request, independent of host.
array<string>? hosts_filter;
// Set of schemes to apply the rewrites to. If empty, the rule will apply to
// every request, independent of scheme.
array<string>? schemes_filter;
// URL request rewrites to apply.
array<UrlRequestRewrite> rewrites;
};
union UrlRequestRewrite {
// Adds a set of headers to a URL request.
UrlRequestRewriteAddHeaders add_headers;
// Removes a header based on the presence of a pattern in the URL query.
UrlRequestRewriteRemoveHeader remove_header;
// Substitutes a pattern in the URL query.
UrlRequestRewriteSubstituteQueryPattern substitute_query_pattern;
// Replaces a URL if the original URL ends with a pattern.
UrlRequestRewriteReplaceUrl replace_url;
};
// Adds |headers| to the URL request. If a header is already present in the
// original URL request, it will be overwritten.
struct UrlRequestRewriteAddHeaders {
// The headers to add.
network.mojom.HttpRequestHeaders headers;
};
// If |query_pattern| in the URL query, removes |header_name| from the list of
// headers. If |query_pattern| is empty, removes |header_name| from the list
// of headers unconditionally
struct UrlRequestRewriteRemoveHeader {
// The pattern to look for in the URL request.
string? query_pattern;
// The header to remove.
string header_name;
};
// If |pattern| is found in the URL request query, replaces it with
// |substitution|.
struct UrlRequestRewriteSubstituteQueryPattern {
// The pattern to look for in the URL request.
string pattern;
// The string to repalce |pattern| with.
string substitution;
};
// If the URL in the URL request ends with |url_ends_with|, rewrites the URL to
// |new_url|.
struct UrlRequestRewriteReplaceUrl {
// The pattern to look for in the URL.
string url_ends_with;
// The replacement URL.
url.mojom.Url new_url;
};
// 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 "fuchsia/engine/url_request_rewrite_type_converters.h"
namespace mojo {
mojom::UrlRequestRewriteAddHeadersPtr
TypeConverter<mojom::UrlRequestRewriteAddHeadersPtr,
fuchsia::web::UrlRequestRewriteAddHeaders>::
Convert(const fuchsia::web::UrlRequestRewriteAddHeaders& input) {
mojom::UrlRequestRewriteAddHeadersPtr add_headers =
mojom::UrlRequestRewriteAddHeaders::New();
if (input.has_headers()) {
for (const auto& header : input.headers()) {
base::StringPiece header_name = cr_fuchsia::BytesAsString(header.name);
base::StringPiece header_value = cr_fuchsia::BytesAsString(header.value);
add_headers->headers.SetHeader(header_name, header_value);
}
}
return add_headers;
}
mojom::UrlRequestRewriteRemoveHeaderPtr
TypeConverter<mojom::UrlRequestRewriteRemoveHeaderPtr,
fuchsia::web::UrlRequestRewriteRemoveHeader>::
Convert(const fuchsia::web::UrlRequestRewriteRemoveHeader& input) {
mojom::UrlRequestRewriteRemoveHeaderPtr remove_header =
mojom::UrlRequestRewriteRemoveHeader::New();
if (input.has_query_pattern())
remove_header->query_pattern = base::make_optional(input.query_pattern());
if (input.has_header_name())
remove_header->header_name =
cr_fuchsia::BytesAsString(input.header_name()).as_string();
return remove_header;
}
mojom::UrlRequestRewriteSubstituteQueryPatternPtr
TypeConverter<mojom::UrlRequestRewriteSubstituteQueryPatternPtr,
fuchsia::web::UrlRequestRewriteSubstituteQueryPattern>::
Convert(
const fuchsia::web::UrlRequestRewriteSubstituteQueryPattern& input) {
mojom::UrlRequestRewriteSubstituteQueryPatternPtr substitute_query_pattern =
mojom::UrlRequestRewriteSubstituteQueryPattern::New();
if (input.has_pattern())
substitute_query_pattern->pattern = input.pattern();
if (input.has_substitution())
substitute_query_pattern->substitution = input.substitution();
return substitute_query_pattern;
}
mojom::UrlRequestRewriteReplaceUrlPtr
TypeConverter<mojom::UrlRequestRewriteReplaceUrlPtr,
fuchsia::web::UrlRequestRewriteReplaceUrl>::
Convert(const fuchsia::web::UrlRequestRewriteReplaceUrl& input) {
mojom::UrlRequestRewriteReplaceUrlPtr replace_url =
mojom::UrlRequestRewriteReplaceUrl::New();
if (input.has_url_ends_with())
replace_url->url_ends_with = input.url_ends_with();
if (input.has_new_url())
replace_url->new_url = GURL(input.new_url());
return replace_url;
}
mojom::UrlRequestRewritePtr
TypeConverter<mojom::UrlRequestRewritePtr, fuchsia::web::UrlRequestRewrite>::
Convert(const fuchsia::web::UrlRequestRewrite& input) {
switch (input.Which()) {
case fuchsia::web::UrlRequestRewrite::Tag::kAddHeaders:
return mojom::UrlRequestRewrite::NewAddHeaders(
mojo::ConvertTo<mojom::UrlRequestRewriteAddHeadersPtr>(
input.add_headers()));
case fuchsia::web::UrlRequestRewrite::Tag::kRemoveHeader:
return mojom::UrlRequestRewrite::NewRemoveHeader(
mojo::ConvertTo<mojom::UrlRequestRewriteRemoveHeaderPtr>(
input.remove_header()));
case fuchsia::web::UrlRequestRewrite::Tag::kSubstituteQueryPattern:
return mojom::UrlRequestRewrite::NewSubstituteQueryPattern(
mojo::ConvertTo<mojom::UrlRequestRewriteSubstituteQueryPatternPtr>(
input.substitute_query_pattern()));
case fuchsia::web::UrlRequestRewrite::Tag::kReplaceUrl:
return mojom::UrlRequestRewrite::NewReplaceUrl(
mojo::ConvertTo<mojom::UrlRequestRewriteReplaceUrlPtr>(
input.replace_url()));
default:
// This is to prevent build breakage when adding new rewrites to the FIDL
// definition.
NOTREACHED();
return nullptr;
}
}
mojom::UrlRequestRewriteRulePtr
TypeConverter<mojom::UrlRequestRewriteRulePtr,
fuchsia::web::UrlRequestRewriteRule>::
Convert(const fuchsia::web::UrlRequestRewriteRule& input) {
mojom::UrlRequestRewriteRulePtr rule = mojom::UrlRequestRewriteRule::New();
if (input.has_hosts_filter())
rule->hosts_filter = base::make_optional(input.hosts_filter());
if (input.has_schemes_filter())
rule->schemes_filter = base::make_optional(input.schemes_filter());
if (input.has_rewrites())
rule->rewrites = mojo::ConvertTo<std::vector<mojom::UrlRequestRewritePtr>>(
input.rewrites());
return rule;
}
} // namespace mojo
// 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 FUCHSIA_ENGINE_URL_REQUEST_REWRITE_TYPE_CONVERTERS_H_
#define FUCHSIA_ENGINE_URL_REQUEST_REWRITE_TYPE_CONVERTERS_H_
#include <fuchsia/web/cpp/fidl.h>
#include "fuchsia/base/string_util.h"
#include "fuchsia/engine/url_request_rewrite.mojom.h"
#include "mojo/public/cpp/bindings/type_converter.h"
namespace mojo {
template <>
struct TypeConverter<mojom::UrlRequestRewriteAddHeadersPtr,
fuchsia::web::UrlRequestRewriteAddHeaders> {
static mojom::UrlRequestRewriteAddHeadersPtr Convert(
const fuchsia::web::UrlRequestRewriteAddHeaders& input);
};
template <>
struct TypeConverter<mojom::UrlRequestRewriteRemoveHeaderPtr,
fuchsia::web::UrlRequestRewriteRemoveHeader> {
static mojom::UrlRequestRewriteRemoveHeaderPtr Convert(
const fuchsia::web::UrlRequestRewriteRemoveHeader& input);
};
template <>
struct TypeConverter<mojom::UrlRequestRewriteSubstituteQueryPatternPtr,
fuchsia::web::UrlRequestRewriteSubstituteQueryPattern> {
static mojom::UrlRequestRewriteSubstituteQueryPatternPtr Convert(
const fuchsia::web::UrlRequestRewriteSubstituteQueryPattern& input);
};
template <>
struct TypeConverter<mojom::UrlRequestRewriteReplaceUrlPtr,
fuchsia::web::UrlRequestRewriteReplaceUrl> {
static mojom::UrlRequestRewriteReplaceUrlPtr Convert(
const fuchsia::web::UrlRequestRewriteReplaceUrl& input);
};
template <>
struct TypeConverter<mojom::UrlRequestRewritePtr,
fuchsia::web::UrlRequestRewrite> {
static mojom::UrlRequestRewritePtr Convert(
const fuchsia::web::UrlRequestRewrite& input);
};
template <>
struct TypeConverter<mojom::UrlRequestRewriteRulePtr,
fuchsia::web::UrlRequestRewriteRule> {
static mojom::UrlRequestRewriteRulePtr Convert(
const fuchsia::web::UrlRequestRewriteRule& input);
};
} // namespace mojo
#endif // FUCHSIA_ENGINE_URL_REQUEST_REWRITE_TYPE_CONVERTERS_H_
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