Commit 3f69381d authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[on_load_script_injector] Make ScriptId type into a template parameter.

Promotes ScriptId to a template parameter, so that the script injector
can be used for multiple purposes on a given platform.
Specifically, it will allow the use of uint64 script IDs on
FrameImpl, and base::StringPiece in bindings tests.

Migrate OnLoadScriptInjectorHost implementation from .cc to .h.


Bug: 1104369
Change-Id: Idfacd460d8d12038cfc2c00896e538ee87c55a1a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2341837
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarSean Topping <seantopping@chromium.org>
Reviewed-by: default avatarSharon Yang <yangsharon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795994}
parent 8e5c3158
......@@ -27,14 +27,15 @@ namespace blink {
class AssociatedInterfaceProvider;
} // namespace blink
namespace on_load_script_injector {
class OnLoadScriptInjectorHost;
} // namespace on_load_script_injector
namespace content {
class WebContents;
} // namespace content
namespace on_load_script_injector {
template <typename>
class OnLoadScriptInjectorHost;
} // namespace on_load_script_injector
namespace chromecast {
class QueryableDataHost;
......@@ -338,7 +339,7 @@ class CastWebContents {
// Returns the script injector instance, which injects scripts at page load
// time.
virtual on_load_script_injector::OnLoadScriptInjectorHost*
virtual on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>*
script_injector() = 0;
// Injects on-load scripts into the WebContents' main frame.
......
......@@ -327,7 +327,7 @@ void CastWebContentsImpl::ClearRenderWidgetHostView() {
}
}
on_load_script_injector::OnLoadScriptInjectorHost*
on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>*
CastWebContentsImpl::script_injector() {
return &script_injector_;
}
......
......@@ -70,7 +70,8 @@ class CastWebContentsImpl : public CastWebContents,
void BlockMediaLoading(bool blocked) override;
void BlockMediaStarting(bool blocked) override;
void EnableBackgroundVideoPlayback(bool enabled) override;
on_load_script_injector::OnLoadScriptInjectorHost* script_injector() override;
on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>*
script_injector() override;
void InjectScriptsIntoMainFrame() override;
void PostMessageToMainFrame(
const std::string& target_origin,
......@@ -175,7 +176,8 @@ class CastWebContentsImpl : public CastWebContents,
bool notifying_;
int last_error_;
on_load_script_injector::OnLoadScriptInjectorHost script_injector_;
on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>
script_injector_;
base::ObserverList<Observer>::Unchecked observer_list_;
......
......@@ -37,10 +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(on_load_script_injector::OnLoadScriptInjectorHost*,
script_injector,
(),
(override));
MOCK_METHOD(
on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>*,
script_injector,
(),
(override));
MOCK_METHOD(void, InjectScriptsIntoMainFrame, (), (override));
MOCK_METHOD(void,
PostMessageToMainFrame,
......
......@@ -9,6 +9,10 @@ mojom("on_load_script_injector_mojom") {
public_deps = [ "//mojo/public/mojom/base" ]
visibility = [ "./*" ]
export_define = "ON_LOAD_SCRIPT_INJECTOR_IMPLEMENTATION=1"
export_class_attribute = "ON_LOAD_SCRIPT_INJECTOR_EXPORT"
export_header = "components/on_load_script_injector/export.h"
}
source_set("export") {
......
......@@ -6,121 +6,20 @@
#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;
OriginScopedScript::OriginScopedScript() = default;
OnLoadScriptInjectorHost::OriginScopedScript::OriginScopedScript(
std::vector<url::Origin> origins,
base::ReadOnlySharedMemoryRegion script)
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) {
OriginScopedScript& OriginScopedScript::operator=(OriginScopedScript&& other) {
origins_ = std::move(other.origins_);
script_ = std::move(other.script_);
return *this;
}
OnLoadScriptInjectorHost::OriginScopedScript::~OriginScopedScript() = default;
OriginScopedScript::~OriginScopedScript() = default;
} // namespace on_load_script_injector
......@@ -10,26 +10,44 @@
#include <vector>
#include "base/memory/read_only_shared_memory_region.h"
#include "base/numerics/safe_math.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/on_load_script_injector/export.h"
#include "components/on_load_script_injector/on_load_script_injector.mojom.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "url/origin.h"
namespace on_load_script_injector {
class ON_LOAD_SCRIPT_INJECTOR_EXPORT 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_;
};
// Manages the set of scripts to be injected into document just prior to
// document load.
class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjectorHost {
template <typename ScriptId>
class OnLoadScriptInjectorHost {
public:
#if defined(OS_FUCHSIA)
using ScriptId = uint64_t;
#else
using ScriptId = std::string;
#endif
OnLoadScriptInjectorHost();
~OnLoadScriptInjectorHost();
OnLoadScriptInjectorHost() = default;
~OnLoadScriptInjectorHost() = default;
OnLoadScriptInjectorHost(const OnLoadScriptInjectorHost&) = delete;
OnLoadScriptInjectorHost& operator=(const OnLoadScriptInjectorHost&) = delete;
......@@ -42,41 +60,92 @@ class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjectorHost {
// 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);
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));
}
// Same as AddScript(), except that scripts are injected for all pages.
void AddScriptForAllOrigins(ScriptId id, base::StringPiece script);
void AddScriptForAllOrigins(ScriptId id, base::StringPiece script) {
AddScript(id, {kMatchAllOrigins}, script);
}
// Removes the script |id|.
void RemoveScript(ScriptId id);
void 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;
}
// 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);
content::RenderFrameHost* render_frame_host) {
DCHECK(url.is_valid());
private:
class OriginScopedScript {
public:
OriginScopedScript();
OriginScopedScript(std::vector<url::Origin> origins,
base::ReadOnlySharedMemoryRegion script);
OriginScopedScript& operator=(OriginScopedScript&& other);
~OriginScopedScript();
mojo::AssociatedRemote<mojom::OnLoadScriptInjector> injector;
render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&injector);
const std::vector<url::Origin>& origins() const { return origins_; }
const base::ReadOnlySharedMemoryRegion& script() const { return script_; }
injector->ClearOnLoadScripts();
private:
std::vector<url::Origin> origins_;
if (before_load_scripts_.empty())
return;
// A shared memory buffer containing the script, encoded as UTF16.
base::ReadOnlySharedMemoryRegion script_;
};
// 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());
}
}
private:
bool IsUrlMatchedByOriginList(
const GURL& url,
const std::vector<url::Origin>& allowed_origins);
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;
}
// An opaque Origin that, when specified, allows script injection on all URLs
// regardless of origin.
......
......@@ -268,7 +268,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_;
on_load_script_injector::OnLoadScriptInjectorHost<uint64_t> script_injector_;
fidl::Binding<fuchsia::web::Frame> binding_;
media_control::MediaBlocker media_blocker_;
......
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