Handle IPC messages in webContents instead of BrowserWindow.
This commit is contained in:
parent
1815f8b40d
commit
c0875864dc
21 changed files with 138 additions and 421 deletions
|
@ -1,37 +0,0 @@
|
|||
// 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/common/api/api_messages.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
using content::RenderViewHost;
|
||||
|
||||
namespace {
|
||||
|
||||
bool Send(const string16& channel, int process_id, int routing_id,
|
||||
const base::ListValue& arguments) {
|
||||
RenderViewHost* render_view_host(RenderViewHost::FromID(
|
||||
process_id, routing_id));
|
||||
if (!render_view_host) {
|
||||
node::ThrowError("Invalid render view host");
|
||||
return false;
|
||||
}
|
||||
|
||||
return render_view_host->Send(new AtomViewMsg_Message(routing_id, channel,
|
||||
arguments));
|
||||
}
|
||||
|
||||
void Initialize(v8::Handle<v8::Object> exports) {
|
||||
mate::Dictionary dict(v8::Isolate::GetCurrent(), exports);
|
||||
dict.SetMethod("send", &Send);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE(atom_browser_ipc, Initialize)
|
|
@ -8,6 +8,7 @@
|
|||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
@ -48,6 +49,18 @@ void WebContents::DidStopLoading(content::RenderViewHost* render_view_host) {
|
|||
Emit("did-stop-loading");
|
||||
}
|
||||
|
||||
bool WebContents::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(WebContents, message)
|
||||
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync,
|
||||
OnRendererMessageSync)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void WebContents::WebContentsDestroyed(content::WebContents*) {
|
||||
// The RenderViewDeleted was not called when the WebContents is destroyed.
|
||||
RenderViewDeleted(web_contents_->GetRenderViewHost());
|
||||
|
@ -166,7 +179,20 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
|||
.SetMethod("getProcessId", &WebContents::GetProcessID)
|
||||
.SetMethod("isCrashed", &WebContents::IsCrashed)
|
||||
.SetMethod("executeJavaScript", &WebContents::ExecuteJavaScript)
|
||||
.SetMethod("send", &WebContents::SendIPCMessage);
|
||||
.SetMethod("_send", &WebContents::SendIPCMessage);
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessage(const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
// webContents.emit(channel, new Event(), args...);
|
||||
Emit(UTF16ToUTF8(channel), args, web_contents(), NULL);
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessageSync(const string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message) {
|
||||
// webContents.emit(channel, new Event(sender, message), args...);
|
||||
Emit(UTF16ToUTF8(channel), args, web_contents(), message);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -60,9 +60,18 @@ class WebContents : public mate::EventEmitter,
|
|||
content::RenderViewHost* render_view_host) OVERRIDE;
|
||||
virtual void DidStopLoading(
|
||||
content::RenderViewHost* render_view_host) OVERRIDE;
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
|
||||
virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE;
|
||||
|
||||
private:
|
||||
// Called when received a message from renderer.
|
||||
void OnRendererMessage(const string16& channel, const base::ListValue& args);
|
||||
|
||||
// Called when received a synchronous message from renderer.
|
||||
void OnRendererMessageSync(const string16& channel,
|
||||
const base::ListValue& args,
|
||||
IPC::Message* message);
|
||||
|
||||
content::WebContents* web_contents_; // Weak.
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebContents);
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
// 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/browser/api/atom_browser_bindings.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/event.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "atom/common/native_mate_converters/v8_value_converter.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/values.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomBrowserBindings::AtomBrowserBindings() {
|
||||
}
|
||||
|
||||
void AtomBrowserBindings::OnRendererMessage(int process_id,
|
||||
int routing_id,
|
||||
const string16& channel,
|
||||
const base::ListValue& args) {
|
||||
v8::Locker locker(node_isolate);
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
scoped_ptr<V8ValueConverter> converter(new V8ValueConverter);
|
||||
|
||||
// process.emit(channel, 'message', process_id, routing_id);
|
||||
std::vector<v8::Handle<v8::Value>> arguments;
|
||||
arguments.reserve(3 + args.GetSize());
|
||||
arguments.push_back(mate::ConvertToV8(node_isolate, channel));
|
||||
const base::Value* value;
|
||||
if (args.Get(0, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, global_env->context()));
|
||||
arguments.push_back(v8::Integer::New(process_id));
|
||||
arguments.push_back(v8::Integer::New(routing_id));
|
||||
|
||||
for (size_t i = 1; i < args.GetSize(); i++) {
|
||||
const base::Value* value;
|
||||
if (args.Get(i, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, global_env->context()));
|
||||
}
|
||||
|
||||
node::MakeCallback(global_env->process_object(),
|
||||
"emit",
|
||||
arguments.size(),
|
||||
&arguments[0]);
|
||||
}
|
||||
|
||||
void AtomBrowserBindings::OnRendererMessageSync(
|
||||
int process_id,
|
||||
int routing_id,
|
||||
const string16& channel,
|
||||
const base::ListValue& args,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message) {
|
||||
v8::Locker locker(node_isolate);
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
scoped_ptr<V8ValueConverter> converter(new V8ValueConverter);
|
||||
|
||||
// Create the event object.
|
||||
mate::Handle<mate::Event> event = mate::Event::Create(node_isolate);
|
||||
event->SetSenderAndMessage(sender, message);
|
||||
|
||||
// process.emit(channel, 'sync-message', event, process_id, routing_id);
|
||||
std::vector<v8::Handle<v8::Value>> arguments;
|
||||
arguments.reserve(3 + args.GetSize());
|
||||
arguments.push_back(mate::ConvertToV8(node_isolate, channel));
|
||||
const base::Value* value;
|
||||
if (args.Get(0, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, global_env->context()));
|
||||
arguments.push_back(event.ToV8());
|
||||
arguments.push_back(v8::Integer::New(process_id));
|
||||
arguments.push_back(v8::Integer::New(routing_id));
|
||||
|
||||
for (size_t i = 1; i < args.GetSize(); i++) {
|
||||
const base::Value* value;
|
||||
if (args.Get(i, &value))
|
||||
arguments.push_back(converter->ToV8Value(value, global_env->context()));
|
||||
}
|
||||
|
||||
node::MakeCallback(global_env->process_object(),
|
||||
"emit",
|
||||
arguments.size(),
|
||||
&arguments[0]);
|
||||
}
|
||||
|
||||
} // namespace atom
|
|
@ -1,49 +0,0 @@
|
|||
// 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_BROWSER_BINDINGS_H_
|
||||
#define ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_H_
|
||||
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "base/strings/string16.h"
|
||||
|
||||
namespace base {
|
||||
class ListValue;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomBrowserBindings : public AtomBindings {
|
||||
public:
|
||||
AtomBrowserBindings();
|
||||
|
||||
// Called when received a message from renderer.
|
||||
void OnRendererMessage(int process_id,
|
||||
int routing_id,
|
||||
const string16& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Called when received a synchronous message from renderer.
|
||||
void OnRendererMessageSync(int process_id,
|
||||
int routing_id,
|
||||
const string16& channel,
|
||||
const base::ListValue& args,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserBindings);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_API_ATOM_BROWSER_BINDINGS_H_
|
|
@ -24,6 +24,13 @@ bool EventEmitter::Emit(const base::StringPiece& name) {
|
|||
|
||||
bool EventEmitter::Emit(const base::StringPiece& name,
|
||||
const base::ListValue& args) {
|
||||
return Emit(name, args, NULL, NULL);
|
||||
}
|
||||
|
||||
bool EventEmitter::Emit(const base::StringPiece& name,
|
||||
const base::ListValue& args,
|
||||
content::WebContents* sender,
|
||||
IPC::Message* message) {
|
||||
v8::Locker locker(node_isolate);
|
||||
v8::HandleScope handle_scope(node_isolate);
|
||||
|
||||
|
@ -31,6 +38,8 @@ bool EventEmitter::Emit(const base::StringPiece& name,
|
|||
scoped_ptr<atom::V8ValueConverter> converter(new atom::V8ValueConverter);
|
||||
|
||||
mate::Handle<mate::Event> event = mate::Event::Create(node_isolate);
|
||||
if (sender && message)
|
||||
event->SetSenderAndMessage(sender, message);
|
||||
|
||||
// v8_args = [name, event, args...];
|
||||
std::vector<v8::Handle<v8::Value>> v8_args;
|
||||
|
|
|
@ -11,6 +11,14 @@ namespace base {
|
|||
class ListValue;
|
||||
}
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
|
||||
// Provide helperers to emit event in JavaScript.
|
||||
|
@ -18,12 +26,16 @@ class EventEmitter : public Wrappable {
|
|||
protected:
|
||||
EventEmitter();
|
||||
|
||||
// this.emit(name);
|
||||
// this.emit(name, new Event());
|
||||
bool Emit(const base::StringPiece& name);
|
||||
|
||||
// this.emit(name, args...);
|
||||
// this.emit(name, new Event(), args...);
|
||||
bool Emit(const base::StringPiece& name, const base::ListValue& args);
|
||||
|
||||
// this.emit(name, new Event(sender, message), args...);
|
||||
bool Emit(const base::StringPiece& name, const base::ListValue& args,
|
||||
content::WebContents* sender, IPC::Message* message);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(EventEmitter);
|
||||
};
|
||||
|
|
|
@ -1,10 +1,32 @@
|
|||
EventEmitter = require('events').EventEmitter
|
||||
IDWeakMap = require 'id-weak-map'
|
||||
app = require 'app'
|
||||
ipc = require 'ipc'
|
||||
|
||||
BrowserWindow = process.atomBinding('window').BrowserWindow
|
||||
BrowserWindow::__proto__ = EventEmitter.prototype
|
||||
|
||||
wrapWebContents = (webContents) ->
|
||||
return null unless webContents.isAlive()
|
||||
# webContents is an EventEmitter.
|
||||
webContents.__proto__ = EventEmitter.prototype
|
||||
|
||||
# Wrap around the send method.
|
||||
webContents.send = (args...) ->
|
||||
@_send 'ATOM_INTERNAL_MESSAGE', [args...]
|
||||
|
||||
# Dispatch the ipc messages.
|
||||
webContents.on 'ipc-message', (event, channel, args...) =>
|
||||
Object.defineProperty event, 'sender', value: webContents
|
||||
ipc.emit channel, event, args...
|
||||
webContents.on 'ipc-message-sync', (event, channel, args...) =>
|
||||
set = (value) -> event.sendReply JSON.stringify(value)
|
||||
Object.defineProperty event, 'returnValue', {set}
|
||||
Object.defineProperty event, 'sender', value: webContents
|
||||
ipc.emit channel, event, args...
|
||||
|
||||
webContents
|
||||
|
||||
# Store all created windows in the weak map.
|
||||
BrowserWindow.windows = new IDWeakMap
|
||||
|
||||
|
@ -45,15 +67,10 @@ BrowserWindow::toggleDevTools = ->
|
|||
if @isDevToolsOpened() then @closeDevTools() else @openDevTools()
|
||||
|
||||
BrowserWindow::getWebContents = ->
|
||||
webContents = @_getWebContents()
|
||||
webContents.__proto__ = EventEmitter.prototype
|
||||
webContents
|
||||
wrapWebContents @_getWebContents()
|
||||
|
||||
BrowserWindow::getDevToolsWebContents = ->
|
||||
webContents = @_getDevToolsWebContents()
|
||||
webContents.__proto__ = EventEmitter.prototype
|
||||
webContents = null unless webContents.isAlive()
|
||||
webContents
|
||||
wrapWebContents @_getDevToolsWebContents()
|
||||
|
||||
BrowserWindow::restart = ->
|
||||
@loadUrl(@getUrl())
|
||||
|
|
|
@ -1,32 +1,3 @@
|
|||
EventEmitter = require('events').EventEmitter
|
||||
send = process.atomBinding('ipc').send
|
||||
|
||||
sendWrap = (channel, processId, routingId, args...) ->
|
||||
BrowserWindow = require 'browser-window'
|
||||
if processId?.constructor is BrowserWindow
|
||||
window = processId
|
||||
args = [routingId, args...]
|
||||
processId = window.getProcessId()
|
||||
routingId = window.getRoutingId()
|
||||
|
||||
send channel, processId, routingId, [args...]
|
||||
|
||||
class Ipc extends EventEmitter
|
||||
constructor: ->
|
||||
process.on 'ATOM_INTERNAL_MESSAGE', (args...) =>
|
||||
@emit(args...)
|
||||
process.on 'ATOM_INTERNAL_MESSAGE_SYNC', (channel, event, args...) =>
|
||||
set = (value) -> event.sendReply JSON.stringify(value)
|
||||
|
||||
Object.defineProperty event, 'returnValue', {set}
|
||||
Object.defineProperty event, 'result', {set}
|
||||
|
||||
@emit(channel, event, args...)
|
||||
|
||||
send: (processId, routingId, args...) ->
|
||||
@sendChannel(processId, routingId, 'message', args...)
|
||||
|
||||
sendChannel: (args...) ->
|
||||
sendWrap('ATOM_INTERNAL_MESSAGE', args...)
|
||||
|
||||
module.exports = new Ipc
|
||||
module.exports = new EventEmitter
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue