From ef5a4b5fe07bca5ef38ad121bb75ccc403817267 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 20 Sep 2013 22:32:59 +0800 Subject: [PATCH] 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. --- browser/api/atom_api_event.cc | 7 +++++++ browser/api/atom_api_event.h | 5 +++++ browser/api/atom_browser_bindings.cc | 9 +++------ browser/api/atom_browser_bindings.h | 3 +-- browser/api/lib/ipc.coffee | 11 +++++++++-- browser/native_window.cc | 11 ++++++++--- browser/native_window.h | 6 +++++- common/api/api_messages.h | 2 +- renderer/api/atom_api_renderer_ipc.cc | 6 +++--- renderer/api/lib/ipc.coffee | 4 ++-- 10 files changed, 44 insertions(+), 20 deletions(-) diff --git a/browser/api/atom_api_event.cc b/browser/api/atom_api_event.cc index 9854401..ad666de 100644 --- a/browser/api/atom_api_event.cc +++ b/browser/api/atom_api_event.cc @@ -39,6 +39,13 @@ v8::Handle Event::CreateV8Object() { return scope.Close(v8_event); } +// static +std::string Event::GetReturnValue(v8::Handle event) { + v8::HandleScope scope; + v8::Local json = event->Get(v8::String::New("returnValue")); + return *v8::String::Utf8Value(json); +} + v8::Handle Event::New(const v8::Arguments &args) { Event* event = new Event; event->Wrap(args.This()); diff --git a/browser/api/atom_api_event.h b/browser/api/atom_api_event.h index c0ab000..d858531 100644 --- a/browser/api/atom_api_event.h +++ b/browser/api/atom_api_event.h @@ -5,6 +5,8 @@ #ifndef ATOM_BROWSER_ATOM_API_EVENT_H_ #define ATOM_BROWSER_ATOM_API_EVENT_H_ +#include + #include "base/basictypes.h" #include "vendor/node/src/node_object_wrap.h" @@ -19,6 +21,9 @@ class Event : public node::ObjectWrap { // Create a V8 Event object. static v8::Handle CreateV8Object(); + // Get JSON string of the event.returnValue from a Event object. + static std::string GetReturnValue(v8::Handle event); + // Accessor to return handle_, this follows Google C++ Style. v8::Persistent& handle() { return handle_; } diff --git a/browser/api/atom_browser_bindings.cc b/browser/api/atom_browser_bindings.cc index fb102ff..544f49f 100644 --- a/browser/api/atom_browser_bindings.cc +++ b/browser/api/atom_browser_bindings.cc @@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/values.h" +#include "browser/api/atom_api_event.h" #include "common/v8_value_converter_impl.h" #include "content/public/browser/browser_thread.h" #include "vendor/node/src/node.h" @@ -74,7 +75,7 @@ void AtomBrowserBindings::OnRendererMessageSync( int routing_id, const std::string& channel, const base::ListValue& args, - base::DictionaryValue* result) { + std::string* result) { v8::HandleScope scope; v8::Handle context = v8::Context::GetCurrent(); @@ -101,11 +102,7 @@ void AtomBrowserBindings::OnRendererMessageSync( } node::MakeCallback(node::process, "emit", arguments.size(), &arguments[0]); - - scoped_ptr base_event(converter->FromV8Value(event, context)); - DCHECK(base_event && base_event->IsType(base::Value::TYPE_DICTIONARY)); - - result->Swap(static_cast(base_event.get())); + *result = api::Event::GetReturnValue(event); } } // namespace atom diff --git a/browser/api/atom_browser_bindings.h b/browser/api/atom_browser_bindings.h index 32a6fae..d936c66 100644 --- a/browser/api/atom_browser_bindings.h +++ b/browser/api/atom_browser_bindings.h @@ -10,7 +10,6 @@ #include "common/api/atom_bindings.h" namespace base { -class DictionaryValue; class ListValue; } @@ -35,7 +34,7 @@ class AtomBrowserBindings : public AtomBindings { int routing_id, const std::string& channel, const base::ListValue& args, - base::DictionaryValue* result); + std::string* result); // The require('atom').browserMainParts object. v8::Handle browser_main_parts() { diff --git a/browser/api/lib/ipc.coffee b/browser/api/lib/ipc.coffee index 2aa4d06..8e81e0d 100644 --- a/browser/api/lib/ipc.coffee +++ b/browser/api/lib/ipc.coffee @@ -14,8 +14,15 @@ class Ipc extends EventEmitter constructor: -> process.on 'ATOM_INTERNAL_MESSAGE', (args...) => @emit(args...) - process.on 'ATOM_INTERNAL_MESSAGE_SYNC', (args...) => - @emit(args...) + process.on 'ATOM_INTERNAL_MESSAGE_SYNC', (channel, event, 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...) -> @sendChannel(processId, routingId, 'message', args...) diff --git a/browser/native_window.cc b/browser/native_window.cc index 154a1a6..6c4f3df 100644 --- a/browser/native_window.cc +++ b/browser/native_window.cc @@ -300,7 +300,8 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(NativeWindow, message) 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, UpdateDraggableRegions) IPC_MESSAGE_UNHANDLED(handled = false) @@ -351,13 +352,17 @@ void NativeWindow::OnRendererMessage(const std::string& channel, void NativeWindow::OnRendererMessageSync(const std::string& channel, const base::ListValue& args, - base::DictionaryValue* result) { + IPC::Message* reply_msg) { + std::string json; AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync( GetWebContents()->GetRenderProcessHost()->GetID(), GetWebContents()->GetRoutingID(), channel, args, - result); + &json); + + AtomViewHostMsg_Message_Sync::WriteReplyParams(reply_msg, json); + Send(reply_msg); } } // namespace atom diff --git a/browser/native_window.h b/browser/native_window.h index 3316b07..03a2883 100644 --- a/browser/native_window.h +++ b/browser/native_window.h @@ -35,6 +35,10 @@ class Rect; class Size; } +namespace IPC { +class Message; +} + namespace atom { class AtomJavaScriptDialogManager; @@ -178,7 +182,7 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, void OnRendererMessageSync(const std::string& channel, const base::ListValue& args, - base::DictionaryValue* result); + IPC::Message* reply_msg); // Notification manager. content::NotificationRegistrar registrar_; diff --git a/common/api/api_messages.h b/common/api/api_messages.h index ee031e6..c93abeb 100644 --- a/common/api/api_messages.h +++ b/common/api/api_messages.h @@ -28,7 +28,7 @@ IPC_MESSAGE_ROUTED2(AtomViewHostMsg_Message, IPC_SYNC_MESSAGE_ROUTED2_1(AtomViewHostMsg_Message_Sync, std::string /* channel */, ListValue /* arguments */, - DictionaryValue /* result */) + std::string /* result (in JSON) */) IPC_MESSAGE_ROUTED2(AtomViewMsg_Message, std::string /* channel */, diff --git a/renderer/api/atom_api_renderer_ipc.cc b/renderer/api/atom_api_renderer_ipc.cc index 022ad28..1f7a6f5 100644 --- a/renderer/api/atom_api_renderer_ipc.cc +++ b/renderer/api/atom_api_renderer_ipc.cc @@ -97,12 +97,12 @@ v8::Handle RendererIPC::SendSync(const v8::Arguments &args) { RenderView* render_view = GetCurrentRenderView(); - base::DictionaryValue result; + std::string json; IPC::SyncMessage* message = new AtomViewHostMsg_Message_Sync( render_view->GetRoutingID(), channel, *static_cast(arguments.get()), - &result); + &json); // Enable the UI thread in browser to receive messages. message->EnableMessagePumping(); bool success = render_view->Send(message); @@ -110,7 +110,7 @@ v8::Handle RendererIPC::SendSync(const v8::Arguments &args) { if (!success) 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 diff --git a/renderer/api/lib/ipc.coffee b/renderer/api/lib/ipc.coffee index 88b8c1c..c54545d 100644 --- a/renderer/api/lib/ipc.coffee +++ b/renderer/api/lib/ipc.coffee @@ -17,10 +17,10 @@ class Ipc extends EventEmitter sendSync: (args...) -> msg = ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', 'sync-message', args...) - msg.returnValue ? msg.result + JSON.parse(msg) sendChannelSync: (args...) -> msg = ipc.sendSync('ATOM_INTERNAL_MESSAGE_SYNC', args...) - msg.returnValue ? msg.result + JSON.parse(msg) module.exports = new Ipc -- 2.7.4