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/options_switches.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/node_array_buffer_bridge.h"
|
||||
#include "atom/renderer/web_worker_observer.h"
|
||||
#include "base/command_line.h"
|
||||
#include "content/public/renderer/render_frame.h"
|
||||
#include "content/public/renderer/render_frame_observer.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||
#include "third_party/WebKit/public/web/WebLocalFrame.h"
|
||||
|
@ -33,127 +33,6 @@ namespace atom {
|
|||
|
||||
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) {
|
||||
return static_cast<GURL>(render_frame->GetWebFrame()->document().url())
|
||||
.SchemeIs("chrome-extension");
|
||||
|
@ -307,4 +186,38 @@ v8::Local<v8::Context> AtomRendererClient::GetContext(
|
|||
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
|
||||
|
|
|
@ -29,6 +29,7 @@ class AtomRendererClient : public RendererClientBase {
|
|||
// Get the context that the Electron API is running in.
|
||||
v8::Local<v8::Context> GetContext(
|
||||
blink::WebFrame* frame, v8::Isolate* isolate);
|
||||
void SetupMainWorldOverrides(v8::Handle<v8::Context> context);
|
||||
bool isolated_world() { return isolated_world_; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -468,6 +468,8 @@
|
|||
'atom/renderer/api/atom_api_spell_check_client.h',
|
||||
'atom/renderer/api/atom_api_web_frame.cc',
|
||||
'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.h',
|
||||
'atom/renderer/atom_renderer_client.cc',
|
||||
|
|
Loading…
Reference in a new issue