Pass synchronous messages by JSON string.

We are going to use IPC_MESSAGE_HANDLER_DELAY_REPLY to handle
synchronous messages but DictionaryValue is not copyable, so we pass the
JSON string instead.
This commit is contained in:
Cheng Zhao 2013-09-20 22:32:59 +08:00
parent 07b5039c64
commit ef5a4b5fe0
10 changed files with 44 additions and 20 deletions

View file

@ -39,6 +39,13 @@ v8::Handle<v8::Object> Event::CreateV8Object() {
return scope.Close(v8_event); return scope.Close(v8_event);
} }
// static
std::string Event::GetReturnValue(v8::Handle<v8::Object> event) {
v8::HandleScope scope;
v8::Local<v8::Value> json = event->Get(v8::String::New("returnValue"));
return *v8::String::Utf8Value(json);
}
v8::Handle<v8::Value> Event::New(const v8::Arguments &args) { v8::Handle<v8::Value> Event::New(const v8::Arguments &args) {
Event* event = new Event; Event* event = new Event;
event->Wrap(args.This()); event->Wrap(args.This());

View file

@ -5,6 +5,8 @@
#ifndef ATOM_BROWSER_ATOM_API_EVENT_H_ #ifndef ATOM_BROWSER_ATOM_API_EVENT_H_
#define ATOM_BROWSER_ATOM_API_EVENT_H_ #define ATOM_BROWSER_ATOM_API_EVENT_H_
#include <string>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "vendor/node/src/node_object_wrap.h" #include "vendor/node/src/node_object_wrap.h"
@ -19,6 +21,9 @@ class Event : public node::ObjectWrap {
// Create a V8 Event object. // Create a V8 Event object.
static v8::Handle<v8::Object> CreateV8Object(); static v8::Handle<v8::Object> CreateV8Object();
// Get JSON string of the event.returnValue from a Event object.
static std::string GetReturnValue(v8::Handle<v8::Object> event);
// Accessor to return handle_, this follows Google C++ Style. // Accessor to return handle_, this follows Google C++ Style.
v8::Persistent<v8::Object>& handle() { return handle_; } v8::Persistent<v8::Object>& handle() { return handle_; }

View file

@ -8,6 +8,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/values.h" #include "base/values.h"
#include "browser/api/atom_api_event.h"
#include "common/v8_value_converter_impl.h" #include "common/v8_value_converter_impl.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "vendor/node/src/node.h" #include "vendor/node/src/node.h"
@ -74,7 +75,7 @@ void AtomBrowserBindings::OnRendererMessageSync(
int routing_id, int routing_id,
const std::string& channel, const std::string& channel,
const base::ListValue& args, const base::ListValue& args,
base::DictionaryValue* result) { std::string* result) {
v8::HandleScope scope; v8::HandleScope scope;
v8::Handle<v8::Context> context = v8::Context::GetCurrent(); v8::Handle<v8::Context> context = v8::Context::GetCurrent();
@ -101,11 +102,7 @@ void AtomBrowserBindings::OnRendererMessageSync(
} }
node::MakeCallback(node::process, "emit", arguments.size(), &arguments[0]); node::MakeCallback(node::process, "emit", arguments.size(), &arguments[0]);
*result = api::Event::GetReturnValue(event);
scoped_ptr<base::Value> base_event(converter->FromV8Value(event, context));
DCHECK(base_event && base_event->IsType(base::Value::TYPE_DICTIONARY));
result->Swap(static_cast<base::DictionaryValue*>(base_event.get()));
} }
} // namespace atom } // namespace atom

View file

@ -10,7 +10,6 @@
#include "common/api/atom_bindings.h" #include "common/api/atom_bindings.h"
namespace base { namespace base {
class DictionaryValue;
class ListValue; class ListValue;
} }
@ -35,7 +34,7 @@ class AtomBrowserBindings : public AtomBindings {
int routing_id, int routing_id,
const std::string& channel, const std::string& channel,
const base::ListValue& args, const base::ListValue& args,
base::DictionaryValue* result); std::string* result);
// The require('atom').browserMainParts object. // The require('atom').browserMainParts object.
v8::Handle<v8::Object> browser_main_parts() { v8::Handle<v8::Object> browser_main_parts() {

View file

@ -14,8 +14,15 @@ class Ipc extends EventEmitter
constructor: -> constructor: ->
process.on 'ATOM_INTERNAL_MESSAGE', (args...) => process.on 'ATOM_INTERNAL_MESSAGE', (args...) =>
@emit(args...) @emit(args...)
process.on 'ATOM_INTERNAL_MESSAGE_SYNC', (args...) => process.on 'ATOM_INTERNAL_MESSAGE_SYNC', (channel, event, args...) =>
@emit(args...) returnValue = 'null'
get = -> returnValue
set = (value) -> returnValue = JSON.stringify(value)
Object.defineProperty event, 'returnValue', {get, set}
Object.defineProperty event, 'result', {get, set}
@emit(channel, event, args...)
send: (processId, routingId, args...) -> send: (processId, routingId, args...) ->
@sendChannel(processId, routingId, 'message', args...) @sendChannel(processId, routingId, 'message', args...)

View file

@ -300,7 +300,8 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
bool handled = true; bool handled = true;
IPC_BEGIN_MESSAGE_MAP(NativeWindow, message) IPC_BEGIN_MESSAGE_MAP(NativeWindow, message)
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage) IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message_Sync, OnRendererMessageSync) IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync,
OnRendererMessageSync)
IPC_MESSAGE_HANDLER(AtomViewHostMsg_UpdateDraggableRegions, IPC_MESSAGE_HANDLER(AtomViewHostMsg_UpdateDraggableRegions,
UpdateDraggableRegions) UpdateDraggableRegions)
IPC_MESSAGE_UNHANDLED(handled = false) IPC_MESSAGE_UNHANDLED(handled = false)
@ -351,13 +352,17 @@ void NativeWindow::OnRendererMessage(const std::string& channel,
void NativeWindow::OnRendererMessageSync(const std::string& channel, void NativeWindow::OnRendererMessageSync(const std::string& channel,
const base::ListValue& args, const base::ListValue& args,
base::DictionaryValue* result) { IPC::Message* reply_msg) {
std::string json;
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync( AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync(
GetWebContents()->GetRenderProcessHost()->GetID(), GetWebContents()->GetRenderProcessHost()->GetID(),
GetWebContents()->GetRoutingID(), GetWebContents()->GetRoutingID(),
channel, channel,
args, args,
result); &json);
AtomViewHostMsg_Message_Sync::WriteReplyParams(reply_msg, json);
Send(reply_msg);
} }
} // namespace atom } // namespace atom

View file

@ -35,6 +35,10 @@ class Rect;
class Size; class Size;
} }
namespace IPC {
class Message;
}
namespace atom { namespace atom {
class AtomJavaScriptDialogManager; class AtomJavaScriptDialogManager;
@ -178,7 +182,7 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
void OnRendererMessageSync(const std::string& channel, void OnRendererMessageSync(const std::string& channel,
const base::ListValue& args, const base::ListValue& args,
base::DictionaryValue* result); IPC::Message* reply_msg);
// Notification manager. // Notification manager.
content::NotificationRegistrar registrar_; content::NotificationRegistrar registrar_;

View file

@ -28,7 +28,7 @@ IPC_MESSAGE_ROUTED2(AtomViewHostMsg_Message,
IPC_SYNC_MESSAGE_ROUTED2_1(AtomViewHostMsg_Message_Sync, IPC_SYNC_MESSAGE_ROUTED2_1(AtomViewHostMsg_Message_Sync,
std::string /* channel */, std::string /* channel */,
ListValue /* arguments */, ListValue /* arguments */,
DictionaryValue /* result */) std::string /* result (in JSON) */)
IPC_MESSAGE_ROUTED2(AtomViewMsg_Message, IPC_MESSAGE_ROUTED2(AtomViewMsg_Message,
std::string /* channel */, std::string /* channel */,

View file

@ -97,12 +97,12 @@ v8::Handle<v8::Value> RendererIPC::SendSync(const v8::Arguments &args) {
RenderView* render_view = GetCurrentRenderView(); RenderView* render_view = GetCurrentRenderView();
base::DictionaryValue result; std::string json;
IPC::SyncMessage* message = new AtomViewHostMsg_Message_Sync( IPC::SyncMessage* message = new AtomViewHostMsg_Message_Sync(
render_view->GetRoutingID(), render_view->GetRoutingID(),
channel, channel,
*static_cast<base::ListValue*>(arguments.get()), *static_cast<base::ListValue*>(arguments.get()),
&result); &json);
// Enable the UI thread in browser to receive messages. // Enable the UI thread in browser to receive messages.
message->EnableMessagePumping(); message->EnableMessagePumping();
bool success = render_view->Send(message); bool success = render_view->Send(message);
@ -110,7 +110,7 @@ v8::Handle<v8::Value> RendererIPC::SendSync(const v8::Arguments &args) {
if (!success) if (!success)
return node::ThrowError("Unable to send AtomViewHostMsg_Message_Sync"); return node::ThrowError("Unable to send AtomViewHostMsg_Message_Sync");
return scope.Close(converter->ToV8Value(&result, context)); return scope.Close(v8::String::New(json.data(), json.size()));
} }
// static // static

View file

@ -17,10 +17,10 @@ class Ipc extends EventEmitter
sendSync: (args...) -> sendSync: (args...) ->
msg = ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', 'sync-message', args...) msg = ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', 'sync-message', args...)
msg.returnValue ? msg.result JSON.parse(msg)
sendChannelSync: (args...) -> sendChannelSync: (args...) ->
msg = ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', args...) msg = ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', args...)
msg.returnValue ? msg.result JSON.parse(msg)
module.exports = new Ipc module.exports = new Ipc