| Index: headless/lib/renderer/headless_content_renderer_client.cc
|
| diff --git a/headless/lib/renderer/headless_content_renderer_client.cc b/headless/lib/renderer/headless_content_renderer_client.cc
|
| index a82418083d448dedfc8f85a0a448b4aa7bd239ca..b627f692601aabfc5bfe377a2261f2de20a02c89 100644
|
| --- a/headless/lib/renderer/headless_content_renderer_client.cc
|
| +++ b/headless/lib/renderer/headless_content_renderer_client.cc
|
| @@ -7,19 +7,8 @@
|
| #include "base/memory/ptr_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "content/public/common/bindings_policy.h"
|
| -#include "content/public/common/isolated_world_ids.h"
|
| #include "content/public/renderer/render_frame.h"
|
| -#include "content/public/renderer/render_frame_observer.h"
|
| -#include "gin/handle.h"
|
| -#include "gin/object_template_builder.h"
|
| -#include "gin/wrappable.h"
|
| -#include "headless/lib/tab_socket.mojom.h"
|
| #include "printing/features/features.h"
|
| -#include "services/service_manager/public/cpp/interface_provider.h"
|
| -#include "third_party/WebKit/public/platform/WebIsolatedWorldIds.h"
|
| -#include "third_party/WebKit/public/web/WebKit.h"
|
| -#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
| -#include "third_party/WebKit/public/web/WebScriptExecutionCallback.h"
|
|
|
| #if BUILDFLAG(ENABLE_BASIC_PRINTING)
|
| #include "components/printing/renderer/print_web_view_helper.h"
|
| @@ -32,143 +21,77 @@
|
|
|
| HeadlessContentRendererClient::~HeadlessContentRendererClient() {}
|
|
|
| -class HeadlessTabSocketBindings
|
| - : public gin::Wrappable<HeadlessTabSocketBindings>,
|
| - public content::RenderFrameObserver,
|
| - public blink::WebScriptExecutionCallback {
|
| - public:
|
| - explicit HeadlessTabSocketBindings(content::RenderFrame* render_frame)
|
| - : content::RenderFrameObserver(render_frame), weak_ptr_factory_(this) {}
|
| - ~HeadlessTabSocketBindings() override {}
|
| -
|
| - // content::RenderFrameObserver implementation:
|
| - void DidCreateScriptContext(v8::Local<v8::Context> context,
|
| - int world_id) override {
|
| - if (world_id == content::ISOLATED_WORLD_ID_GLOBAL) {
|
| - // For the main world only inject TabSocket if
|
| - // BINDINGS_POLICY_HEADLESS_MAIN_WORLD is set.
|
| - if (!(render_frame()->GetEnabledBindings() &
|
| - content::BindingsPolicy::BINDINGS_POLICY_HEADLESS_MAIN_WORLD)) {
|
| - return;
|
| - }
|
| - } else {
|
| - // For the isolated worlds only inject TabSocket if
|
| - // BINDINGS_POLICY_HEADLESS_ISOLATED_WORLD is set and the world id falls
|
| - // within the range reserved for DevTools created isolated worlds.
|
| - if (!(render_frame()->GetEnabledBindings() &
|
| - content::BindingsPolicy::BINDINGS_POLICY_HEADLESS_ISOLATED_WORLD)) {
|
| - return;
|
| - }
|
| - if (world_id < blink::kDevToolsFirstIsolatedWorldId ||
|
| - world_id > blink::kDevToolsLastIsolatedWorldId) {
|
| - return;
|
| - }
|
| - }
|
| -
|
| - InitializeTabSocketBindings(context);
|
| - }
|
| -
|
| - void WillReleaseScriptContext(v8::Local<v8::Context> context,
|
| - int world_id) override {
|
| - if (context_ == context) {
|
| - on_message_callback_.Reset();
|
| - context_.Reset();
|
| - }
|
| - }
|
| -
|
| - void OnDestruct() override {}
|
| -
|
| - // gin::WrappableBase implementation:
|
| - gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
| - v8::Isolate* isolate) override {
|
| - return gin::Wrappable<HeadlessTabSocketBindings>::GetObjectTemplateBuilder(
|
| - isolate)
|
| - .SetMethod("send", &HeadlessTabSocketBindings::SendImpl)
|
| - .SetProperty("onmessage", &HeadlessTabSocketBindings::GetOnMessage,
|
| - &HeadlessTabSocketBindings::SetOnMessage);
|
| - }
|
| -
|
| - static gin::WrapperInfo kWrapperInfo;
|
| -
|
| - private:
|
| - void SendImpl(const std::string& message) {
|
| - EnsureTabSocketPtr()->SendMessageToEmbedder(message);
|
| - }
|
| -
|
| - v8::Local<v8::Value> GetOnMessage() { return GetOnMessageCallback(); }
|
| -
|
| - void SetOnMessage(v8::Local<v8::Function> callback) {
|
| - on_message_callback_.Reset(blink::MainThreadIsolate(), callback);
|
| -
|
| - EnsureTabSocketPtr()->AwaitNextMessageFromEmbedder(
|
| - base::Bind(&HeadlessTabSocketBindings::OnNextMessageFromEmbedder,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| - }
|
| -
|
| - void OnNextMessageFromEmbedder(const std::string& message) {
|
| - v8::Isolate* isolate = blink::MainThreadIsolate();
|
| - v8::HandleScope handle_scope(isolate);
|
| - v8::Local<v8::Context> context = GetContext();
|
| - v8::Local<v8::Value> argv[] = {
|
| - gin::Converter<std::string>::ToV8(isolate, message),
|
| - };
|
| -
|
| - render_frame()->GetWebFrame()->RequestExecuteV8Function(
|
| - context, GetOnMessageCallback(), context->Global(), arraysize(argv),
|
| - argv, this);
|
| - }
|
| -
|
| - void InitializeTabSocketBindings(v8::Local<v8::Context> context) {
|
| - // Add TabSocket bindings to the DevTools created isolated world.
|
| - v8::Isolate* isolate = blink::MainThreadIsolate();
|
| - v8::HandleScope handle_scope(isolate);
|
| - if (context.IsEmpty())
|
| - return;
|
| -
|
| - v8::Context::Scope context_scope(context);
|
| - gin::Handle<HeadlessTabSocketBindings> bindings =
|
| - gin::CreateHandle(isolate, this);
|
| - if (bindings.IsEmpty())
|
| - return;
|
| -
|
| - v8::Local<v8::Object> global = context->Global();
|
| - global->Set(gin::StringToV8(isolate, "TabSocket"), bindings.ToV8());
|
| - context_.Reset(blink::MainThreadIsolate(), context);
|
| - }
|
| -
|
| - headless::TabSocketPtr& EnsureTabSocketPtr() {
|
| - if (!tab_socket_ptr_.is_bound()) {
|
| - render_frame()->GetRemoteInterfaces()->GetInterface(
|
| - mojo::MakeRequest(&tab_socket_ptr_));
|
| - }
|
| - return tab_socket_ptr_;
|
| - }
|
| -
|
| - v8::Local<v8::Context> GetContext() {
|
| - return v8::Local<v8::Context>::New(blink::MainThreadIsolate(), context_);
|
| - }
|
| -
|
| - v8::Local<v8::Function> GetOnMessageCallback() {
|
| - return v8::Local<v8::Function>::New(blink::MainThreadIsolate(),
|
| - on_message_callback_);
|
| - }
|
| -
|
| - headless::TabSocketPtr tab_socket_ptr_;
|
| - v8::UniquePersistent<v8::Context> context_;
|
| - v8::UniquePersistent<v8::Function> on_message_callback_;
|
| - base::WeakPtrFactory<HeadlessTabSocketBindings> weak_ptr_factory_;
|
| -};
|
| -
|
| -gin::WrapperInfo HeadlessTabSocketBindings::kWrapperInfo = {
|
| - gin::kEmbedderNativeGin};
|
| -
|
| void HeadlessContentRendererClient::RenderFrameCreated(
|
| content::RenderFrame* render_frame) {
|
| #if BUILDFLAG(ENABLE_BASIC_PRINTING)
|
| new printing::PrintWebViewHelper(
|
| render_frame, base::MakeUnique<HeadlessPrintWebViewHelperDelegate>());
|
| #endif
|
| - new HeadlessTabSocketBindings(render_frame);
|
| +}
|
| +
|
| +void HeadlessContentRendererClient::RunScriptsAtDocumentStart(
|
| + content::RenderFrame* render_frame) {
|
| + if (!(render_frame->GetEnabledBindings() &
|
| + content::BindingsPolicy::BINDINGS_POLICY_HEADLESS)) {
|
| + return;
|
| + }
|
| +
|
| + render_frame->ExecuteJavaScript(base::UTF8ToUTF16(R"(
|
| + (function() {
|
| + let tabSocket = null;
|
| + let messagesToSend = [];
|
| +
|
| + function getNextEmbedderMessage() {
|
| + tabSocket.awaitNextMessageFromEmbedder().then(
|
| + function(result) {
|
| + window.TabSocket.onmessage(new CustomEvent(
|
| + "onmessage", {detail : {message : result.message}}));
|
| + getNextEmbedderMessage();
|
| + });
|
| + };
|
| +
|
| + window.TabSocket = new Proxy(
|
| + {
|
| + send: function(message) {
|
| + if (tabSocket) {
|
| + tabSocket.sendMessageToEmbedder(message);
|
| + } else {
|
| + messagesToSend.push(message);
|
| + }
|
| + },
|
| + onmessage: null
|
| + },
|
| + {
|
| + set: function(target, prop, value, receiver) {
|
| + if (prop !== "onmessage")
|
| + return false;
|
| + target[prop] = value;
|
| + if (tabSocket)
|
| + getNextEmbedderMessage();
|
| + return true;
|
| + }
|
| + });
|
| +
|
| + // Note define() defines a module in the mojo module dependency
|
| + // system. While we don't expose our module, the callback below only
|
| + // fires after the requested modules have been loaded.
|
| + define([
|
| + 'headless/lib/tab_socket.mojom',
|
| + 'content/public/renderer/frame_interfaces',
|
| + ], function(tabSocketMojom, frameInterfaces) {
|
| + tabSocket = new tabSocketMojom.TabSocketPtr(
|
| + frameInterfaces.getInterface(tabSocketMojom.TabSocket.name));
|
| + // Send any messages that may have been created before the dependency
|
| + // was resolved.
|
| + for (var i = 0; i < messagesToSend.length; i++) {
|
| + tabSocket.sendMessageToEmbedder(messagesToSend[i]);
|
| + }
|
| + messagesToSend = [];
|
| + if (window.TabSocket.onmessage)
|
| + getNextEmbedderMessage();
|
| + });
|
| +
|
| + })(); )"));
|
| }
|
|
|
| } // namespace headless
|
|
|