Move all sources under atom/.
This commit is contained in:
parent
26ddbbb0ee
commit
516d46444d
217 changed files with 519 additions and 519 deletions
98
atom/renderer/api/atom_api_renderer_ipc.cc
Normal file
98
atom/renderer/api/atom_api_renderer_ipc.cc
Normal file
|
@ -0,0 +1,98 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/renderer/api/atom_api_renderer_ipc.h"
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "atom/common/v8/native_type_conversions.h"
|
||||
#include "content/public/renderer/render_view.h"
|
||||
#include "third_party/WebKit/public/web/WebFrame.h"
|
||||
#include "third_party/WebKit/public/web/WebView.h"
|
||||
|
||||
#include "atom/common/v8/node_common.h"
|
||||
|
||||
using content::RenderView;
|
||||
using WebKit::WebFrame;
|
||||
using WebKit::WebView;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
namespace {
|
||||
|
||||
RenderView* GetCurrentRenderView() {
|
||||
WebFrame* frame = WebFrame::frameForCurrentContext();
|
||||
if (!frame)
|
||||
return NULL;
|
||||
|
||||
WebView* view = frame->view();
|
||||
if (!view)
|
||||
return NULL; // can happen during closing.
|
||||
|
||||
return RenderView::FromWebView(view);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
void RendererIPC::Send(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
string16 channel;
|
||||
scoped_ptr<base::Value> arguments;
|
||||
if (!FromV8Arguments(args, &channel, &arguments))
|
||||
return node::ThrowTypeError("Bad argument");
|
||||
|
||||
RenderView* render_view = GetCurrentRenderView();
|
||||
if (render_view == NULL)
|
||||
return;
|
||||
|
||||
bool success = render_view->Send(new AtomViewHostMsg_Message(
|
||||
render_view->GetRoutingID(),
|
||||
channel,
|
||||
*static_cast<base::ListValue*>(arguments.get())));
|
||||
|
||||
if (!success)
|
||||
return node::ThrowError("Unable to send AtomViewHostMsg_Message");
|
||||
}
|
||||
|
||||
// static
|
||||
void RendererIPC::SendSync(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
string16 channel;
|
||||
scoped_ptr<base::Value> arguments;
|
||||
if (!FromV8Arguments(args, &channel, &arguments))
|
||||
return node::ThrowTypeError("Bad argument");
|
||||
|
||||
RenderView* render_view = GetCurrentRenderView();
|
||||
if (render_view == NULL)
|
||||
return;
|
||||
|
||||
string16 json;
|
||||
IPC::SyncMessage* message = new AtomViewHostMsg_Message_Sync(
|
||||
render_view->GetRoutingID(),
|
||||
channel,
|
||||
*static_cast<base::ListValue*>(arguments.get()),
|
||||
&json);
|
||||
// Enable the UI thread in browser to receive messages.
|
||||
message->EnableMessagePumping();
|
||||
bool success = render_view->Send(message);
|
||||
|
||||
if (!success)
|
||||
return node::ThrowError("Unable to send AtomViewHostMsg_Message_Sync");
|
||||
|
||||
args.GetReturnValue().Set(ToV8Value(json));
|
||||
}
|
||||
|
||||
// static
|
||||
void RendererIPC::Initialize(v8::Handle<v8::Object> target) {
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
NODE_SET_METHOD(target, "send", Send);
|
||||
NODE_SET_METHOD(target, "sendSync", SendSync);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
NODE_MODULE(atom_renderer_ipc, atom::api::RendererIPC::Initialize)
|
30
atom/renderer/api/atom_api_renderer_ipc.h
Normal file
30
atom/renderer/api/atom_api_renderer_ipc.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_RENDERER_API_ATOM_API_RENDERER_IPC_H_
|
||||
#define ATOM_RENDERER_API_ATOM_API_RENDERER_IPC_H_
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class RendererIPC {
|
||||
public:
|
||||
static void Initialize(v8::Handle<v8::Object> target);
|
||||
|
||||
private:
|
||||
static void Send(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SendSync(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(RendererIPC);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_RENDERER_API_ATOM_API_RENDERER_IPC_H_
|
76
atom/renderer/api/atom_renderer_bindings.cc
Normal file
76
atom/renderer/api/atom_renderer_bindings.cc
Normal file
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/renderer/api/atom_renderer_bindings.h"
|
||||
|
||||
#include "atom/common/v8/native_type_conversions.h"
|
||||
#include "content/public/renderer/render_view.h"
|
||||
#include "third_party/WebKit/public/web/WebFrame.h"
|
||||
#include "third_party/WebKit/public/web/WebView.h"
|
||||
|
||||
#include "atom/common/v8/node_common.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
v8::Handle<v8::Object> GetProcessObject(v8::Handle<v8::Context> context) {
|
||||
v8::Handle<v8::Object> process =
|
||||
context->Global()->Get(v8::String::New("process"))->ToObject();
|
||||
DCHECK(!process.IsEmpty());
|
||||
|
||||
return process;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomRendererBindings::AtomRendererBindings() {
|
||||
}
|
||||
|
||||
AtomRendererBindings::~AtomRendererBindings() {
|
||||
}
|
||||
|
||||
void AtomRendererBindings::BindToFrame(WebKit::WebFrame* frame) {
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
|
||||
if (context.IsEmpty())
|
||||
return;
|
||||
|
||||
v8::Context::Scope scope(context);
|
||||
AtomBindings::BindTo(GetProcessObject(context));
|
||||
}
|
||||
|
||||
void AtomRendererBindings::OnBrowserMessage(content::RenderView* render_view,
|
||||
const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
if (!render_view->GetWebView())
|
||||
return;
|
||||
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
v8::Local<v8::Context> context =
|
||||
render_view->GetWebView()->mainFrame()->mainWorldScriptContext();
|
||||
if (context.IsEmpty())
|
||||
return;
|
||||
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
||||
v8::Handle<v8::Object> process = GetProcessObject(context);
|
||||
scoped_ptr<V8ValueConverter> converter(new V8ValueConverter);
|
||||
|
||||
std::vector<v8::Handle<v8::Value>> arguments;
|
||||
arguments.reserve(1 + args.GetSize());
|
||||
arguments.push_back(ToV8Value(channel));
|
||||
|
||||
for (size_t i = 0; i < args.GetSize(); i++) {
|
||||
const base::Value* value;
|
||||
if (args.Get(i, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, context));
|
||||
}
|
||||
|
||||
node::MakeCallback(process, "emit", arguments.size(), &arguments[0]);
|
||||
}
|
||||
|
||||
} // namespace atom
|
45
atom/renderer/api/atom_renderer_bindings.h
Normal file
45
atom/renderer/api/atom_renderer_bindings.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_RENDERER_API_ATOM_RENDERER_BINDINGS_H_
|
||||
#define ATOM_RENDERER_API_ATOM_RENDERER_BINDINGS_H_
|
||||
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
|
||||
#include "base/strings/string16.h"
|
||||
|
||||
namespace base {
|
||||
class ListValue;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class RenderView;
|
||||
}
|
||||
|
||||
namespace WebKit {
|
||||
class WebFrame;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomRendererBindings : public AtomBindings {
|
||||
public:
|
||||
AtomRendererBindings();
|
||||
virtual ~AtomRendererBindings();
|
||||
|
||||
// Call BindTo for process object of the frame.
|
||||
void BindToFrame(WebKit::WebFrame* frame);
|
||||
|
||||
// Dispatch messages from browser.
|
||||
void OnBrowserMessage(content::RenderView* render_view,
|
||||
const string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomRendererBindings);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_RENDERER_API_ATOM_BINDINGS_H_
|
24
atom/renderer/api/lib/ipc.coffee
Normal file
24
atom/renderer/api/lib/ipc.coffee
Normal file
|
@ -0,0 +1,24 @@
|
|||
EventEmitter = require('events').EventEmitter
|
||||
ipc = process.atomBinding('ipc')
|
||||
|
||||
class Ipc extends EventEmitter
|
||||
constructor: ->
|
||||
process.on 'ATOM_INTERNAL_MESSAGE', (args...) =>
|
||||
@emit args...
|
||||
|
||||
window.addEventListener 'unload', (event) ->
|
||||
process.removeAllListeners 'ATOM_INTERNAL_MESSAGE'
|
||||
|
||||
send: (args...) ->
|
||||
@sendChannel 'message', args...
|
||||
|
||||
sendChannel: (args...) ->
|
||||
ipc.send 'ATOM_INTERNAL_MESSAGE', [args...]
|
||||
|
||||
sendSync: (args...) ->
|
||||
@sendSync 'sync-message', args...
|
||||
|
||||
sendChannelSync: (args...) ->
|
||||
JSON.parse ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', [args...])
|
||||
|
||||
module.exports = new Ipc
|
131
atom/renderer/api/lib/remote.coffee
Normal file
131
atom/renderer/api/lib/remote.coffee
Normal file
|
@ -0,0 +1,131 @@
|
|||
ipc = require 'ipc'
|
||||
CallbacksRegistry = require 'callbacks-registry'
|
||||
v8Util = process.atomBinding 'v8_util'
|
||||
|
||||
callbacksRegistry = new CallbacksRegistry
|
||||
|
||||
# Convert the arguments object into an array of meta data.
|
||||
wrapArgs = (args) ->
|
||||
valueToMeta = (value) ->
|
||||
if Array.isArray value
|
||||
type: 'array', value: wrapArgs(value)
|
||||
else if value? and typeof value is 'object' and v8Util.getHiddenValue value, 'atomId'
|
||||
type: 'remote-object', id: v8Util.getHiddenValue value, 'atomId'
|
||||
else if value? and typeof value is 'object'
|
||||
ret = type: 'object', name: value.constructor.name, members: []
|
||||
ret.members.push(name: prop, value: valueToMeta(field)) for prop, field of value
|
||||
ret
|
||||
else if typeof value is 'function' and v8Util.getHiddenValue value, 'returnValue'
|
||||
type: 'function-with-return-value', value: valueToMeta(value())
|
||||
else if typeof value is 'function'
|
||||
type: 'function', id: callbacksRegistry.add(value)
|
||||
else
|
||||
type: 'value', value: value
|
||||
|
||||
Array::slice.call(args).map valueToMeta
|
||||
|
||||
# Convert meta data from browser into real value.
|
||||
metaToValue = (meta) ->
|
||||
switch meta.type
|
||||
when 'value' then meta.value
|
||||
when 'array' then (metaToValue(el) for el in meta.members)
|
||||
when 'error'
|
||||
throw new Error("#{meta.message}\n#{meta.stack}")
|
||||
else
|
||||
if meta.type is 'function'
|
||||
# A shadow class to represent the remote function object.
|
||||
ret =
|
||||
class RemoteFunction
|
||||
constructor: ->
|
||||
if @constructor == RemoteFunction
|
||||
# Constructor call.
|
||||
obj = ipc.sendChannelSync 'ATOM_BROWSER_CONSTRUCTOR', meta.id, wrapArgs(arguments)
|
||||
|
||||
# Returning object in constructor will replace constructed object
|
||||
# with the returned object.
|
||||
# http://stackoverflow.com/questions/1978049/what-values-can-a-constructor-return-to-avoid-returning-this
|
||||
return metaToValue obj
|
||||
else
|
||||
# Function call.
|
||||
ret = ipc.sendChannelSync 'ATOM_BROWSER_FUNCTION_CALL', meta.id, wrapArgs(arguments)
|
||||
return metaToValue ret
|
||||
else
|
||||
ret = v8Util.createObjectWithName meta.name
|
||||
|
||||
# Polulate delegate members.
|
||||
for member in meta.members
|
||||
do (member) ->
|
||||
if member.type is 'function'
|
||||
ret[member.name] =
|
||||
class RemoteMemberFunction
|
||||
constructor: ->
|
||||
if @constructor is RemoteMemberFunction
|
||||
# Constructor call.
|
||||
obj = ipc.sendChannelSync 'ATOM_BROWSER_MEMBER_CONSTRUCTOR', meta.id, member.name, wrapArgs(arguments)
|
||||
return metaToValue obj
|
||||
else
|
||||
# Call member function.
|
||||
ret = ipc.sendChannelSync 'ATOM_BROWSER_MEMBER_CALL', meta.id, member.name, wrapArgs(arguments)
|
||||
return metaToValue ret
|
||||
else
|
||||
ret.__defineSetter__ member.name, (value) ->
|
||||
# Set member data.
|
||||
ipc.sendChannelSync 'ATOM_BROWSER_MEMBER_SET', meta.id, member.name, value
|
||||
value
|
||||
|
||||
ret.__defineGetter__ member.name, ->
|
||||
# Get member data.
|
||||
ret = ipc.sendChannelSync 'ATOM_BROWSER_MEMBER_GET', meta.id, member.name
|
||||
metaToValue ret
|
||||
|
||||
# Track delegate object's life time, and tell the browser to clean up
|
||||
# when the object is GCed.
|
||||
v8Util.setDestructor ret, ->
|
||||
ipc.sendChannel 'ATOM_BROWSER_DEREFERENCE', meta.storeId
|
||||
|
||||
# Remember object's id.
|
||||
v8Util.setHiddenValue ret, 'atomId', meta.id
|
||||
|
||||
ret
|
||||
|
||||
# Browser calls a callback in renderer.
|
||||
ipc.on 'ATOM_RENDERER_CALLBACK', (id, args) ->
|
||||
callbacksRegistry.apply id, metaToValue(args)
|
||||
|
||||
# A callback in browser is released.
|
||||
ipc.on 'ATOM_RENDERER_RELEASE_CALLBACK', (id) ->
|
||||
callbacksRegistry.remove id
|
||||
|
||||
# Get remote module.
|
||||
# (Just like node's require, the modules are cached permanently, note that this
|
||||
# is safe leak since the object is not expected to get freed in browser)
|
||||
moduleCache = {}
|
||||
exports.require = (module) ->
|
||||
return moduleCache[module] if moduleCache[module]?
|
||||
|
||||
meta = ipc.sendChannelSync 'ATOM_BROWSER_REQUIRE', module
|
||||
moduleCache[module] = metaToValue meta
|
||||
|
||||
# Get current window object.
|
||||
windowCache = null
|
||||
exports.getCurrentWindow = ->
|
||||
return windowCache if windowCache?
|
||||
meta = ipc.sendChannelSync 'ATOM_BROWSER_CURRENT_WINDOW'
|
||||
windowCache = metaToValue meta
|
||||
|
||||
# Get a global object in browser.
|
||||
exports.getGlobal = (name) ->
|
||||
meta = ipc.sendChannelSync 'ATOM_BROWSER_GLOBAL', name
|
||||
metaToValue meta
|
||||
|
||||
# Get the process object in browser.
|
||||
processCache = null
|
||||
exports.__defineGetter__ 'process', ->
|
||||
processCache = exports.getGlobal('process') unless processCache?
|
||||
processCache
|
||||
|
||||
# Create a funtion that will return the specifed value when called in browser.
|
||||
exports.createFunctionWithReturnValue = (returnValue) ->
|
||||
func = -> returnValue
|
||||
v8Util.setHiddenValue func, 'returnValue', true
|
||||
func
|
69
atom/renderer/atom_render_view_observer.cc
Normal file
69
atom/renderer/atom_render_view_observer.cc
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/renderer/atom_render_view_observer.h"
|
||||
|
||||
#include "atom/common/api/api_messages.h"
|
||||
#include "content/public/renderer/render_view.h"
|
||||
#include "ipc/ipc_message_macros.h"
|
||||
#include "atom/renderer/api/atom_renderer_bindings.h"
|
||||
#include "atom/renderer/atom_renderer_client.h"
|
||||
#include "third_party/WebKit/public/web/WebDraggableRegion.h"
|
||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||
#include "third_party/WebKit/public/web/WebFrame.h"
|
||||
#include "third_party/WebKit/public/web/WebView.h"
|
||||
|
||||
#include "atom/common/v8/node_common.h"
|
||||
|
||||
using WebKit::WebFrame;
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomRenderViewObserver::AtomRenderViewObserver(
|
||||
content::RenderView* render_view,
|
||||
AtomRendererClient* renderer_client)
|
||||
: content::RenderViewObserver(render_view),
|
||||
renderer_client_(renderer_client) {
|
||||
}
|
||||
|
||||
AtomRenderViewObserver::~AtomRenderViewObserver() {
|
||||
}
|
||||
|
||||
void AtomRenderViewObserver::DraggableRegionsChanged(WebKit::WebFrame* frame) {
|
||||
WebKit::WebVector<WebKit::WebDraggableRegion> webregions =
|
||||
frame->document().draggableRegions();
|
||||
std::vector<DraggableRegion> regions;
|
||||
for (size_t i = 0; i < webregions.size(); ++i) {
|
||||
DraggableRegion region;
|
||||
region.bounds = webregions[i].bounds;
|
||||
region.draggable = webregions[i].draggable;
|
||||
regions.push_back(region);
|
||||
}
|
||||
Send(new AtomViewHostMsg_UpdateDraggableRegions(routing_id(), regions));
|
||||
}
|
||||
|
||||
bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(AtomRenderViewObserver, message)
|
||||
IPC_MESSAGE_HANDLER(AtomViewMsg_Message, OnBrowserMessage)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void AtomRenderViewObserver::OnBrowserMessage(const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
if (!render_view()->GetWebView())
|
||||
return;
|
||||
|
||||
WebKit::WebFrame* frame = render_view()->GetWebView()->mainFrame();
|
||||
if (!renderer_client_->IsNodeBindingEnabled(frame))
|
||||
return;
|
||||
|
||||
renderer_client_->atom_bindings()->OnBrowserMessage(
|
||||
render_view(), channel, args);
|
||||
}
|
||||
|
||||
} // namespace atom
|
42
atom/renderer/atom_render_view_observer.h
Normal file
42
atom/renderer/atom_render_view_observer.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_RENDERER_ATOM_RENDER_VIEW_OBSERVER_
|
||||
#define ATOM_RENDERER_ATOM_RENDER_VIEW_OBSERVER_
|
||||
|
||||
#include "content/public/renderer/render_view_observer.h"
|
||||
|
||||
namespace base {
|
||||
class ListValue;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomRendererClient;
|
||||
|
||||
class AtomRenderViewObserver : public content::RenderViewObserver {
|
||||
public:
|
||||
explicit AtomRenderViewObserver(content::RenderView* render_view,
|
||||
AtomRendererClient* renderer_client);
|
||||
|
||||
protected:
|
||||
virtual ~AtomRenderViewObserver();
|
||||
|
||||
private:
|
||||
// content::RenderViewObserver implementation.
|
||||
virtual void DraggableRegionsChanged(WebKit::WebFrame* frame) OVERRIDE;
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
|
||||
void OnBrowserMessage(const string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Weak reference to renderer client.
|
||||
AtomRendererClient* renderer_client_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomRenderViewObserver);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_RENDERER_ATOM_RENDER_VIEW_OBSERVER_
|
179
atom/renderer/atom_renderer_client.cc
Normal file
179
atom/renderer/atom_renderer_client.cc
Normal file
|
@ -0,0 +1,179 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/renderer/atom_renderer_client.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "atom/renderer/api/atom_renderer_bindings.h"
|
||||
#include "atom/renderer/atom_render_view_observer.h"
|
||||
#include "third_party/WebKit/public/web/WebDocument.h"
|
||||
#include "third_party/WebKit/public/web/WebFrame.h"
|
||||
|
||||
#include "atom/common/v8/node_common.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// Security tokens.
|
||||
const char* kSecurityAll = "all";
|
||||
const char* kSecurityExceptIframe = "except-iframe";
|
||||
const char* kSecurityManualEnableIframe = "manual-enable-iframe";
|
||||
const char* kSecurityDisable = "disable";
|
||||
const char* kSecurityEnableNodeIntegration = "enable-node-integration";
|
||||
|
||||
// Scheme used by devtools
|
||||
const char* kChromeDevToolsScheme = "chrome-devtools";
|
||||
|
||||
} // namespace
|
||||
|
||||
AtomRendererClient::AtomRendererClient()
|
||||
: node_integration_(EXCEPT_IFRAME),
|
||||
main_frame_(NULL) {
|
||||
// Translate the token.
|
||||
std::string token = CommandLine::ForCurrentProcess()->
|
||||
GetSwitchValueASCII(switches::kNodeIntegration);
|
||||
if (token == kSecurityExceptIframe)
|
||||
node_integration_ = EXCEPT_IFRAME;
|
||||
else if (token == kSecurityManualEnableIframe)
|
||||
node_integration_ = MANUAL_ENABLE_IFRAME;
|
||||
else if (token == kSecurityDisable)
|
||||
node_integration_ = DISABLE;
|
||||
else if (token == kSecurityAll)
|
||||
node_integration_ = ALL;
|
||||
|
||||
if (IsNodeBindingEnabled()) {
|
||||
node_bindings_.reset(NodeBindings::Create(false));
|
||||
atom_bindings_.reset(new AtomRendererBindings);
|
||||
}
|
||||
}
|
||||
|
||||
AtomRendererClient::~AtomRendererClient() {
|
||||
}
|
||||
|
||||
void AtomRendererClient::RenderThreadStarted() {
|
||||
if (!IsNodeBindingEnabled())
|
||||
return;
|
||||
|
||||
node_bindings_->Initialize();
|
||||
node_bindings_->PrepareMessageLoop();
|
||||
|
||||
DCHECK(!global_env);
|
||||
|
||||
// Create a default empty environment which would be used when we need to
|
||||
// run V8 code out of a window context (like running a uv callback).
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(node_isolate);
|
||||
global_env = node::Environment::New(context);
|
||||
}
|
||||
|
||||
void AtomRendererClient::RenderViewCreated(content::RenderView* render_view) {
|
||||
new AtomRenderViewObserver(render_view, this);
|
||||
}
|
||||
|
||||
void AtomRendererClient::DidCreateScriptContext(WebKit::WebFrame* frame,
|
||||
v8::Handle<v8::Context> context,
|
||||
int extension_group,
|
||||
int world_id) {
|
||||
// The first web frame is the main frame.
|
||||
if (main_frame_ == NULL)
|
||||
main_frame_ = frame;
|
||||
|
||||
if (!IsNodeBindingEnabled(frame))
|
||||
return;
|
||||
|
||||
v8::Context::Scope scope(context);
|
||||
|
||||
// Check the existance of process object to prevent duplicate initialization.
|
||||
if (context->Global()->Has(v8::String::New("process")))
|
||||
return;
|
||||
|
||||
// Give the node loop a run to make sure everything is ready.
|
||||
node_bindings_->RunMessageLoop();
|
||||
|
||||
// Setup node environment for each window.
|
||||
node::Environment* env = node_bindings_->CreateEnvironment(context);
|
||||
|
||||
// Add atom-shell extended APIs.
|
||||
atom_bindings_->BindToFrame(frame);
|
||||
|
||||
// Store the created environment.
|
||||
web_page_envs_.push_back(env);
|
||||
|
||||
// Make uv loop being wrapped by window context.
|
||||
if (node_bindings_->uv_env() == NULL)
|
||||
node_bindings_->set_uv_env(env);
|
||||
}
|
||||
|
||||
void AtomRendererClient::WillReleaseScriptContext(
|
||||
WebKit::WebFrame* frame,
|
||||
v8::Handle<v8::Context> context,
|
||||
int world_id) {
|
||||
if (!IsNodeBindingEnabled(frame))
|
||||
return;
|
||||
|
||||
node::Environment* env = node::Environment::GetCurrent(context);
|
||||
if (env == NULL) {
|
||||
LOG(ERROR) << "Encounter a non-node context when releasing script context";
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the environment.
|
||||
web_page_envs_.erase(
|
||||
std::remove(web_page_envs_.begin(), web_page_envs_.end(), env),
|
||||
web_page_envs_.end());
|
||||
|
||||
// Notice that we are not disposing the environment object here, because there
|
||||
// may still be pending uv operations in the uv loop, and when they got done
|
||||
// they would be needing the original environment.
|
||||
// So we are leaking the environment object here, just like Chrome leaking the
|
||||
// memory :) . Since it's only leaked when refreshing or unloading, so as long
|
||||
// as we make sure renderer process is restared then the memory would not be
|
||||
// leaked.
|
||||
// env->Dispose();
|
||||
|
||||
// Wrap the uv loop with another environment.
|
||||
if (env == node_bindings_->uv_env()) {
|
||||
node::Environment* env = web_page_envs_.size() > 0 ? web_page_envs_[0] :
|
||||
NULL;
|
||||
node_bindings_->set_uv_env(env);
|
||||
}
|
||||
}
|
||||
|
||||
bool AtomRendererClient::ShouldFork(WebKit::WebFrame* frame,
|
||||
const GURL& url,
|
||||
const std::string& http_method,
|
||||
bool is_initial_navigation,
|
||||
bool is_server_redirect,
|
||||
bool* send_referrer) {
|
||||
// Handle all the navigations and reloads in browser.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AtomRendererClient::IsNodeBindingEnabled(WebKit::WebFrame* frame) {
|
||||
if (node_integration_ == DISABLE)
|
||||
return false;
|
||||
// Do not pollute devtools.
|
||||
else if (frame != NULL &&
|
||||
GURL(frame->document().url()).SchemeIs(kChromeDevToolsScheme))
|
||||
return false;
|
||||
// Node integration is enabled in main frame unless explictly disabled.
|
||||
else if (frame == main_frame_)
|
||||
return true;
|
||||
else if (node_integration_ == MANUAL_ENABLE_IFRAME &&
|
||||
frame != NULL &&
|
||||
frame->uniqueName().utf8().find(kSecurityEnableNodeIntegration)
|
||||
== std::string::npos)
|
||||
return false;
|
||||
else if (node_integration_ == EXCEPT_IFRAME && frame != NULL)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace atom
|
70
atom/renderer/atom_renderer_client.h
Normal file
70
atom/renderer/atom_renderer_client.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) 2013 GitHub, Inc. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_
|
||||
#define ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "content/public/renderer/content_renderer_client.h"
|
||||
|
||||
namespace node {
|
||||
class Environment;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomRendererBindings;
|
||||
class NodeBindings;
|
||||
|
||||
class AtomRendererClient : public content::ContentRendererClient {
|
||||
public:
|
||||
AtomRendererClient();
|
||||
virtual ~AtomRendererClient();
|
||||
|
||||
bool IsNodeBindingEnabled(WebKit::WebFrame* frame = NULL);
|
||||
|
||||
AtomRendererBindings* atom_bindings() const { return atom_bindings_.get(); }
|
||||
|
||||
private:
|
||||
enum NodeIntegration {
|
||||
ALL,
|
||||
EXCEPT_IFRAME,
|
||||
MANUAL_ENABLE_IFRAME,
|
||||
DISABLE,
|
||||
};
|
||||
|
||||
virtual void RenderThreadStarted() OVERRIDE;
|
||||
virtual void RenderViewCreated(content::RenderView*) OVERRIDE;
|
||||
virtual void DidCreateScriptContext(WebKit::WebFrame* frame,
|
||||
v8::Handle<v8::Context> context,
|
||||
int extension_group,
|
||||
int world_id) OVERRIDE;
|
||||
virtual void WillReleaseScriptContext(WebKit::WebFrame* frame,
|
||||
v8::Handle<v8::Context>,
|
||||
int world_id) OVERRIDE;
|
||||
virtual bool ShouldFork(WebKit::WebFrame* frame,
|
||||
const GURL& url,
|
||||
const std::string& http_method,
|
||||
bool is_initial_navigation,
|
||||
bool is_server_redirect,
|
||||
bool* send_referrer);
|
||||
|
||||
std::vector<node::Environment*> web_page_envs_;
|
||||
|
||||
scoped_ptr<NodeBindings> node_bindings_;
|
||||
scoped_ptr<AtomRendererBindings> atom_bindings_;
|
||||
|
||||
// The level of node integration we should support.
|
||||
NodeIntegration node_integration_;
|
||||
|
||||
// The main frame.
|
||||
WebKit::WebFrame* main_frame_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomRendererClient);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_RENDERER_ATOM_RENDERER_CLIENT_H_
|
46
atom/renderer/lib/init.coffee
Normal file
46
atom/renderer/lib/init.coffee
Normal file
|
@ -0,0 +1,46 @@
|
|||
path = require 'path'
|
||||
Module = require 'module'
|
||||
|
||||
# Expose information of current process.
|
||||
process.__atom_type = 'renderer'
|
||||
process.resourcesPath = path.resolve process.argv[1], '..', '..', '..'
|
||||
|
||||
# We modified the original process.argv to let node.js load the
|
||||
# atom-renderer.js, we need to restore it here.
|
||||
process.argv.splice 1, 1
|
||||
|
||||
# Add renderer/api/lib to require's search paths, which contains javascript part
|
||||
# of Atom's built-in libraries.
|
||||
globalPaths = Module.globalPaths
|
||||
globalPaths.push path.join(process.resourcesPath, 'renderer', 'api', 'lib')
|
||||
# And also app.
|
||||
globalPaths.push path.join(process.resourcesPath, 'app')
|
||||
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init.js')
|
||||
|
||||
# Expose global variables.
|
||||
global.require = require
|
||||
global.module = module
|
||||
|
||||
# Set the __filename to the path of html file if it's file:// protocol.
|
||||
if window.location.protocol is 'file:'
|
||||
pathname =
|
||||
if process.platform is 'win32'
|
||||
window.location.pathname.substr 1
|
||||
else
|
||||
window.location.pathname
|
||||
global.__filename = decodeURIComponent pathname
|
||||
global.__dirname = path.dirname global.__filename
|
||||
|
||||
# Set module's filename so relative require can work as expected.
|
||||
module.filename = global.__filename
|
||||
|
||||
# Also search for module under the html file.
|
||||
module.paths = module.paths.concat Module._nodeModulePaths(global.__dirname)
|
||||
else
|
||||
global.__filename = __filename
|
||||
global.__dirname = __dirname
|
||||
|
||||
# Override default web functions.
|
||||
require path.join(__dirname, 'override')
|
54
atom/renderer/lib/override.coffee
Normal file
54
atom/renderer/lib/override.coffee
Normal file
|
@ -0,0 +1,54 @@
|
|||
# Redirect window.onerror to uncaughtException.
|
||||
window.onerror = (error) ->
|
||||
if global.process.listeners('uncaughtException').length > 0
|
||||
global.process.emit 'uncaughtException', error
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
# Override default window.close, see:
|
||||
# https://github.com/atom/atom-shell/issues/70
|
||||
window.close = ->
|
||||
require('remote').getCurrentWindow().close()
|
||||
|
||||
# Override default window.open.
|
||||
window.open = (url, name, features) ->
|
||||
options = {}
|
||||
for feature in features.split ','
|
||||
[name, value] = feature.split '='
|
||||
options[name] =
|
||||
if value is 'yes'
|
||||
true
|
||||
else if value is 'no'
|
||||
false
|
||||
else
|
||||
value
|
||||
|
||||
options.x ?= options.left
|
||||
options.y ?= options.top
|
||||
options.title ?= name
|
||||
options.width ?= 800
|
||||
options.height ?= 600
|
||||
|
||||
BrowserWindow = require('remote').require 'browser-window'
|
||||
browser = new BrowserWindow options
|
||||
browser.loadUrl url
|
||||
browser
|
||||
|
||||
# Use the dialog API to implement alert().
|
||||
window.alert = (message, title='') ->
|
||||
remote = require 'remote'
|
||||
dialog = remote.require 'dialog'
|
||||
buttons = ['OK']
|
||||
dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
|
||||
|
||||
# And the confirm().
|
||||
window.confirm = (message, title='') ->
|
||||
remote = require 'remote'
|
||||
dialog = remote.require 'dialog'
|
||||
buttons = ['OK', 'Cancel']
|
||||
not dialog.showMessageBox remote.getCurrentWindow(), {message, title, buttons}
|
||||
|
||||
# But we do not support prompt().
|
||||
window.prompt = ->
|
||||
throw new Error('prompt() is and will not be supported in atom-shell.')
|
14
atom/renderer/resources/mac/Info.plist
Normal file
14
atom/renderer/resources/mac/Info.plist
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.github.atom.helper</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>LSUIElement</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
Loading…
Add table
Add a link
Reference in a new issue