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 { ...@@ -27,14 +27,15 @@ namespace blink {
class AssociatedInterfaceProvider; class AssociatedInterfaceProvider;
} // namespace blink } // namespace blink
namespace on_load_script_injector {
class OnLoadScriptInjectorHost;
} // namespace on_load_script_injector
namespace content { namespace content {
class WebContents; class WebContents;
} // namespace content } // namespace content
namespace on_load_script_injector {
template <typename>
class OnLoadScriptInjectorHost;
} // namespace on_load_script_injector
namespace chromecast { namespace chromecast {
class QueryableDataHost; class QueryableDataHost;
...@@ -338,7 +339,7 @@ class CastWebContents { ...@@ -338,7 +339,7 @@ class CastWebContents {
// Returns the script injector instance, which injects scripts at page load // Returns the script injector instance, which injects scripts at page load
// time. // time.
virtual on_load_script_injector::OnLoadScriptInjectorHost* virtual on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>*
script_injector() = 0; script_injector() = 0;
// Injects on-load scripts into the WebContents' main frame. // Injects on-load scripts into the WebContents' main frame.
......
...@@ -327,7 +327,7 @@ void CastWebContentsImpl::ClearRenderWidgetHostView() { ...@@ -327,7 +327,7 @@ void CastWebContentsImpl::ClearRenderWidgetHostView() {
} }
} }
on_load_script_injector::OnLoadScriptInjectorHost* on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>*
CastWebContentsImpl::script_injector() { CastWebContentsImpl::script_injector() {
return &script_injector_; return &script_injector_;
} }
......
...@@ -70,7 +70,8 @@ class CastWebContentsImpl : public CastWebContents, ...@@ -70,7 +70,8 @@ class CastWebContentsImpl : public CastWebContents,
void BlockMediaLoading(bool blocked) override; void BlockMediaLoading(bool blocked) override;
void BlockMediaStarting(bool blocked) override; void BlockMediaStarting(bool blocked) override;
void EnableBackgroundVideoPlayback(bool enabled) 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 InjectScriptsIntoMainFrame() override;
void PostMessageToMainFrame( void PostMessageToMainFrame(
const std::string& target_origin, const std::string& target_origin,
...@@ -175,7 +176,8 @@ class CastWebContentsImpl : public CastWebContents, ...@@ -175,7 +176,8 @@ class CastWebContentsImpl : public CastWebContents,
bool notifying_; bool notifying_;
int last_error_; 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_; base::ObserverList<Observer>::Unchecked observer_list_;
......
...@@ -37,10 +37,11 @@ class MockCastWebContents : public CastWebContents { ...@@ -37,10 +37,11 @@ class MockCastWebContents : public CastWebContents {
MOCK_METHOD(void, BlockMediaLoading, (bool), (override)); MOCK_METHOD(void, BlockMediaLoading, (bool), (override));
MOCK_METHOD(void, BlockMediaStarting, (bool), (override)); MOCK_METHOD(void, BlockMediaStarting, (bool), (override));
MOCK_METHOD(void, EnableBackgroundVideoPlayback, (bool), (override)); MOCK_METHOD(void, EnableBackgroundVideoPlayback, (bool), (override));
MOCK_METHOD(on_load_script_injector::OnLoadScriptInjectorHost*, MOCK_METHOD(
script_injector, on_load_script_injector::OnLoadScriptInjectorHost<base::StringPiece>*,
(), script_injector,
(override)); (),
(override));
MOCK_METHOD(void, InjectScriptsIntoMainFrame, (), (override)); MOCK_METHOD(void, InjectScriptsIntoMainFrame, (), (override));
MOCK_METHOD(void, MOCK_METHOD(void,
PostMessageToMainFrame, PostMessageToMainFrame,
......
...@@ -9,6 +9,10 @@ mojom("on_load_script_injector_mojom") { ...@@ -9,6 +9,10 @@ mojom("on_load_script_injector_mojom") {
public_deps = [ "//mojo/public/mojom/base" ] public_deps = [ "//mojo/public/mojom/base" ]
visibility = [ "./*" ] 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") { source_set("export") {
......
...@@ -6,121 +6,20 @@ ...@@ -6,121 +6,20 @@
#include <utility> #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 { namespace on_load_script_injector {
OnLoadScriptInjectorHost::OnLoadScriptInjectorHost() = default; OriginScopedScript::OriginScopedScript() = 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( OriginScopedScript::OriginScopedScript(std::vector<url::Origin> origins,
std::vector<url::Origin> origins, base::ReadOnlySharedMemoryRegion script)
base::ReadOnlySharedMemoryRegion script)
: origins_(std::move(origins)), script_(std::move(script)) {} : origins_(std::move(origins)), script_(std::move(script)) {}
OnLoadScriptInjectorHost::OriginScopedScript& OriginScopedScript& OriginScopedScript::operator=(OriginScopedScript&& other) {
OnLoadScriptInjectorHost::OriginScopedScript::operator=(
OnLoadScriptInjectorHost::OriginScopedScript&& other) {
origins_ = std::move(other.origins_); origins_ = std::move(other.origins_);
script_ = std::move(other.script_); script_ = std::move(other.script_);
return *this; return *this;
} }
OnLoadScriptInjectorHost::OriginScopedScript::~OriginScopedScript() = default; OriginScopedScript::~OriginScopedScript() = default;
} // namespace on_load_script_injector } // namespace on_load_script_injector
...@@ -10,26 +10,44 @@ ...@@ -10,26 +10,44 @@
#include <vector> #include <vector>
#include "base/memory/read_only_shared_memory_region.h" #include "base/memory/read_only_shared_memory_region.h"
#include "base/numerics/safe_math.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "components/on_load_script_injector/export.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 "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" #include "url/origin.h"
namespace on_load_script_injector { 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 // Manages the set of scripts to be injected into document just prior to
// document load. // document load.
class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjectorHost { template <typename ScriptId>
class OnLoadScriptInjectorHost {
public: public:
#if defined(OS_FUCHSIA) OnLoadScriptInjectorHost() = default;
using ScriptId = uint64_t; ~OnLoadScriptInjectorHost() = default;
#else
using ScriptId = std::string;
#endif
OnLoadScriptInjectorHost();
~OnLoadScriptInjectorHost();
OnLoadScriptInjectorHost(const OnLoadScriptInjectorHost&) = delete; OnLoadScriptInjectorHost(const OnLoadScriptInjectorHost&) = delete;
OnLoadScriptInjectorHost& operator=(const OnLoadScriptInjectorHost&) = delete; OnLoadScriptInjectorHost& operator=(const OnLoadScriptInjectorHost&) = delete;
...@@ -42,41 +60,92 @@ class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjectorHost { ...@@ -42,41 +60,92 @@ class ON_LOAD_SCRIPT_INJECTOR_EXPORT OnLoadScriptInjectorHost {
// All entries of |origins_to_inject| must be valid/not opaque. // All entries of |origins_to_inject| must be valid/not opaque.
void AddScript(ScriptId id, void AddScript(ScriptId id,
std::vector<url::Origin> origins_to_inject, 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. // 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|. // 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 // Injects the scripts associated with the origin of |url| into the document
// hosted by |render_frame_host|. // hosted by |render_frame_host|.
void InjectScriptsForURL(const GURL& url, void InjectScriptsForURL(const GURL& url,
content::RenderFrameHost* render_frame_host); content::RenderFrameHost* render_frame_host) {
DCHECK(url.is_valid());
private: mojo::AssociatedRemote<mojom::OnLoadScriptInjector> injector;
class OriginScopedScript { render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface(&injector);
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_; } injector->ClearOnLoadScripts();
const base::ReadOnlySharedMemoryRegion& script() const { return script_; }
private: if (before_load_scripts_.empty())
std::vector<url::Origin> origins_; return;
// A shared memory buffer containing the script, encoded as UTF16. // Provision the renderer's ScriptInjector with the scripts associated with
base::ReadOnlySharedMemoryRegion script_; // |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( bool IsUrlMatchedByOriginList(
const GURL& url, 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 // An opaque Origin that, when specified, allows script injection on all URLs
// regardless of origin. // regardless of origin.
......
...@@ -268,7 +268,7 @@ class FrameImpl : public fuchsia::web::Frame, ...@@ -268,7 +268,7 @@ class FrameImpl : public fuchsia::web::Frame,
std::unique_ptr<MediaPlayerImpl> media_player_; std::unique_ptr<MediaPlayerImpl> media_player_;
std::unique_ptr<CastStreamingSessionClient> cast_streaming_session_client_; 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_; fidl::Binding<fuchsia::web::Frame> binding_;
media_control::MediaBlocker media_blocker_; 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