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:
Thiago de Arruda 2017-03-31 10:01:33 -03:00
parent 8a324a9375
commit 91ee0ea740
5 changed files with 175 additions and 122 deletions

View 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

View 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_

View file

@ -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

View file

@ -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:

View file

@ -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',