Send reply for sync messages when event.returnValue is set.
authorCheng Zhao <zcbenz@gmail.com>
Sun, 22 Sep 2013 01:52:58 +0000 (09:52 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Sun, 22 Sep 2013 01:52:58 +0000 (09:52 +0800)
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

index accfb29..d9b523b 100644 (file)
@@ -4,7 +4,9 @@
 
 #include "browser/api/atom_api_event.h"
 
+#include "common/api/api_messages.h"
 #include "common/string16_conversions.h"
+#include "ipc/ipc_sender.h"
 
 using node::node_isolate;
 
@@ -15,7 +17,9 @@ namespace api {
 v8::Persistent<v8::FunctionTemplate> Event::constructor_template_;
 
 Event::Event()
-    : prevent_default_(false) {
+    : sender_(NULL),
+      message_(NULL),
+      prevent_default_(false) {
 }
 
 Event::~Event() {
@@ -33,6 +37,7 @@ v8::Handle<v8::Object> Event::CreateV8Object() {
     constructor_template_->SetClassName(v8::String::NewSymbol("Event"));
 
     NODE_SET_PROTOTYPE_METHOD(t, "preventDefault", PreventDefault);
+    NODE_SET_PROTOTYPE_METHOD(t, "sendReply", SendReply);
   }
 
   v8::Handle<v8::Object> v8_event =
@@ -48,14 +53,24 @@ string16 Event::GetReturnValue(v8::Handle<v8::Object> event) {
   return V8ValueToUTF16(json);
 }
 
-v8::Handle<v8::Value> Event::New(const v8::Arguments &args) {
+
+void Event::SetSenderAndMessage(IPC::Sender* sender, IPC::Message* message) {
+  DCHECK(!sender_);
+  DCHECK(!message_);
+  sender_ = sender;
+  message_ = message;
+}
+
+// static
+v8::Handle<v8::Value> Event::New(const v8::Arguments& args) {
   Event* event = new Event;
   event->Wrap(args.This());
 
   return args.This();
 }
 
-v8::Handle<v8::Value> Event::PreventDefault(const v8::Arguments &args) {
+// static
+v8::Handle<v8::Value> Event::PreventDefault(const v8::Arguments& args) {
   Event* event = Unwrap<Event>(args.This());
   if (event == NULL)
     return node::ThrowError("Event is already destroyed");
@@ -65,6 +80,23 @@ v8::Handle<v8::Value> Event::PreventDefault(const v8::Arguments &args) {
   return v8::Undefined();
 }
 
+// static
+v8::Handle<v8::Value> Event::SendReply(const v8::Arguments& args) {
+  Event* event = Unwrap<Event>(args.This());
+  if (event == NULL)
+    return node::ThrowError("Event is already destroyed");
+
+  if (event->sender_ == NULL)
+    return node::ThrowError("Can only send reply to synchronous events");
+
+  string16 json = GetReturnValue(args.This());
+
+  AtomViewHostMsg_Message_Sync::WriteReplyParams(event->message_, json);
+  event->sender_->Send(event->message_);
+
+  return v8::Undefined();
+}
+
 }  // namespace api
 
 }  // namespace atom
index 6517e14..ebbec7b 100644 (file)
@@ -9,6 +9,11 @@
 #include "base/string16.h"
 #include "vendor/node/src/node_object_wrap.h"
 
+namespace IPC {
+class Message;
+class Sender;
+}
+
 namespace atom {
 
 namespace api {
@@ -23,6 +28,9 @@ class Event : public node::ObjectWrap {
   // Get JSON string of the event.returnValue from a Event object.
   static string16 GetReturnValue(v8::Handle<v8::Object> event);
 
+  // Pass the sender and message to be replied.
+  void SetSenderAndMessage(IPC::Sender* sender, IPC::Message* message);
+
   // Accessor to return handle_, this follows Google C++ Style.
   v8::Persistent<v8::Object>& handle() { return handle_; }
 
@@ -33,11 +41,17 @@ class Event : public node::ObjectWrap {
   Event();
 
  private:
-  static v8::Handle<v8::Value> New(const v8::Arguments &args);
-  static v8::Handle<v8::Value> PreventDefault(const v8::Arguments &args);
+  static v8::Handle<v8::Value> New(const v8::Arguments& args);
+
+  static v8::Handle<v8::Value> PreventDefault(const v8::Arguments& args);
+  static v8::Handle<v8::Value> SendReply(const v8::Arguments& args);
 
   static v8::Persistent<v8::FunctionTemplate> constructor_template_;
 
+  // Replyer for the synchronous messages.
+  IPC::Sender* sender_;
+  IPC::Message* message_;
+
   bool prevent_default_;
 
   DISALLOW_COPY_AND_ASSIGN(Event);
index 7c69de9..85ba15c 100644 (file)
@@ -76,14 +76,17 @@ void AtomBrowserBindings::OnRendererMessageSync(
     int routing_id,
     const string16& channel,
     const base::ListValue& args,
-    string16* result) {
+    IPC::Sender* sender,
+    IPC::Message* message) {
   v8::HandleScope scope;
 
   v8::Handle<v8::Context> context = v8::Context::GetCurrent();
 
   scoped_ptr<V8ValueConverter> converter(new V8ValueConverterImpl());
 
-  v8::Handle<v8::Object> event = v8::Object::New();
+  // Create the event object.
+  v8::Handle<v8::Object> event = api::Event::CreateV8Object();
+  api::Event::Unwrap<api::Event>(event)->SetSenderAndMessage(sender, message);
 
   // process.emit(channel, 'sync-message', event, process_id, routing_id);
   std::vector<v8::Handle<v8::Value>> arguments;
@@ -103,7 +106,6 @@ void AtomBrowserBindings::OnRendererMessageSync(
   }
 
   node::MakeCallback(node::process, "emit", arguments.size(), &arguments[0]);
-  *result = api::Event::GetReturnValue(event);
 }
 
 }  // namespace atom
index 92ddd49..27b9195 100644 (file)
@@ -12,6 +12,11 @@ namespace base {
 class ListValue;
 }
 
+namespace IPC {
+class Message;
+class Sender;
+}
+
 namespace atom {
 
 class AtomBrowserBindings : public AtomBindings {
@@ -33,7 +38,8 @@ class AtomBrowserBindings : public AtomBindings {
                              int routing_id,
                              const string16& channel,
                              const base::ListValue& args,
-                             string16* result);
+                             IPC::Sender* sender,
+                             IPC::Message* message);
 
   // The require('atom').browserMainParts object.
   v8::Handle<v8::Object> browser_main_parts() {
index 8e81e0d..27deb70 100644 (file)
@@ -15,9 +15,12 @@ class Ipc extends EventEmitter
     process.on 'ATOM_INTERNAL_MESSAGE', (args...) =>
       @emit(args...)
     process.on 'ATOM_INTERNAL_MESSAGE_SYNC', (channel, event, args...) =>
-      returnValue = 'null'
+      returnValue = null
       get = -> returnValue
-      set = (value) -> returnValue = JSON.stringify(value)
+      set = (value) ->
+        throw new Error('returnValue can be only set once') if returnValue?
+        returnValue = JSON.stringify(value)
+        event.sendReply()
 
       Object.defineProperty event, 'returnValue', {get, set}
       Object.defineProperty event, 'result', {get, set}
index 9a7ba7d..f602819 100644 (file)
@@ -353,16 +353,13 @@ void NativeWindow::OnRendererMessage(const string16& channel,
 void NativeWindow::OnRendererMessageSync(const string16& channel,
                                          const base::ListValue& args,
                                          IPC::Message* reply_msg) {
-  string16 json;
   AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync(
       GetWebContents()->GetRenderProcessHost()->GetID(),
       GetWebContents()->GetRoutingID(),
       channel,
       args,
-      &json);
-
-  AtomViewHostMsg_Message_Sync::WriteReplyParams(reply_msg, json);
-  Send(reply_msg);
+      this,
+      reply_msg);
 }
 
 }  // namespace atom