],
'coffee_sources': [
'browser/api/lib/atom.coffee',
+ 'browser/api/lib/ipc.coffee',
'browser/api/lib/window.coffee',
'browser/atom/atom.coffee',
+ 'renderer/api/lib/ipc.coffee',
],
'lib_sources': [
'app/atom_main_delegate.cc',
'app/atom_main_delegate.h',
+ 'browser/api/atom_api_browser_ipc.cc',
+ 'browser/api/atom_api_browser_ipc.h',
'browser/api/atom_api_event.cc',
'browser/api/atom_api_event.h',
'browser/api/atom_api_event_emitter.cc',
'common/options_switches.h',
'common/v8_value_converter_impl.cc',
'common/v8_value_converter_impl.h',
+ 'renderer/api/atom_api_renderer_ipc.cc',
+ 'renderer/api/atom_api_renderer_ipc.h',
'renderer/api/atom_renderer_bindings.cc',
'renderer/api/atom_renderer_bindings.h',
'renderer/atom_render_view_observer.cc',
--- /dev/null
+// 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 "browser/api/atom_api_browser_ipc.h"
+
+#include "base/values.h"
+#include "common/api/api_messages.h"
+#include "common/v8_value_converter_impl.h"
+#include "content/public/browser/render_view_host.h"
+#include "vendor/node/src/node.h"
+#include "vendor/node/src/node_internals.h"
+
+using content::RenderViewHost;
+using content::V8ValueConverter;
+
+namespace atom {
+
+namespace api {
+
+// static
+v8::Handle<v8::Value> BrowserIPC::Send(const v8::Arguments &args) {
+ v8::HandleScope scope;
+
+ if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsString())
+ return node::ThrowTypeError("Bad argument");
+
+ int process_id = args[0]->IntegerValue();
+ int routing_id = args[1]->IntegerValue();
+ std::string channel(*v8::String::Utf8Value(args[2]));
+
+ RenderViewHost* render_view_host(RenderViewHost::FromID(
+ process_id, routing_id));
+ if (!render_view_host)
+ return node::ThrowError("Invalid render view host");
+
+ // Convert Arguments to Array, so we can use V8ValueConverter to convert it
+ // to ListValue.
+ v8::Local<v8::Array> v8_args = v8::Array::New(args.Length() - 3);
+ for (int i = 0; i < args.Length() - 3; ++i)
+ v8_args->Set(i, args[i + 3]);
+
+ scoped_ptr<V8ValueConverter> converter(new V8ValueConverterImpl());
+ scoped_ptr<base::Value> arguments(
+ converter->FromV8Value(v8_args, v8::Context::GetCurrent()));
+
+ DCHECK(arguments && arguments->IsType(base::Value::TYPE_LIST));
+
+ render_view_host->Send(new AtomViewMsg_Message(
+ routing_id,
+ channel,
+ *static_cast<base::ListValue*>(arguments.get())));
+
+ return v8::Undefined();
+}
+
+// static
+void BrowserIPC::Initialize(v8::Handle<v8::Object> target) {
+ node::SetMethod(target, "send", Send);
+}
+
+} // namespace api
+
+} // namespace atom
+
+NODE_MODULE(atom_browser_ipc, atom::api::BrowserIPC::Initialize)
--- /dev/null
+// 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_BROWSER_API_ATOM_API_BROWSER_IPC_H_
+#define ATOM_BROWSER_API_ATOM_API_BROWSER_IPC_H_
+
+#include "base/basictypes.h"
+#include "v8/include/v8.h"
+
+namespace atom {
+
+namespace api {
+
+class BrowserIPC {
+ public:
+ static void Initialize(v8::Handle<v8::Object> target);
+
+ private:
+ static v8::Handle<v8::Value> Send(const v8::Arguments &args);
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(BrowserIPC);
+};
+
+} // namespace api
+
+} // namespace atom
+
+#endif // ATOM_BROWSER_API_ATOM_API_BROWSER_IPC_H_
DCHECK(!browser_main_parts_.IsEmpty());
}
-void AtomBrowserBindings::OnRendererMessage(
- int routing_id, const base::ListValue& args) {
+void AtomBrowserBindings::OnRendererMessage(int process_id,
+ int routing_id,
+ const std::string& channel,
+ const base::ListValue& args) {
v8::HandleScope scope;
v8::Handle<v8::Context> context = v8::Context::GetCurrent();
scoped_ptr<V8ValueConverter> converter(new V8ValueConverterImpl());
std::vector<v8::Handle<v8::Value>> arguments;
- arguments.reserve(2 + args.GetSize());
- arguments.push_back(v8::String::New("message"));
+ arguments.reserve(3 + args.GetSize());
+ arguments.push_back(v8::String::New(channel.c_str(), channel.size()));
+ arguments.push_back(v8::Integer::New(process_id));
arguments.push_back(v8::Integer::New(routing_id));
for (size_t i = 0; i < args.GetSize(); i++) {
#ifndef ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_
#define ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_
+#include <iosfwd>
+
#include "common/api/atom_bindings.h"
namespace base {
virtual void AfterLoad();
// Called when received a message from renderer.
- void OnRendererMessage(int routing_id, const base::ListValue& args);
+ void OnRendererMessage(int process_id,
+ int routing_id,
+ const std::string& channel,
+ const base::ListValue& args);
// The require('atom').browserMainParts object.
v8::Handle<v8::Object> browser_main_parts() {
--- /dev/null
+EventEmitter = require('events').EventEmitter
+send = process.atom_binding('ipc').send
+
+class Ipc extends EventEmitter
+ constructor: ->
+ process.on 'ATOM_INTERNAL_MESSAGE', (args...) =>
+ @emit('message', args...)
+
+ send: (process_id, routing_id, args...) ->
+ send(process_id, routing_id, 'ATOM_INTERNAL_MESSAGE', args...)
+
+module.exports = new Ipc
var atom = require('atom');
+var ipc = require('ipc');
var Window = require('window');
var mainWindow = null;
-process.on('message', function() {
- console.log.apply(this, arguments);
+ipc.on('message', function(process_id, routing_id) {
+ console.log('message from', process_id, routing_id);
+ ipc.send.apply(ipc, arguments);
});
atom.browserMainParts.preMainMessageLoopRun = function() {
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_process_host.h"
#include "common/api/api_messages.h"
#include "common/options_switches.h"
#include "ipc/ipc_message_macros.h"
}
}
-void NativeWindow::OnRendererMessage(const base::ListValue& args) {
+void NativeWindow::OnRendererMessage(const std::string& channel,
+ const base::ListValue& args) {
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage(
- GetWebContents()->GetRoutingID(), args);
+ GetWebContents()->GetRenderProcessHost()->GetID(),
+ GetWebContents()->GetRoutingID(),
+ channel,
+ args);
}
} // namespace atom
const content::NotificationDetails& details) OVERRIDE;
private:
- void OnRendererMessage(const base::ListValue& args);
+ void OnRendererMessage(const std::string& channel,
+ const base::ListValue& args);
// Notification manager.
content::NotificationRegistrar registrar_;
#define IPC_MESSAGE_START ShellMsgStart
-IPC_MESSAGE_ROUTED1(AtomViewHostMsg_Message,
+IPC_MESSAGE_ROUTED2(AtomViewHostMsg_Message,
+ std::string /* channel */,
ListValue /* arguments */)
-IPC_MESSAGE_ROUTED1(AtomViewMsg_Message,
+IPC_MESSAGE_ROUTED2(AtomViewMsg_Message,
+ std::string /* channel */,
ListValue /* arguments */)
NODE_EXT_LIST_START
+NODE_EXT_LIST_ITEM(atom_browser_ipc)
NODE_EXT_LIST_ITEM(atom_browser_window)
+NODE_EXT_LIST_ITEM(atom_renderer_ipc)
+
NODE_EXT_LIST_END
--- /dev/null
+// 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 "renderer/api/atom_api_renderer_ipc.h"
+
+#include "base/values.h"
+#include "common/api/api_messages.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/v8_value_converter.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#include "vendor/node/src/node.h"
+
+using content::RenderView;
+using content::V8ValueConverter;
+using WebKit::WebFrame;
+using WebKit::WebView;
+
+namespace atom {
+
+namespace api {
+
+namespace {
+
+RenderView* GetCurrentRenderView() {
+ WebFrame* frame = WebFrame::frameForCurrentContext();
+ DCHECK(frame);
+ if (!frame)
+ return NULL;
+
+ WebView* view = frame->view();
+ if (!view)
+ return NULL; // can happen during closing.
+
+ RenderView* render_view = RenderView::FromWebView(view);
+ DCHECK(render_view);
+ return render_view;
+}
+
+} // namespace
+
+// static
+v8::Handle<v8::Value> RendererIPC::Send(const v8::Arguments &args) {
+ v8::HandleScope scope;
+
+ if (!args[0]->IsString())
+ return node::ThrowTypeError("Bad argument");
+
+ std::string channel(*v8::String::Utf8Value(args[0]));
+
+ RenderView* render_view = GetCurrentRenderView();
+
+ // Convert Arguments to Array, so we can use V8ValueConverter to convert it
+ // to ListValue.
+ v8::Local<v8::Array> v8_args = v8::Array::New(args.Length() - 1);
+ for (int i = 0; i < args.Length() - 1; ++i)
+ v8_args->Set(i, args[i + 1]);
+
+ scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
+ scoped_ptr<base::Value> arguments(
+ converter->FromV8Value(v8_args, v8::Context::GetCurrent()));
+
+ DCHECK(arguments && arguments->IsType(base::Value::TYPE_LIST));
+
+ render_view->Send(new AtomViewHostMsg_Message(
+ render_view->GetRoutingID(),
+ channel,
+ *static_cast<base::ListValue*>(arguments.get())));
+
+ return v8::Undefined();
+}
+
+// static
+void RendererIPC::Initialize(v8::Handle<v8::Object> target) {
+ node::SetMethod(target, "send", Send);
+}
+
+} // namespace api
+
+} // namespace atom
+
+NODE_MODULE(atom_renderer_ipc, atom::api::RendererIPC::Initialize)
--- /dev/null
+// 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 v8::Handle<v8::Value> Send(const v8::Arguments &args);
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(RendererIPC);
+};
+
+} // namespace api
+
+} // namespace atom
+
+#endif // ATOM_RENDERER_API_ATOM_API_RENDERER_IPC_H_
#include "renderer/api/atom_renderer_bindings.h"
+#include <vector>
+
#include "base/logging.h"
#include "base/values.h"
-#include "common/api/api_messages.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/v8_value_converter.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
using content::RenderView;
using content::V8ValueConverter;
using WebKit::WebFrame;
-using WebKit::WebView;
namespace atom {
return process;
}
-RenderView* GetCurrentRenderView() {
- WebFrame* frame = WebFrame::frameForCurrentContext();
- DCHECK(frame);
- if (!frame)
- return NULL;
-
- WebView* view = frame->view();
- if (!view)
- return NULL; // can happen during closing.
-
- RenderView* render_view = RenderView::FromWebView(view);
- DCHECK(render_view);
- return render_view;
-}
-
} // namespace
AtomRendererBindings::AtomRendererBindings(RenderView* render_view)
AtomBindings::BindTo(GetProcessObject(context));
}
-void AtomRendererBindings::AddIPCBindings(WebFrame* frame) {
- v8::HandleScope handle_scope;
-
- v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
- if (context.IsEmpty())
+void AtomRendererBindings::OnRendererMessage(const std::string& channel,
+ const base::ListValue& args) {
+ if (!render_view_->GetWebView())
return;
- v8::Context::Scope scope(context);
-
- v8::Handle<v8::Object> process = GetProcessObject(context);
-
- node::SetMethod(process, "send", Send);
-}
-
-// static
-v8::Handle<v8::Value> AtomRendererBindings::Send(const v8::Arguments &args) {
v8::HandleScope scope;
- RenderView* render_view = GetCurrentRenderView();
+ v8::Local<v8::Context> context =
+ render_view_->GetWebView()->mainFrame()->mainWorldScriptContext();
+ if (context.IsEmpty())
+ return;
- // Convert Arguments to Array, so we can use V8ValueConverter to convert it
- // to ListValue.
- v8::Local<v8::Array> v8_args = v8::Array::New(args.Length());
- for (int i = 0; i < args.Length(); ++i)
- v8_args->Set(i, args[i]);
+ v8::Context::Scope context_scope(context);
+ v8::Handle<v8::Object> process = GetProcessObject(context);
scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
- scoped_ptr<base::Value> arguments(
- converter->FromV8Value(v8_args, v8::Context::GetCurrent()));
- DCHECK(arguments && arguments->IsType(base::Value::TYPE_LIST));
+ std::vector<v8::Handle<v8::Value>> arguments;
+ arguments.reserve(1 + args.GetSize());
+ arguments.push_back(v8::String::New(channel.c_str(), channel.size()));
- render_view->Send(new AtomViewHostMsg_Message(
- render_view->GetRoutingID(),
- *static_cast<base::ListValue*>(arguments.get())));
+ 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));
+ }
- return v8::Undefined();
+ node::MakeCallback(process, "emit", arguments.size(), &arguments[0]);
}
} // namespace atom
// 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_
-#define ATOM_RENDERER_API_ATOM_RENDERER_BINDINGS_
+#ifndef ATOM_RENDERER_API_ATOM_RENDERER_BINDINGS_H_
+#define ATOM_RENDERER_API_ATOM_RENDERER_BINDINGS_H_
+
+#include <iosfwd>
#include "common/api/atom_bindings.h"
+namespace base {
+class ListValue;
+}
+
namespace content {
class RenderView;
}
// Call BindTo for process object of the frame.
void BindToFrame(WebKit::WebFrame* frame);
- // Add process.send and make process.on accept IPC message.
- void AddIPCBindings(WebKit::WebFrame* frame);
+ // Dispatch messages from browser.
+ void OnRendererMessage(const std::string& channel,
+ const base::ListValue& args);
private:
- static v8::Handle<v8::Value> Send(const v8::Arguments &args);
-
content::RenderView* render_view_;
DISALLOW_COPY_AND_ASSIGN(AtomRendererBindings);
} // namespace atom
-#endif // ATOM_RENDERER_API_ATOM_BINDINGS_
+#endif // ATOM_RENDERER_API_ATOM_BINDINGS_H_
--- /dev/null
+EventEmitter = require('events').EventEmitter
+send = process.atom_binding('ipc').send
+
+class Ipc extends EventEmitter
+ constructor: ->
+ process.on 'ATOM_INTERNAL_MESSAGE', (args...) =>
+ @emit('message', args...)
+
+ send: (args...) ->
+ send('ATOM_INTERNAL_MESSAGE', args...)
+
+module.exports = new Ipc
+++ /dev/null
-RemoteObject = process.atom_binding('remote_object').RemoteObject
-
-module.exports = RemoteObject
#include <algorithm>
#include <vector>
+#include "common/api/api_messages.h"
#include "common/node_bindings.h"
+#include "ipc/ipc_message_macros.h"
#include "renderer/api/atom_renderer_bindings.h"
#include "renderer/atom_renderer_client.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
renderer_client_->node_bindings()->BindTo(frame);
atom_bindings()->BindToFrame(frame);
- atom_bindings()->AddIPCBindings(frame);
}
void AtomRenderViewObserver::FrameWillClose(WebFrame* frame) {
vec.erase(std::remove(vec.begin(), vec.end(), frame), vec.end());
}
+bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(AtomRenderViewObserver, message)
+ IPC_MESSAGE_HANDLER(AtomViewMsg_Message, OnRendererMessage)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+void AtomRenderViewObserver::OnRendererMessage(const std::string& channel,
+ const base::ListValue& args) {
+ atom_bindings()->OnRendererMessage(channel, args);
+}
+
} // namespace atom
#include "base/memory/scoped_ptr.h"
#include "content/public/renderer/render_view_observer.h"
+namespace base {
+class ListValue;
+}
+
namespace atom {
class AtomRendererBindings;
virtual void FrameWillClose(WebKit::WebFrame*) OVERRIDE;
private:
+ // content::RenderViewObserver implementation.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+ void OnRendererMessage(const std::string& channel,
+ const base::ListValue& args);
+
scoped_ptr<AtomRendererBindings> atom_bindings_;
// Weak reference to renderer client.