Move AtomRenderFrameObserver into a separate module.
Also move SetupMainWorldOverrides into the AtomRendererClient class(since the code there is specific to AtomRendererClient).
This commit is contained in:
parent
8a324a9375
commit
91ee0ea740
5 changed files with 175 additions and 122 deletions
84
atom/renderer/atom_render_frame_observer.cc
Normal file
84
atom/renderer/atom_render_frame_observer.cc
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright (c) 2017 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/renderer/atom_render_frame_observer.h"
|
||||||
|
|
||||||
|
#include "content/public/renderer/render_frame.h"
|
||||||
|
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||||
|
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
||||||
|
#include "third_party/WebKit/public/web/WebScriptSource.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
AtomRenderFrameObserver::AtomRenderFrameObserver(
|
||||||
|
content::RenderFrame* frame,
|
||||||
|
AtomRendererClient* renderer_client)
|
||||||
|
: content::RenderFrameObserver(frame),
|
||||||
|
render_frame_(frame),
|
||||||
|
renderer_client_(renderer_client) {}
|
||||||
|
|
||||||
|
void AtomRenderFrameObserver::DidClearWindowObject() {
|
||||||
|
renderer_client_->DidClearWindowObject(render_frame_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomRenderFrameObserver::DidCreateScriptContext(
|
||||||
|
v8::Handle<v8::Context> context,
|
||||||
|
int extension_group,
|
||||||
|
int world_id) {
|
||||||
|
if (ShouldNotifyClient(world_id))
|
||||||
|
renderer_client_->DidCreateScriptContext(context, render_frame_);
|
||||||
|
|
||||||
|
if (renderer_client_->isolated_world() && IsMainWorld(world_id)
|
||||||
|
&& render_frame_->IsMainFrame()) {
|
||||||
|
CreateIsolatedWorldContext();
|
||||||
|
renderer_client_->SetupMainWorldOverrides(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomRenderFrameObserver::WillReleaseScriptContext(
|
||||||
|
v8::Local<v8::Context> context,
|
||||||
|
int world_id) {
|
||||||
|
if (ShouldNotifyClient(world_id))
|
||||||
|
renderer_client_->WillReleaseScriptContext(context, render_frame_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomRenderFrameObserver::OnDestruct() {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomRenderFrameObserver::CreateIsolatedWorldContext() {
|
||||||
|
auto frame = render_frame_->GetWebFrame();
|
||||||
|
|
||||||
|
// This maps to the name shown in the context combo box in the Console tab
|
||||||
|
// of the dev tools.
|
||||||
|
frame->setIsolatedWorldHumanReadableName(
|
||||||
|
World::ISOLATED_WORLD,
|
||||||
|
blink::WebString::fromUTF8("Electron Isolated Context"));
|
||||||
|
|
||||||
|
// Setup document's origin policy in isolated world
|
||||||
|
frame->setIsolatedWorldSecurityOrigin(
|
||||||
|
World::ISOLATED_WORLD, frame->document().getSecurityOrigin());
|
||||||
|
|
||||||
|
// Create initial script context in isolated world
|
||||||
|
blink::WebScriptSource source("void 0");
|
||||||
|
frame->executeScriptInIsolatedWorld(
|
||||||
|
World::ISOLATED_WORLD, &source, 1, ExtensionGroup::MAIN_GROUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtomRenderFrameObserver::IsMainWorld(int world_id) {
|
||||||
|
return world_id == World::MAIN_WORLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtomRenderFrameObserver::IsIsolatedWorld(int world_id) {
|
||||||
|
return world_id == World::ISOLATED_WORLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AtomRenderFrameObserver::ShouldNotifyClient(int world_id) {
|
||||||
|
if (renderer_client_->isolated_world() && render_frame_->IsMainFrame())
|
||||||
|
return IsIsolatedWorld(world_id);
|
||||||
|
else
|
||||||
|
return IsMainWorld(world_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
53
atom/renderer/atom_render_frame_observer.h
Normal file
53
atom/renderer/atom_render_frame_observer.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright (c) 2017 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ATOM_RENDERER_ATOM_RENDER_FRAME_OBSERVER_H_
|
||||||
|
#define ATOM_RENDERER_ATOM_RENDER_FRAME_OBSERVER_H_
|
||||||
|
|
||||||
|
#include "atom/renderer/atom_renderer_client.h"
|
||||||
|
#include "content/public/renderer/render_frame_observer.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
enum World {
|
||||||
|
MAIN_WORLD = 0,
|
||||||
|
// Use a high number far away from 0 to not collide with any other world
|
||||||
|
// IDs created internally by Chrome.
|
||||||
|
ISOLATED_WORLD = 999
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ExtensionGroup {
|
||||||
|
MAIN_GROUP = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper class to forward the messages to the client.
|
||||||
|
class AtomRenderFrameObserver : public content::RenderFrameObserver {
|
||||||
|
public:
|
||||||
|
AtomRenderFrameObserver(content::RenderFrame* frame,
|
||||||
|
AtomRendererClient* renderer_client);
|
||||||
|
|
||||||
|
// content::RenderFrameObserver:
|
||||||
|
void DidClearWindowObject() override;
|
||||||
|
void DidCreateScriptContext(v8::Handle<v8::Context> context,
|
||||||
|
int extension_group,
|
||||||
|
int world_id) override;
|
||||||
|
void WillReleaseScriptContext(v8::Local<v8::Context> context,
|
||||||
|
int world_id) override;
|
||||||
|
void OnDestruct() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool ShouldNotifyClient(int world_id);
|
||||||
|
void CreateIsolatedWorldContext();
|
||||||
|
bool IsMainWorld(int world_id);
|
||||||
|
bool IsIsolatedWorld(int world_id);
|
||||||
|
|
||||||
|
content::RenderFrame* render_frame_;
|
||||||
|
AtomRendererClient* renderer_client_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(AtomRenderFrameObserver);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_RENDERER_ATOM_RENDER_FRAME_OBSERVER_H_
|
|
@ -16,12 +16,12 @@
|
||||||
#include "atom/common/node_bindings.h"
|
#include "atom/common/node_bindings.h"
|
||||||
#include "atom/common/options_switches.h"
|
#include "atom/common/options_switches.h"
|
||||||
#include "atom/renderer/api/atom_api_renderer_ipc.h"
|
#include "atom/renderer/api/atom_api_renderer_ipc.h"
|
||||||
|
#include "atom/renderer/atom_render_frame_observer.h"
|
||||||
#include "atom/renderer/atom_render_view_observer.h"
|
#include "atom/renderer/atom_render_view_observer.h"
|
||||||
#include "atom/renderer/node_array_buffer_bridge.h"
|
#include "atom/renderer/node_array_buffer_bridge.h"
|
||||||
#include "atom/renderer/web_worker_observer.h"
|
#include "atom/renderer/web_worker_observer.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "content/public/renderer/render_frame.h"
|
#include "content/public/renderer/render_frame.h"
|
||||||
#include "content/public/renderer/render_frame_observer.h"
|
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||||
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
||||||
|
@ -33,127 +33,6 @@ namespace atom {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum World {
|
|
||||||
MAIN_WORLD = 0,
|
|
||||||
// Use a high number far away from 0 to not collide with any other world
|
|
||||||
// IDs created internally by Chrome.
|
|
||||||
ISOLATED_WORLD = 999
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ExtensionGroup {
|
|
||||||
MAIN_GROUP = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper class to forward the messages to the client.
|
|
||||||
class AtomRenderFrameObserver : public content::RenderFrameObserver {
|
|
||||||
public:
|
|
||||||
AtomRenderFrameObserver(content::RenderFrame* frame,
|
|
||||||
AtomRendererClient* renderer_client)
|
|
||||||
: content::RenderFrameObserver(frame),
|
|
||||||
render_frame_(frame),
|
|
||||||
renderer_client_(renderer_client) {}
|
|
||||||
|
|
||||||
// content::RenderFrameObserver:
|
|
||||||
void DidClearWindowObject() override {
|
|
||||||
renderer_client_->DidClearWindowObject(render_frame_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreateIsolatedWorldContext() {
|
|
||||||
auto frame = render_frame_->GetWebFrame();
|
|
||||||
|
|
||||||
// This maps to the name shown in the context combo box in the Console tab
|
|
||||||
// of the dev tools.
|
|
||||||
frame->setIsolatedWorldHumanReadableName(
|
|
||||||
World::ISOLATED_WORLD,
|
|
||||||
blink::WebString::fromUTF8("Electron Isolated Context"));
|
|
||||||
|
|
||||||
// Setup document's origin policy in isolated world
|
|
||||||
frame->setIsolatedWorldSecurityOrigin(
|
|
||||||
World::ISOLATED_WORLD, frame->document().getSecurityOrigin());
|
|
||||||
|
|
||||||
// Create initial script context in isolated world
|
|
||||||
blink::WebScriptSource source("void 0");
|
|
||||||
frame->executeScriptInIsolatedWorld(
|
|
||||||
World::ISOLATED_WORLD, &source, 1, ExtensionGroup::MAIN_GROUP);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupMainWorldOverrides(v8::Handle<v8::Context> context) {
|
|
||||||
// Setup window overrides in the main world context
|
|
||||||
v8::Isolate* isolate = context->GetIsolate();
|
|
||||||
|
|
||||||
// Wrap the bundle into a function that receives the binding object as
|
|
||||||
// an argument.
|
|
||||||
std::string bundle(node::isolated_bundle_data,
|
|
||||||
node::isolated_bundle_data + sizeof(node::isolated_bundle_data));
|
|
||||||
std::string wrapper = "(function (binding, require) {\n" + bundle + "\n})";
|
|
||||||
auto script = v8::Script::Compile(
|
|
||||||
mate::ConvertToV8(isolate, wrapper)->ToString());
|
|
||||||
auto func = v8::Handle<v8::Function>::Cast(
|
|
||||||
script->Run(context).ToLocalChecked());
|
|
||||||
|
|
||||||
auto binding = v8::Object::New(isolate);
|
|
||||||
api::Initialize(binding, v8::Null(isolate), context, nullptr);
|
|
||||||
|
|
||||||
// Pass in CLI flags needed to setup window
|
|
||||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
|
||||||
mate::Dictionary dict(isolate, binding);
|
|
||||||
if (command_line->HasSwitch(switches::kGuestInstanceID))
|
|
||||||
dict.Set(options::kGuestInstanceID,
|
|
||||||
command_line->GetSwitchValueASCII(switches::kGuestInstanceID));
|
|
||||||
if (command_line->HasSwitch(switches::kOpenerID))
|
|
||||||
dict.Set(options::kOpenerID,
|
|
||||||
command_line->GetSwitchValueASCII(switches::kOpenerID));
|
|
||||||
dict.Set("hiddenPage", command_line->HasSwitch(switches::kHiddenPage));
|
|
||||||
|
|
||||||
v8::Local<v8::Value> args[] = { binding };
|
|
||||||
ignore_result(func->Call(context, v8::Null(isolate), 1, args));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsMainWorld(int world_id) {
|
|
||||||
return world_id == World::MAIN_WORLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsIsolatedWorld(int world_id) {
|
|
||||||
return world_id == World::ISOLATED_WORLD;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShouldNotifyClient(int world_id) {
|
|
||||||
if (renderer_client_->isolated_world() && render_frame_->IsMainFrame())
|
|
||||||
return IsIsolatedWorld(world_id);
|
|
||||||
else
|
|
||||||
return IsMainWorld(world_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DidCreateScriptContext(v8::Handle<v8::Context> context,
|
|
||||||
int extension_group,
|
|
||||||
int world_id) override {
|
|
||||||
if (ShouldNotifyClient(world_id))
|
|
||||||
renderer_client_->DidCreateScriptContext(context, render_frame_);
|
|
||||||
|
|
||||||
if (renderer_client_->isolated_world() && IsMainWorld(world_id)
|
|
||||||
&& render_frame_->IsMainFrame()) {
|
|
||||||
CreateIsolatedWorldContext();
|
|
||||||
SetupMainWorldOverrides(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WillReleaseScriptContext(v8::Local<v8::Context> context,
|
|
||||||
int world_id) override {
|
|
||||||
if (ShouldNotifyClient(world_id))
|
|
||||||
renderer_client_->WillReleaseScriptContext(context, render_frame_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnDestruct() override {
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
content::RenderFrame* render_frame_;
|
|
||||||
AtomRendererClient* renderer_client_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(AtomRenderFrameObserver);
|
|
||||||
};
|
|
||||||
|
|
||||||
bool IsDevToolsExtension(content::RenderFrame* render_frame) {
|
bool IsDevToolsExtension(content::RenderFrame* render_frame) {
|
||||||
return static_cast<GURL>(render_frame->GetWebFrame()->document().url())
|
return static_cast<GURL>(render_frame->GetWebFrame()->document().url())
|
||||||
.SchemeIs("chrome-extension");
|
.SchemeIs("chrome-extension");
|
||||||
|
@ -307,4 +186,38 @@ v8::Local<v8::Context> AtomRendererClient::GetContext(
|
||||||
return frame->mainWorldScriptContext();
|
return frame->mainWorldScriptContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AtomRendererClient::SetupMainWorldOverrides(
|
||||||
|
v8::Handle<v8::Context> context) {
|
||||||
|
// Setup window overrides in the main world context
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
|
||||||
|
// Wrap the bundle into a function that receives the binding object as
|
||||||
|
// an argument.
|
||||||
|
std::string bundle(node::isolated_bundle_data,
|
||||||
|
node::isolated_bundle_data + sizeof(node::isolated_bundle_data));
|
||||||
|
std::string wrapper = "(function (binding, require) {\n" + bundle + "\n})";
|
||||||
|
auto script = v8::Script::Compile(
|
||||||
|
mate::ConvertToV8(isolate, wrapper)->ToString());
|
||||||
|
auto func = v8::Handle<v8::Function>::Cast(
|
||||||
|
script->Run(context).ToLocalChecked());
|
||||||
|
|
||||||
|
auto binding = v8::Object::New(isolate);
|
||||||
|
api::Initialize(binding, v8::Null(isolate), context, nullptr);
|
||||||
|
|
||||||
|
// Pass in CLI flags needed to setup window
|
||||||
|
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||||
|
mate::Dictionary dict(isolate, binding);
|
||||||
|
if (command_line->HasSwitch(switches::kGuestInstanceID))
|
||||||
|
dict.Set(options::kGuestInstanceID,
|
||||||
|
command_line->GetSwitchValueASCII(switches::kGuestInstanceID));
|
||||||
|
if (command_line->HasSwitch(switches::kOpenerID))
|
||||||
|
dict.Set(options::kOpenerID,
|
||||||
|
command_line->GetSwitchValueASCII(switches::kOpenerID));
|
||||||
|
dict.Set("hiddenPage", command_line->HasSwitch(switches::kHiddenPage));
|
||||||
|
|
||||||
|
v8::Local<v8::Value> args[] = { binding };
|
||||||
|
ignore_result(func->Call(context, v8::Null(isolate), 1, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -29,6 +29,7 @@ class AtomRendererClient : public RendererClientBase {
|
||||||
// Get the context that the Electron API is running in.
|
// Get the context that the Electron API is running in.
|
||||||
v8::Local<v8::Context> GetContext(
|
v8::Local<v8::Context> GetContext(
|
||||||
blink::WebFrame* frame, v8::Isolate* isolate);
|
blink::WebFrame* frame, v8::Isolate* isolate);
|
||||||
|
void SetupMainWorldOverrides(v8::Handle<v8::Context> context);
|
||||||
bool isolated_world() { return isolated_world_; }
|
bool isolated_world() { return isolated_world_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -468,6 +468,8 @@
|
||||||
'atom/renderer/api/atom_api_spell_check_client.h',
|
'atom/renderer/api/atom_api_spell_check_client.h',
|
||||||
'atom/renderer/api/atom_api_web_frame.cc',
|
'atom/renderer/api/atom_api_web_frame.cc',
|
||||||
'atom/renderer/api/atom_api_web_frame.h',
|
'atom/renderer/api/atom_api_web_frame.h',
|
||||||
|
'atom/renderer/atom_render_frame_observer.cc',
|
||||||
|
'atom/renderer/atom_render_frame_observer.h',
|
||||||
'atom/renderer/atom_render_view_observer.cc',
|
'atom/renderer/atom_render_view_observer.cc',
|
||||||
'atom/renderer/atom_render_view_observer.h',
|
'atom/renderer/atom_render_view_observer.h',
|
||||||
'atom/renderer/atom_renderer_client.cc',
|
'atom/renderer/atom_renderer_client.cc',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue