Pass synchronous messages by JSON string.
authorCheng Zhao <zcbenz@gmail.com>
Fri, 20 Sep 2013 14:32:59 +0000 (22:32 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Fri, 20 Sep 2013 14:32:59 +0000 (22:32 +0800)
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
browser/api/atom_api_event.h
browser/api/atom_browser_bindings.cc
browser/api/atom_browser_bindings.h
browser/api/lib/ipc.coffee
browser/native_window.cc
browser/native_window.h
common/api/api_messages.h
renderer/api/atom_api_renderer_ipc.cc
renderer/api/lib/ipc.coffee

index 9854401..ad666de 100644 (file)
@@ -39,6 +39,13 @@ v8::Handle<v8::Object> Event::CreateV8Object() {
   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) {
   Event* event = new Event;
   event->Wrap(args.This());
index c0ab000..d858531 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef ATOM_BROWSER_ATOM_API_EVENT_H_
 #define ATOM_BROWSER_ATOM_API_EVENT_H_
 
+#include <string>
+
 #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<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.
   v8::Persistent<v8::Object>& handle() { return handle_; }
 
index fb102ff..544f49f 100644 (file)
@@ -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<v8::Context> context = v8::Context::GetCurrent();
@@ -101,11 +102,7 @@ void AtomBrowserBindings::OnRendererMessageSync(
   }
 
   node::MakeCallback(node::process, "emit", arguments.size(), &arguments[0]);
-
-  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()));
+  *result = api::Event::GetReturnValue(event);
 }
 
 }  // namespace atom
index 32a6fae..d936c66 100644 (file)
@@ -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<v8::Object> browser_main_parts() {
index 2aa4d06..8e81e0d 100644 (file)
@@ -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...)
index 154a1a6..6c4f3df 100644 (file)
@@ -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
index 3316b07..03a2883 100644 (file)
@@ -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_;
index ee031e6..c93abeb 100644 (file)
@@ -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 */,
index 022ad28..1f7a6f5 100644 (file)
@@ -97,12 +97,12 @@ v8::Handle<v8::Value> 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<base::ListValue*>(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<v8::Value> 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
index 88b8c1c..c54545d 100644 (file)
@@ -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