Commit 6f8f04b4 authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[bindings] Combine OnLoadScriptInjector impls into a shared component.

Consolidates the forked OnLoadScriptInjectors into one single shared
implementation. The shared implementation is a necessary prerequisite
step for developing platform-agnostic bindings browsertests.

* Deletes Fuchsia and Cast specific OnLoadScriptInjectors.
* Moves most browser process logic into a new class
  "OnLoadScriptInjectorHost", to further harmonize the platforms.
* Migrate Mojo interface from ScopedSharedBufferHandle to ReadOnlySharedMemoryRegion.

Merge-With: eureka-internal/432742
Bug: 1113289
Bug: 1060846
Bug: 1103058
Test: cast_shell_browsertests and web_engine_browsertests both pass.
Change-Id: If9fd2c54de08d9bc225771b01cdb32152a95fde8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2286193
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarDavid Dorwin <ddorwin@chromium.org>
Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Reviewed-by: default avatarSharon Yang <yangsharon@chromium.org>
Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795103}
parent 2914c6e6
......@@ -62,6 +62,7 @@ if (is_linux || is_chromeos || is_android) {
":bindings_resources",
"//base",
"//chromecast/browser:public",
"//components/on_load_script_injector/browser",
"//mojo/public/cpp/system",
"//third_party/blink/public/common",
]
......
include_rules = [
"+chromecast/browser",
"+components/cast/api_bindings",
"+components/on_load_script_injector/browser",
"+content/public/common",
"+content/public/test",
"+fuchsia",
......
......@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "chromecast/bindings/grit/resources.h"
#include "components/on_load_script_injector/browser/on_load_script_injector_host.h"
#include "mojo/public/cpp/bindings/connector.h"
#include "ui/base/resource/resource_bundle.h"
......@@ -25,7 +26,15 @@ const char kControlPortConnectMessage[] = "cast.master.connect";
} // namespace
BindingsManagerCast::BindingsManagerCast() : cast_web_contents_(nullptr) {
BindingsManagerCast::BindingsManagerCast(
chromecast::CastWebContents* cast_web_contents)
: cast_web_contents_(cast_web_contents) {
DCHECK(cast_web_contents_);
// TODO(crbug.com/1103058): Remove this when NamedMessagePortConnector is
// added as a Component.
CastWebContents::Observer::Observe(cast_web_contents_);
// NamedMessagePortConnector binding will be injected into page first.
AddBinding(kNamedMessagePortConnectorBindingsId,
ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
......@@ -36,43 +45,8 @@ BindingsManagerCast::~BindingsManagerCast() = default;
void BindingsManagerCast::AddBinding(base::StringPiece binding_name,
base::StringPiece binding_script) {
bindings_by_id_[binding_name.as_string()] = binding_script.as_string();
}
void BindingsManagerCast::AttachToPage(
chromecast::CastWebContents* cast_web_contents) {
DCHECK(!cast_web_contents_) << "AttachToPage() was called twice.";
DCHECK(cast_web_contents);
cast_web_contents_ = cast_web_contents;
CastWebContents::Observer::Observe(cast_web_contents_);
for (const auto& binding : bindings_by_id_) {
LOG(INFO) << "Register bindings for page. bindingId: " << binding.first;
cast_web_contents_->AddBeforeLoadJavaScript(
binding.first /* binding ID */, {"*"}, binding.second /* binding JS */);
}
}
void BindingsManagerCast::OnPageStateChanged(
CastWebContents* cast_web_contents) {
auto page_state = cast_web_contents->page_state();
switch (page_state) {
case CastWebContents::PageState::IDLE:
case CastWebContents::PageState::LOADING:
case CastWebContents::PageState::CLOSED:
return;
case CastWebContents::PageState::DESTROYED:
case CastWebContents::PageState::ERROR:
blink_port_.Reset();
CastWebContents::Observer::Observe(nullptr);
cast_web_contents_ = nullptr;
return;
case CastWebContents::PageState::LOADED:
OnPageLoaded();
return;
}
cast_web_contents_->script_injector()->AddScriptForAllOrigins(
binding_name.as_string(), binding_script);
}
void BindingsManagerCast::OnPageLoaded() {
......@@ -98,6 +72,29 @@ void BindingsManagerCast::OnPageLoaded() {
std::move(message_ports));
}
void BindingsManagerCast::OnPageStateChanged(
CastWebContents* cast_web_contents) {
auto page_state = cast_web_contents->page_state();
switch (page_state) {
case CastWebContents::PageState::LOADING:
cast_web_contents_->InjectScriptsIntoMainFrame();
return;
case CastWebContents::PageState::DESTROYED:
case CastWebContents::PageState::ERROR:
blink_port_.Reset();
CastWebContents::Observer::Observe(nullptr);
cast_web_contents_ = nullptr;
return;
case CastWebContents::PageState::LOADED:
OnPageLoaded();
return;
case CastWebContents::PageState::IDLE:
case CastWebContents::PageState::CLOSED:
return;
}
}
bool BindingsManagerCast::OnMessage(blink::WebMessagePort::Message message) {
// Receive MessagePort and forward ports to their corresponding
// binding handlers.
......
......@@ -23,13 +23,9 @@ class BindingsManagerCast : public BindingsManager,
public CastWebContents::Observer,
public blink::WebMessagePort::MessageReceiver {
public:
BindingsManagerCast();
explicit BindingsManagerCast(chromecast::CastWebContents* cast_web_contents);
~BindingsManagerCast() override;
// Add JS bindings to the page |cast_web_contents_|.
// Start Observing the PageState changes.
void AttachToPage(chromecast::CastWebContents* cast_web_contents);
// The document and its statically-declared subresources are loaded.
// BindingsManagerCast will inject all registered bindings at this time.
// BindingsManagerCast will post a message that conveys an end of MessagePort
......@@ -37,21 +33,20 @@ class BindingsManagerCast : public BindingsManager,
// port to communicate with the native part.
void OnPageLoaded();
// BindingsManager implementation:
// BindingsManager implementation.
void AddBinding(base::StringPiece binding_name,
base::StringPiece binding_script) override;
// CastWebContents::Observer implementation:
private:
// CastWebContents::Observer implementation.
void OnPageStateChanged(CastWebContents* cast_web_contents) override;
private:
// blink::WebMessagePort::MessageReceiver implementation:
bool OnMessage(blink::WebMessagePort::Message message) override;
void OnPipeError() override;
// Stores all bindings, keyed on the string-based IDs.
std::map<std::string, std::string> bindings_by_id_;
chromecast::CastWebContents* cast_web_contents_;
// Receives messages from JS.
blink::WebMessagePort blink_port_;
......
......@@ -290,7 +290,8 @@ class BindingsManagerCastBrowserTest : public content::BrowserTestBase {
cast_web_contents_ =
std::make_unique<CastWebContentsImpl>(web_contents_.get(), init_params);
title_change_observer_.Observe(cast_web_contents_.get());
bindings_manager_ = std::make_unique<bindings::BindingsManagerCast>();
bindings_manager_ = std::make_unique<bindings::BindingsManagerCast>(
cast_web_contents_.get());
}
void PostRunTestOnMainThread() override {
......@@ -345,9 +346,6 @@ IN_PROC_BROWSER_TEST_F(BindingsManagerCastBrowserTest, EndToEnd) {
std::make_unique<TestBindingBackend>(bindings_manager_.get());
// TestBindingBackend test_binding_backend(bindings_manager_.get());
// Attach BindingsManager to the page.
bindings_manager_->AttachToPage(cast_web_contents_.get());
// Load test page.
constexpr char kTestPageTitle[] = "bindings";
cast_web_contents_->LoadUrl(test_url);
......
......@@ -201,6 +201,7 @@ cast_source_set("browser") {
"//components/metrics",
"//components/metrics:content",
"//components/metrics:net",
"//components/on_load_script_injector/browser",
"//components/variations/net",
# TODO(gfhuang): Eliminate this dependency if ScreenInfoMetricsProvider
......
......@@ -23,6 +23,7 @@ include_rules = [
"+components/media_control/mojom",
"+components/network_hints",
"+components/network_session_configurator/common",
"+components/on_load_script_injector/browser",
"+components/policy/core/browser",
"+components/prefs",
"+components/pref_registry",
......
......@@ -27,6 +27,10 @@ namespace blink {
class AssociatedInterfaceProvider;
} // namespace blink
namespace on_load_script_injector {
class OnLoadScriptInjectorHost;
} // namespace on_load_script_injector
namespace content {
class WebContents;
} // namespace content
......@@ -332,29 +336,13 @@ class CastWebContents {
// Page Communication
// ===========================================================================
// Executes a UTF-8 encoded |script| for every subsequent page load where
// the frame's URL has an origin reflected in |origins|. The script is
// executed early, prior to the execution of the document's scripts.
//
// Scripts are identified by a string-based client-managed |id|. Any
// script previously injected using the same |id| will be replaced.
//
// The order in which multiple bindings are executed is the same as the
// order in which the bindings were Added. If a script is added which
// clobbers an existing script of the same |id|, the previous script's
// precedence in the injection order will be preserved.
// |script| and |id| must be non-empty string.
//
// At least one |origins| entry must be specified.
// If a wildcard "*" is specified in |origins|, then the script will be
// evaluated for all documents.
virtual void AddBeforeLoadJavaScript(base::StringPiece id,
const std::vector<std::string>& origins,
base::StringPiece script) = 0;
// Removes a previously added JavaScript snippet identified by |id|.
// This is a no-op if there is no JavaScript snippet identified by |id|.
virtual void RemoveBeforeLoadJavaScript(base::StringPiece id) = 0;
// Returns the script injector instance, which injects scripts at page load
// time.
virtual on_load_script_injector::OnLoadScriptInjectorHost*
script_injector() = 0;
// Injects on-load scripts into the WebContents' main frame.
virtual void InjectScriptsIntoMainFrame() = 0;
// Posts a message to the frame's onMessage handler.
//
......
......@@ -22,7 +22,6 @@
#include "chromecast/browser/devtools/remote_debugging_server.h"
#include "chromecast/browser/queryable_data_host_cast.h"
#include "chromecast/common/mojom/activity_url_filter.mojom.h"
#include "chromecast/common/mojom/on_load_script_injector.mojom.h"
#include "chromecast/common/mojom/queryable_data_store.mojom.h"
#include "chromecast/common/queryable_data.h"
#include "chromecast/net/connectivity_checker.h"
......@@ -64,24 +63,6 @@ void RemoveCastWebContents(CastWebContents* instance) {
}
}
bool IsOriginWhitelisted(const GURL& url,
const std::vector<std::string>& allowed_origins) {
constexpr const char kWildcard[] = "*";
url::Origin url_origin = url::Origin::Create(url);
for (const std::string& allowed_origin : allowed_origins) {
if (allowed_origin == kWildcard)
return true;
if (url_origin.IsSameOriginWith(url::Origin::Create(GURL(allowed_origin))))
return true;
// TODO(crbug.com/893236): Add handling for nonstandard origins
// (e.g. data: URIs).
}
return false;
}
} // namespace
// static
......@@ -346,48 +327,14 @@ void CastWebContentsImpl::ClearRenderWidgetHostView() {
}
}
CastWebContentsImpl::OriginScopedScript::OriginScopedScript() = default;
CastWebContentsImpl::OriginScopedScript::OriginScopedScript(
const std::vector<std::string>& origins,
std::string script)
: origins_(std::move(origins)), script_(std::move(script)) {}
CastWebContentsImpl::OriginScopedScript&
CastWebContentsImpl::OriginScopedScript::operator=(
CastWebContentsImpl::OriginScopedScript&& other) {
origins_ = std::move(other.origins_);
script_ = std::move(other.script_);
return *this;
}
CastWebContentsImpl::OriginScopedScript::~OriginScopedScript() = default;
void CastWebContentsImpl::AddBeforeLoadJavaScript(
base::StringPiece id,
const std::vector<std::string>& origins,
base::StringPiece script) {
DCHECK(!id.empty() && !script.empty() && !origins.empty())
<< "Invalid empty parameters were passed to AddBeforeLoadJavascript";
// If there is no script with the identifier |id|, then create a place for it
// at the end of the injection sequence.
if (before_load_scripts_.find(id.as_string()) == before_load_scripts_.end()) {
before_load_scripts_order_.push_back(id.as_string());
}
before_load_scripts_[id.as_string()] =
OriginScopedScript(origins, script.as_string());
on_load_script_injector::OnLoadScriptInjectorHost*
CastWebContentsImpl::script_injector() {
return &script_injector_;
}
void CastWebContentsImpl::RemoveBeforeLoadJavaScript(base::StringPiece id) {
before_load_scripts_.erase(id.as_string());
for (auto script_id_iter = before_load_scripts_order_.begin();
script_id_iter != before_load_scripts_order_.end(); ++script_id_iter) {
if (*script_id_iter == id) {
before_load_scripts_order_.erase(script_id_iter);
return;
}
}
void CastWebContentsImpl::InjectScriptsIntoMainFrame() {
script_injector_.InjectScriptsForURL(web_contents_->GetURL(),
web_contents_->GetMainFrame());
}
void CastWebContentsImpl::PostMessageToMainFrame(
......@@ -666,32 +613,6 @@ void CastWebContentsImpl::ReadyToCommitNavigation(
UpdatePageState();
DCHECK_EQ(page_state_, PageState::LOADING);
NotifyPageState();
if (before_load_scripts_.empty())
return;
if (!navigation_handle->IsInMainFrame() ||
navigation_handle->IsSameDocument() || navigation_handle->IsErrorPage())
return;
mojo::AssociatedRemote<chromecast::shell::mojom::OnLoadScriptInjector>
before_load_script_injector;
navigation_handle->GetRenderFrameHost()
->GetRemoteAssociatedInterfaces()
->GetInterface(&before_load_script_injector);
// Provision the renderer's ScriptInjector with the scripts scoped to this
// page's origin.
before_load_script_injector->ClearOnLoadScripts();
for (auto script_id : before_load_scripts_order_) {
const OriginScopedScript& origin_scoped_script =
before_load_scripts_[script_id];
if (IsOriginWhitelisted(navigation_handle->GetURL(),
origin_scoped_script.origins())) {
before_load_script_injector->AddOnLoadScript(
origin_scoped_script.script());
}
}
}
void CastWebContentsImpl::DidFinishNavigation(
......
......@@ -23,6 +23,7 @@
#include "base/time/time.h"
#include "chromecast/browser/cast_media_blocker.h"
#include "chromecast/browser/cast_web_contents.h"
#include "components/on_load_script_injector/browser/on_load_script_injector_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
......@@ -69,10 +70,8 @@ class CastWebContentsImpl : public CastWebContents,
void BlockMediaLoading(bool blocked) override;
void BlockMediaStarting(bool blocked) override;
void EnableBackgroundVideoPlayback(bool enabled) override;
void AddBeforeLoadJavaScript(base::StringPiece id,
const std::vector<std::string>& origins,
base::StringPiece script) override;
void RemoveBeforeLoadJavaScript(base::StringPiece id) override;
on_load_script_injector::OnLoadScriptInjectorHost* script_injector() override;
void InjectScriptsIntoMainFrame() override;
void PostMessageToMainFrame(
const std::string& target_origin,
const std::string& data,
......@@ -136,22 +135,6 @@ class CastWebContentsImpl : public CastWebContents,
content::WebContentsObserver::MediaStoppedReason reason) override;
private:
struct OriginScopedScript {
OriginScopedScript();
OriginScopedScript(const std::vector<std::string>& origins,
std::string script);
OriginScopedScript& operator=(OriginScopedScript&& other);
~OriginScopedScript();
const std::vector<std::string>& origins() const { return origins_; }
const std::string script() const { return script_; }
std::vector<std::string> origins_;
std::string script_;
DISALLOW_COPY_AND_ASSIGN(OriginScopedScript);
};
void OnPageLoading();
void OnPageLoaded();
void UpdatePageState();
......@@ -192,8 +175,7 @@ class CastWebContentsImpl : public CastWebContents,
bool notifying_;
int last_error_;
std::map<std::string, OriginScopedScript> before_load_scripts_;
std::vector<std::string> before_load_scripts_order_;
on_load_script_injector::OnLoadScriptInjectorHost script_injector_;
base::ObserverList<Observer>::Unchecked observer_list_;
......
......@@ -37,16 +37,11 @@ class MockCastWebContents : public CastWebContents {
MOCK_METHOD(void, BlockMediaLoading, (bool), (override));
MOCK_METHOD(void, BlockMediaStarting, (bool), (override));
MOCK_METHOD(void, EnableBackgroundVideoPlayback, (bool), (override));
MOCK_METHOD(void,
AddBeforeLoadJavaScript,
(base::StringPiece,
const std::vector<std::string>&,
base::StringPiece),
(override));
MOCK_METHOD(void,
RemoveBeforeLoadJavaScript,
(base::StringPiece),
MOCK_METHOD(on_load_script_injector::OnLoadScriptInjectorHost*,
script_injector,
(),
(override));
MOCK_METHOD(void, InjectScriptsIntoMainFrame, (), (override));
MOCK_METHOD(void,
PostMessageToMainFrame,
(const std::string&,
......
......@@ -15,7 +15,6 @@ mojom("mojom") {
"media_caps.mojom",
"memory_pressure.mojom",
"multiroom.mojom",
"on_load_script_injector.mojom",
"queryable_data_store.mojom",
"service_connector.mojom",
]
......
// 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 chromecast.shell.mojom;
// Interface associated with RenderFrames for managing on-load JavaScript
// injection tasks per frame. Does not enforce script injection policies,
// which must be implemented at a higher level.
interface OnLoadScriptInjector {
// Add an on-load JavaScript injection task. The script will be
// executed before any other script (e.g. <script> tag) runs.
AddOnLoadScript(string script);
// Clear all registered on-load JavaScript injection tasks.
ClearOnLoadScripts();
};
......@@ -43,8 +43,6 @@ cast_source_set("renderer") {
"js_channel_bindings.h",
"native_bindings_helper.cc",
"native_bindings_helper.h",
"on_load_script_injector.cc",
"on_load_script_injector.h",
"queryable_data_bindings.cc",
"queryable_data_bindings.h",
"queryable_data_store.cc",
......@@ -72,6 +70,7 @@ cast_source_set("renderer") {
"//chromecast/media/base:media_codec_support",
"//components/media_control/renderer",
"//components/network_hints/renderer",
"//components/on_load_script_injector/renderer",
"//content/public/common",
"//content/public/renderer",
"//crypto",
......
......@@ -6,6 +6,7 @@ include_rules = [
"+components/media_control/renderer",
"+components/media_control/mojom",
"+components/network_hints/renderer",
"+components/on_load_script_injector/renderer",
"+components/version_info",
"+content/public/common",
"+content/public/renderer",
......
......@@ -22,10 +22,10 @@
#include "chromecast/renderer/js_channel_bindings.h"
#include "chromecast/renderer/media/key_systems_cast.h"
#include "chromecast/renderer/media/media_caps_observer_impl.h"
#include "chromecast/renderer/on_load_script_injector.h"
#include "chromecast/renderer/queryable_data_bindings.h"
#include "components/media_control/renderer/media_playback_options.h"
#include "components/network_hints/renderer/web_prescient_networking_impl.h"
#include "components/on_load_script_injector/renderer/on_load_script_injector.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
......@@ -187,8 +187,8 @@ void CastContentRendererClient::RenderFrameCreated(
}
// Add script injection support to the RenderFrame, used by Cast platform
// APIs. The objects' lifetimes are bound to the RenderFrame's lifetime.
new OnLoadScriptInjector(render_frame);
// APIs. The injector's lifetime is bound to the RenderFrame's lifetime.
new on_load_script_injector::OnLoadScriptInjector(render_frame);
if (!app_media_capabilities_observer_receiver_.is_bound()) {
mojo::Remote<mojom::ApplicationMediaCapabilities> app_media_capabilities;
......
// 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 "chromecast/renderer/on_load_script_injector.h"
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/renderer/render_frame.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
namespace chromecast {
namespace shell {
OnLoadScriptInjector::OnLoadScriptInjector(content::RenderFrame* frame)
: RenderFrameObserver(frame), weak_ptr_factory_(this) {
render_frame()->GetAssociatedInterfaceRegistry()->AddInterface(
base::BindRepeating(&OnLoadScriptInjector::BindToReceiver,
weak_ptr_factory_.GetWeakPtr()));
}
OnLoadScriptInjector::~OnLoadScriptInjector() {}
void OnLoadScriptInjector::BindToReceiver(
mojo::PendingAssociatedReceiver<mojom::OnLoadScriptInjector> receiver) {
receivers_.Add(this, std::move(receiver));
}
void OnLoadScriptInjector::DidCommitProvisionalLoad(
ui::PageTransition transition) {
// Don't inject anything for subframes.
if (!render_frame()->IsMainFrame())
return;
for (std::string& script : on_load_scripts_) {
base::string16 script_utf16 = base::UTF8ToUTF16(script);
render_frame()->ExecuteJavaScript(script_utf16);
}
}
void OnLoadScriptInjector::AddOnLoadScript(const std::string& script) {
on_load_scripts_.push_back(std::move(script));
}
void OnLoadScriptInjector::ClearOnLoadScripts() {
on_load_scripts_.clear();
}
void OnLoadScriptInjector::OnDestruct() {
delete this;
}
} // namespace shell
} // namespace chromecast
// 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 CHROMECAST_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
#define CHROMECAST_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece_forward.h"
#include "chromecast/common/mojom/on_load_script_injector.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
#include "mojo/public/cpp/bindings/associated_receiver_set.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
namespace chromecast {
namespace shell {
// Injects one or more scripts into a RenderFrame at the earliest possible time
// during the page load process.
class OnLoadScriptInjector : public content::RenderFrameObserver,
public mojom::OnLoadScriptInjector {
public:
explicit OnLoadScriptInjector(content::RenderFrame* frame);
void BindToReceiver(
mojo::PendingAssociatedReceiver<mojom::OnLoadScriptInjector> receiver);
void AddOnLoadScript(const std::string& script) override;
void ClearOnLoadScripts() override;
// RenderFrameObserver override:
void OnDestruct() override;
void DidCommitProvisionalLoad(ui::PageTransition transition) override;
private:
// Called by OnDestruct(), when the RenderFrame is destroyed.
~OnLoadScriptInjector() override;
std::vector<std::string> on_load_scripts_;
mojo::AssociatedReceiverSet<mojom::OnLoadScriptInjector> receivers_;
base::WeakPtrFactory<OnLoadScriptInjector> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(OnLoadScriptInjector);
};
} // namespace shell
} // namespace chromecast
#endif // CHROMECAST_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
# 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.
import("//mojo/public/tools/bindings/mojom.gni")
mojom("on_load_script_injector_mojom") {
sources = [ "on_load_script_injector.mojom" ]
public_deps = [ "//mojo/public/mojom/base" ]
visibility = [ "./*" ]
}
source_set("export") {
sources = [ "export.h" ]
}
file://build/fuchsia/OWNERS
# COMPONENT: Fuchsia
# OS: Fuchsia
# TEAM: cr-fuchsia@chromium.org
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
# 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.
import("//build/config/features.gni")
component("browser") {
sources = [
"on_load_script_injector_host.cc",
"on_load_script_injector_host.h",
]
defines = [ "ON_LOAD_SCRIPT_INJECTOR_IMPLEMENTATION" ]
deps = [
"//base",
"//components/on_load_script_injector:export",
"//components/on_load_script_injector:on_load_script_injector_mojom",
"//content/public/browser",
"//mojo/public/cpp/bindings",
"//third_party/blink/public/common",
]
visibility = [
"//chromecast/bindings:bindings_manager_cast",
"//chromecast/browser:browser",
"//fuchsia/engine:web_engine_core",
]
}
include_rules = [
"+content/public/browser",
"+mojo/public/cpp/bindings",
"+third_party/blink/public/common",
]
// 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 "components/on_load_script_injector/browser/on_load_script_injector_host.h"
#include <utility>
#include "base/numerics/safe_math.h"
#include "components/on_load_script_injector/on_load_script_injector.mojom.h"
#include "content/public/browser/navigation_handle.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
namespace on_load_script_injector {
OnLoadScriptInjectorHost::OnLoadScriptInjectorHost() = default;
OnLoadScriptInjectorHost::~OnLoadScriptInjectorHost() = default;
void OnLoadScriptInjectorHost::AddScript(
ScriptId id,
std::vector<url::Origin> origins_to_inject,
base::StringPiece script) {
// If there is no script with the identifier |id|, then create a place for it
// at the end of the injection sequence.
if (before_load_scripts_.find(id) == before_load_scripts_.end())
before_load_scripts_order_.push_back(id);
// Convert script to UTF-16.
base::string16 script_utf16 = base::UTF8ToUTF16(script);
size_t script_utf16_size =
(base::CheckedNumeric<size_t>(script_utf16.size()) * sizeof(base::char16))
.ValueOrDie();
base::WritableSharedMemoryRegion script_shared_memory =
base::WritableSharedMemoryRegion::Create(script_utf16_size);
memcpy(script_shared_memory.Map().memory(), script_utf16.data(),
script_utf16_size);
base::ReadOnlySharedMemoryRegion script_shared_memory_readonly =
base::WritableSharedMemoryRegion::ConvertToReadOnly(
std::move(script_shared_memory));
CHECK(script_shared_memory_readonly.IsValid());
before_load_scripts_[id] = OriginScopedScript(
origins_to_inject, std::move(script_shared_memory_readonly));
}
void OnLoadScriptInjectorHost::AddScriptForAllOrigins(
ScriptId id,
base::StringPiece script) {
AddScript(id, {kMatchAllOrigins}, script);
}
void OnLoadScriptInjectorHost::RemoveScript(ScriptId id) {
before_load_scripts_.erase(id);
for (auto script_id_iter = before_load_scripts_order_.begin();
script_id_iter != before_load_scripts_order_.end(); ++script_id_iter) {
if (*script_id_iter == id) {
before_load_scripts_order_.erase(script_id_iter);
return;
}
}
LOG(WARNING) << "Ignoring attempt to remove unknown OnLoad script: " << id;
}
void OnLoadScriptInjectorHost::InjectScriptsForURL(
const GURL& url,
content::RenderFrameHost* render_frame_host) {
DCHECK(url.is_valid());
mojo::AssociatedRemote<mojom::OnLoadScriptInjector> injector;
render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&injector);
injector->ClearOnLoadScripts();
if (before_load_scripts_.empty())
return;
// Provision the renderer's ScriptInjector with the scripts associated with
// |url|.
for (ScriptId script_id : before_load_scripts_order_) {
const OriginScopedScript& script = before_load_scripts_[script_id];
if (IsUrlMatchedByOriginList(url, script.origins()))
injector->AddOnLoadScript(script.script().Duplicate());
}
}
// static
bool OnLoadScriptInjectorHost::IsUrlMatchedByOriginList(
const GURL& url,
const std::vector<url::Origin>& allowed_origins) {
url::Origin url_origin = url::Origin::Create(url);
for (const url::Origin& allowed_origin : allowed_origins) {
if (allowed_origin == kMatchAllOrigins)
return true;
DCHECK(!allowed_origin.opaque());
if (url_origin.IsSameOriginWith(allowed_origin))
return true;
}
return false;
}
OnLoadScriptInjectorHost::OriginScopedScript::OriginScopedScript() = default;
OnLoadScriptInjectorHost::OriginScopedScript::OriginScopedScript(
std::vector<url::Origin> origins,
base::ReadOnlySharedMemoryRegion script)
: origins_(std::move(origins)), script_(std::move(script)) {}
OnLoadScriptInjectorHost::OriginScopedScript&
OnLoadScriptInjectorHost::OriginScopedScript::operator=(
OnLoadScriptInjectorHost::OriginScopedScript&& other) {
origins_ = std::move(other.origins_);
script_ = std::move(other.script_);
return *this;
}
OnLoadScriptInjectorHost::OriginScopedScript::~OriginScopedScript() = default;
} // namespace on_load_script_injector
// 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.
#ifndef COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_BROWSER_ON_LOAD_SCRIPT_INJECTOR_HOST_H_
#define COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_BROWSER_ON_LOAD_SCRIPT_INJECTOR_HOST_H_
#include <map>
#include <string>
#include <vector>
#include "base/memory/read_only_shared_memory_region.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/on_load_script_injector/export.h"
#include "content/public/browser/render_frame_host.h"
#include "url/origin.h"
namespace on_load_script_injector {
// Manages the set of scripts to be injected into document just prior to
// document load.
class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjectorHost {
public:
#if defined(OS_FUCHSIA)
using ScriptId = uint64_t;
#else
using ScriptId = std::string;
#endif
OnLoadScriptInjectorHost();
~OnLoadScriptInjectorHost();
OnLoadScriptInjectorHost(const OnLoadScriptInjectorHost&) = delete;
OnLoadScriptInjectorHost& operator=(const OnLoadScriptInjectorHost&) = delete;
// Adds a |script| to be injected on pages whose URL's origin matches at least
// one entry of |origins_to_inject|.
// Scripts will be loaded in the order they are added.
// If a script with |id| already exists, it will be replaced with the original
// sequence position preserved.
// All entries of |origins_to_inject| must be valid/not opaque.
void AddScript(ScriptId id,
std::vector<url::Origin> origins_to_inject,
base::StringPiece script);
// Same as AddScript(), except that scripts are injected for all pages.
void AddScriptForAllOrigins(ScriptId id, base::StringPiece script);
// Removes the script |id|.
void RemoveScript(ScriptId id);
// Injects the scripts associated with the origin of |url| into the document
// hosted by |render_frame_host|.
void InjectScriptsForURL(const GURL& url,
content::RenderFrameHost* render_frame_host);
private:
class OriginScopedScript {
public:
OriginScopedScript();
OriginScopedScript(std::vector<url::Origin> origins,
base::ReadOnlySharedMemoryRegion script);
OriginScopedScript& operator=(OriginScopedScript&& other);
~OriginScopedScript();
const std::vector<url::Origin>& origins() const { return origins_; }
const base::ReadOnlySharedMemoryRegion& script() const { return script_; }
private:
std::vector<url::Origin> origins_;
// A shared memory buffer containing the script, encoded as UTF16.
base::ReadOnlySharedMemoryRegion script_;
};
bool IsUrlMatchedByOriginList(
const GURL& url,
const std::vector<url::Origin>& allowed_origins);
// An opaque Origin that, when specified, allows script injection on all URLs
// regardless of origin.
const url::Origin kMatchAllOrigins;
std::map<ScriptId, OriginScopedScript> before_load_scripts_;
std::vector<ScriptId> before_load_scripts_order_;
};
} // namespace on_load_script_injector
#endif // COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_BROWSER_ON_LOAD_SCRIPT_INJECTOR_HOST_
// 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.
#ifndef COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_EXPORT_H_
#define COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_EXPORT_H_
#if defined(COMPONENT_BUILD) && defined(ON_LOAD_SCRIPT_INJECTOR_IMPLEMENTATION)
#define ON_LOAD_SCRIPT_INJECTOR_EXPORT __attribute__((visibility("default")))
#else // !defined(COMPONENT_BUILD) ||
// !defined(ON_LOAD_SCRIPT_INJECTOR_IMPLEMENTATION)
#define ON_LOAD_SCRIPT_INJECTOR_EXPORT
#endif
#endif // COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_EXPORT_H_
......@@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module mojom;
module on_load_script_injector.mojom;
import "mojo/public/mojom/base/shared_memory.mojom";
// Interface associated with RenderFrames for managing on-load JavaScript
// injection tasks the frame. Does not enforce script injection policies,
// which must be implemented at a higher level.
interface OnLoadScriptInjector {
// TODO(crbug.com/1060846): Stop using handle<shared_buffer>.
AddOnLoadScript(handle<shared_buffer> script);
// |script|: The script to inject, in UTF-16.
AddOnLoadScript(mojo_base.mojom.ReadOnlySharedMemoryRegion script);
ClearOnLoadScripts();
};
# 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.
import("//build/config/features.gni")
component("renderer") {
sources = [
"on_load_script_injector.cc",
"on_load_script_injector.h",
]
defines = [ "ON_LOAD_SCRIPT_INJECTOR_IMPLEMENTATION" ]
deps = [
"//base",
"//components/on_load_script_injector:export",
"//components/on_load_script_injector:on_load_script_injector_mojom",
"//content/public/common",
"//content/public/renderer",
"//mojo/public/cpp/bindings",
"//third_party/blink/public/common",
]
visibility = [
"//chromecast/renderer/*",
"//fuchsia/engine:web_engine_core",
]
}
include_rules = [
"+content/public/renderer",
"+mojo/public/cpp/bindings",
"+third_party/blink/public",
]
......@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "fuchsia/engine/renderer/on_load_script_injector.h"
#include "components/on_load_script_injector/renderer/on_load_script_injector.h"
#include <lib/zx/vmo.h>
#include <utility>
#include <vector>
......@@ -13,6 +12,8 @@
#include "content/public/renderer/render_frame.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
namespace on_load_script_injector {
OnLoadScriptInjector::OnLoadScriptInjector(content::RenderFrame* frame)
: RenderFrameObserver(frame), weak_ptr_factory_(this) {
render_frame()->GetAssociatedInterfaceRegistry()->AddInterface(
......@@ -33,18 +34,19 @@ void OnLoadScriptInjector::DidCommitProvisionalLoad(
if (!render_frame()->IsMainFrame())
return;
for (mojo::ScopedSharedBufferHandle& script : on_load_scripts_) {
DCHECK_EQ(script->GetSize() % 2, 0u); // Crude check to see this is UTF-16.
for (base::ReadOnlySharedMemoryRegion& script : on_load_scripts_) {
// Crude check to see this is UTF-16.
DCHECK_EQ(script.GetSize() % sizeof(base::char16), 0u);
auto mapping = script->Map(script->GetSize());
base::string16 script_converted(static_cast<base::char16*>(mapping.get()),
script->GetSize() / sizeof(base::char16));
auto mapping = script.Map();
base::string16 script_converted(mapping.GetMemoryAs<base::char16>(),
script.GetSize() / sizeof(base::char16));
render_frame()->ExecuteJavaScript(script_converted);
}
}
void OnLoadScriptInjector::AddOnLoadScript(
mojo::ScopedSharedBufferHandle script) {
base::ReadOnlySharedMemoryRegion script) {
on_load_scripts_.push_back(std::move(script));
}
......@@ -55,3 +57,5 @@ void OnLoadScriptInjector::ClearOnLoadScripts() {
void OnLoadScriptInjector::OnDestruct() {
delete this;
}
} // namespace on_load_script_injector
......@@ -2,33 +2,39 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FUCHSIA_ENGINE_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
#define FUCHSIA_ENGINE_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
#ifndef COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
#define COMPONENTS_ON_LOAD_SCRIPT_INJECTOR_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
#include <lib/zx/vmo.h>
#include <vector>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/on_load_script_injector/export.h"
#include "components/on_load_script_injector/on_load_script_injector.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
#include "fuchsia/engine/on_load_script_injector.mojom.h"
#include "mojo/public/cpp/bindings/associated_receiver_set.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
namespace on_load_script_injector {
// Injects one or more scripts into a RenderFrame at the earliest possible time
// during the page load process.
class OnLoadScriptInjector : public content::RenderFrameObserver,
public mojom::OnLoadScriptInjector {
class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjector
: public content::RenderFrameObserver,
public mojom::OnLoadScriptInjector {
public:
explicit OnLoadScriptInjector(content::RenderFrame* frame);
OnLoadScriptInjector(const OnLoadScriptInjector&) = delete;
OnLoadScriptInjector& operator=(const OnLoadScriptInjector&) = delete;
void BindToReceiver(
mojo::PendingAssociatedReceiver<mojom::OnLoadScriptInjector> receiver);
void AddOnLoadScript(mojo::ScopedSharedBufferHandle script) override;
// mojom::OnLoadScriptInjector implementation.
void AddOnLoadScript(base::ReadOnlySharedMemoryRegion script) override;
void ClearOnLoadScripts() override;
// RenderFrameObserver override:
// RenderFrameObserver overrides.
void OnDestruct() override;
void DidCommitProvisionalLoad(ui::PageTransition transition) override;
......@@ -36,11 +42,11 @@ class OnLoadScriptInjector : public content::RenderFrameObserver,
// Called by OnDestruct(), when the RenderFrame is destroyed.
~OnLoadScriptInjector() override;
std::vector<mojo::ScopedSharedBufferHandle> on_load_scripts_;
std::vector<base::ReadOnlySharedMemoryRegion> on_load_scripts_;
mojo::AssociatedReceiverSet<mojom::OnLoadScriptInjector> receivers_;
base::WeakPtrFactory<OnLoadScriptInjector> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(OnLoadScriptInjector);
};
#endif // FUCHSIA_ENGINE_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
} // namespace on_load_script_injector
#endif // COMPONENTS_CAST_API_BINDINGS_API_BINDINGS_RENDERER_ON_LOAD_SCRIPT_INJECTOR_H_
......@@ -28,7 +28,6 @@ declare_args() {
mojom("mojom") {
sources = [
"cast_streaming_session.mojom",
"on_load_script_injector.mojom",
"url_request_rewrite.mojom",
]
public_deps = [
......@@ -92,6 +91,8 @@ component("web_engine_core") {
"//components/cdm/renderer",
"//components/media_control/browser",
"//components/media_control/renderer",
"//components/on_load_script_injector/browser",
"//components/on_load_script_injector/renderer",
"//components/version_info",
"//content/public/app",
"//content/public/browser",
......@@ -205,8 +206,6 @@ component("web_engine_core") {
"renderer/cast_streaming_demuxer.h",
"renderer/cast_streaming_receiver.cc",
"renderer/cast_streaming_receiver.h",
"renderer/on_load_script_injector.cc",
"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",
......
......@@ -3,6 +3,7 @@ include_rules = [
"+components/version_info",
"+components/viz/common",
"+components/media_control",
"+components/on_load_script_injector",
"+content/public/app",
"+gpu/command_buffer/service",
"+gpu/config/gpu_finch_features.h",
......
include_rules = [
"+components/keyed_service/core",
"+components/on_load_script_injector/browser",
"+content/public/common",
"+content/public/browser",
"+media/base",
......
......@@ -71,6 +71,9 @@ constexpr gfx::Size kHeadlessWindowSize = {1, 1};
// Simulated screen bounds to use when testing the SemanticsManager.
constexpr gfx::Size kSemanticsTestingWindowSize = {720, 640};
// A special value which matches all origins when specified in an origin list.
constexpr char kWildcardOrigin[] = "*";
// Used for attaching popup-related metadata to a WebContents.
constexpr char kPopupCreationInfo[] = "popup-creation-info";
class PopupFrameCreationInfoUserData : public base::SupportsUserData::Data {
......@@ -96,12 +99,11 @@ bool FrameFocusRules::SupportsChildActivation(const aura::Window*) const {
return true;
}
bool IsOriginAllowed(const GURL& url,
const std::vector<std::string>& allowed_origins) {
constexpr const char kWildcard[] = "*";
// TODO(crbug.com/1113289): Use OnLoadScriptInjectorHost's origin matching code.
bool IsUrlMatchedByOriginList(const GURL& url,
const std::vector<std::string>& allowed_origins) {
for (const std::string& origin : allowed_origins) {
if (origin == kWildcard)
if (origin == kWildcardOrigin)
return true;
GURL origin_url(origin);
......@@ -115,9 +117,6 @@ bool IsOriginAllowed(const GURL& url,
if (origin_url != url.GetOrigin())
continue;
// TODO(crbug.com/893236): Add handling for nonstandard origins
// (e.g. data: URIs).
return true;
}
return false;
......@@ -279,22 +278,6 @@ zx::unowned_channel FrameImpl::GetBindingChannelForTest() const {
return zx::unowned_channel(binding_.channel());
}
FrameImpl::OriginScopedScript::OriginScopedScript() = default;
FrameImpl::OriginScopedScript::OriginScopedScript(
std::vector<std::string> origins,
base::ReadOnlySharedMemoryRegion script)
: origins_(std::move(origins)), script_(std::move(script)) {}
FrameImpl::OriginScopedScript& FrameImpl::OriginScopedScript::operator=(
FrameImpl::OriginScopedScript&& other) {
origins_ = std::move(other.origins_);
script_ = std::move(other.script_);
return *this;
}
FrameImpl::OriginScopedScript::~OriginScopedScript() = default;
aura::Window* FrameImpl::root_window() const {
return window_tree_host_->window();
}
......@@ -310,7 +293,10 @@ void FrameImpl::ExecuteJavaScriptInternal(std::vector<std::string> origins,
return;
}
if (!IsOriginAllowed(web_contents_->GetLastCommittedURL(), origins)) {
// Prevents script injection into the wrong document if the renderer recently
// navigated to a different origin.
if (!IsUrlMatchedByOriginList(web_contents_->GetLastCommittedURL(),
origins)) {
result.set_err(fuchsia::web::FrameError::INVALID_ORIGIN);
callback(std::move(result));
return;
......@@ -528,30 +514,6 @@ bool FrameImpl::MaybeHandleCastStreamingMessage(
return true;
}
void FrameImpl::MaybeInjectBeforeLoadScripts(
content::NavigationHandle* navigation_handle) {
if (before_load_scripts_.empty())
return;
mojo::AssociatedRemote<mojom::OnLoadScriptInjector>
before_load_script_injector;
navigation_handle->GetRenderFrameHost()
->GetRemoteAssociatedInterfaces()
->GetInterface(&before_load_script_injector);
// Provision the renderer's ScriptInjector with the scripts scoped to this
// page's origin.
before_load_script_injector->ClearOnLoadScripts();
for (uint64_t script_id : before_load_scripts_order_) {
const OriginScopedScript& script = before_load_scripts_[script_id];
if (IsOriginAllowed(navigation_handle->GetURL(), script.origins())) {
// TODO(crbug.com/1060846): Stop using handle<shared_buffer>.
before_load_script_injector->AddOnLoadScript(
mojo::WrapReadOnlySharedMemoryRegion(script.script().Duplicate()));
}
}
}
void FrameImpl::MaybeStartCastStreaming(
content::NavigationHandle* navigation_handle) {
if (!IsCastStreamingEnabled() || !cast_streaming_session_client_)
......@@ -651,6 +613,8 @@ void FrameImpl::AddBeforeLoadJavaScript(
std::vector<std::string> origins,
fuchsia::mem::Buffer script,
AddBeforeLoadJavaScriptCallback callback) {
constexpr char kWildcardOrigin[] = "*";
fuchsia::web::Frame_AddBeforeLoadJavaScript_Result result;
if (!context_->IsJavaScriptInjectionAllowed()) {
result.set_err(fuchsia::web::FrameError::INTERNAL_ERROR);
......@@ -658,52 +622,41 @@ void FrameImpl::AddBeforeLoadJavaScript(
return;
}
// Convert the script to UTF8 and store it as a shared memory buffer, so that
// it can be efficiently shared with multiple renderer processes.
base::string16 script_utf16;
if (!cr_fuchsia::ReadUTF8FromVMOAsUTF16(script, &script_utf16)) {
result.set_err(fuchsia::web::FrameError::BUFFER_NOT_UTF8);
std::string script_as_string;
if (!cr_fuchsia::StringFromMemBuffer(script, &script_as_string)) {
LOG(ERROR) << "Couldn't read script from buffer.";
result.set_err(fuchsia::web::FrameError::INTERNAL_ERROR);
callback(std::move(result));
return;
}
// Create a read-only VMO from |script|.
fuchsia::mem::Buffer script_buffer =
cr_fuchsia::MemBufferFromString16(script_utf16, "cr-before-load-js");
// Wrap the VMO into a read-only shared-memory container that Mojo can work
// with.
base::subtle::PlatformSharedMemoryRegion script_region =
base::subtle::PlatformSharedMemoryRegion::Take(
std::move(script_buffer.vmo),
base::subtle::PlatformSharedMemoryRegion::Mode::kWritable,
script_buffer.size, base::UnguessableToken::Create());
script_region.ConvertToReadOnly();
auto script_region_mojo =
base::ReadOnlySharedMemoryRegion::Deserialize(std::move(script_region));
// If there is no script with the identifier |id|, then create a place for it
// at the end of the injection sequence.
if (before_load_scripts_.find(id) == before_load_scripts_.end())
before_load_scripts_order_.push_back(id);
before_load_scripts_[id] =
OriginScopedScript(origins, std::move(script_region_mojo));
// TODO(crbug.com/1108607): Only allow wildcards to be specified standalone.
if (std::any_of(origins.begin(), origins.end(),
[kWildcardOrigin](base::StringPiece origin) {
return origin == kWildcardOrigin;
})) {
script_injector_.AddScriptForAllOrigins(id, script_as_string);
} else {
std::vector<url::Origin> origins_converted;
for (const std::string& origin : origins) {
url::Origin origin_parsed = url::Origin::Create(GURL(origin));
if (origin_parsed.opaque()) {
result.set_err(fuchsia::web::FrameError::INVALID_ORIGIN);
callback(std::move(result));
return;
}
origins_converted.push_back(origin_parsed);
}
script_injector_.AddScript(id, origins_converted, script_as_string);
}
result.set_response(fuchsia::web::Frame_AddBeforeLoadJavaScript_Response());
callback(std::move(result));
}
void FrameImpl::RemoveBeforeLoadJavaScript(uint64_t id) {
before_load_scripts_.erase(id);
for (auto script_id_iter = before_load_scripts_order_.begin();
script_id_iter != before_load_scripts_order_.end(); ++script_id_iter) {
if (*script_id_iter == id) {
before_load_scripts_order_.erase(script_id_iter);
return;
}
}
script_injector_.RemoveScript(id);
}
void FrameImpl::PostMessage(std::string origin,
......@@ -712,8 +665,6 @@ void FrameImpl::PostMessage(std::string origin,
if (MaybeHandleCastStreamingMessage(&origin, &message, &callback))
return;
constexpr char kWildcardOrigin[] = "*";
fuchsia::web::Frame_PostMessage_Result result;
if (origin.empty()) {
result.set_err(fuchsia::web::FrameError::INVALID_ORIGIN);
......@@ -1082,7 +1033,9 @@ void FrameImpl::ReadyToCommitNavigation(
return;
}
MaybeInjectBeforeLoadScripts(navigation_handle);
script_injector_.InjectScriptsForURL(navigation_handle->GetURL(),
navigation_handle->GetRenderFrameHost());
MaybeStartCastStreaming(navigation_handle);
}
......
......@@ -20,6 +20,7 @@
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.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"
#include "content/public/browser/web_contents_observer.h"
#include "fuchsia/engine/browser/accessibility_bridge.h"
......@@ -27,7 +28,6 @@
#include "fuchsia/engine/browser/frame_permission_controller.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 "ui/aura/window_tree_host.h"
#include "ui/wm/core/focus_controller.h"
#include "url/gurl.h"
......@@ -97,26 +97,6 @@ class FrameImpl : public fuchsia::web::Frame,
FRIEND_TEST_ALL_PREFIXES(FrameImplTest, ReloadFrame);
FRIEND_TEST_ALL_PREFIXES(FrameImplTest, Stop);
class OriginScopedScript {
public:
OriginScopedScript();
OriginScopedScript(std::vector<std::string> origins,
base::ReadOnlySharedMemoryRegion script);
OriginScopedScript& operator=(OriginScopedScript&& other);
~OriginScopedScript();
const std::vector<std::string>& origins() const { return origins_; }
const base::ReadOnlySharedMemoryRegion& script() const { return script_; }
private:
std::vector<std::string> origins_;
// A shared memory buffer containing the script, encoded as UTF16.
base::ReadOnlySharedMemoryRegion script_;
DISALLOW_COPY_AND_ASSIGN(OriginScopedScript);
};
aura::Window* root_window() const;
// Shared implementation for the ExecuteJavaScript[NoResult]() APIs.
......@@ -154,9 +134,6 @@ class FrameImpl : public fuchsia::web::Frame,
fuchsia::web::WebMessage* message,
PostMessageCallback* callback);
void MaybeInjectBeforeLoadScripts(
content::NavigationHandle* navigation_handle);
void MaybeStartCastStreaming(content::NavigationHandle* navigation_handle);
// fuchsia::web::Frame implementation.
......@@ -278,8 +255,6 @@ class FrameImpl : public fuchsia::web::Frame,
EventFilter event_filter_;
NavigationControllerImpl navigation_controller_;
logging::LogSeverity log_level_;
std::map<uint64_t, OriginScopedScript> before_load_scripts_;
std::vector<uint64_t> before_load_scripts_order_;
base::RepeatingCallback<void(base::StringPiece)> console_log_message_hook_;
UrlRequestRewriteRulesManager url_request_rewrite_rules_manager_;
FramePermissionController permission_controller_;
......@@ -296,6 +271,7 @@ class FrameImpl : public fuchsia::web::Frame,
std::unique_ptr<MediaPlayerImpl> media_player_;
std::unique_ptr<CastStreamingSessionClient> cast_streaming_session_client_;
on_load_script_injector::OnLoadScriptInjectorHost script_injector_;
fidl::Binding<fuchsia::web::Frame> binding_;
media_control::MediaBlocker media_blocker_;
......
......@@ -9,10 +9,10 @@
#include "base/macros.h"
#include "components/cdm/renderer/widevine_key_system_properties.h"
#include "components/media_control/renderer/media_playback_options.h"
#include "components/on_load_script_injector/renderer/on_load_script_injector.h"
#include "content/public/renderer/render_frame.h"
#include "fuchsia/engine/common/cast_streaming.h"
#include "fuchsia/engine/renderer/cast_streaming_demuxer.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 "media/base/eme_constants.h"
......@@ -130,7 +130,7 @@ void WebEngineContentRendererClient::RenderFrameCreated(
content::RenderFrame* render_frame) {
// Add WebEngine services to the new RenderFrame.
// The objects' lifetimes are bound to the RenderFrame's lifetime.
new OnLoadScriptInjector(render_frame);
new on_load_script_injector::OnLoadScriptInjector(render_frame);
int render_frame_id = render_frame->GetRoutingID();
......
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