Bug 1316396: Part 3 - Clean up the native messaging Port logic. r?aswan draft
authorKris Maglione <maglione.k@gmail.com>
Wed, 09 Nov 2016 12:28:09 -0800
changeset 436930 11cbe7a12e5922b730dfde2bd5954e886c539c29
parent 436929 0f0f0a8a5740d49537ec2fea3dea24761955f512
child 436931 4d33c02dde10a7e5c5193244e0846f92997f6343
push id35242
push usermaglione.k@gmail.com
push dateThu, 10 Nov 2016 02:11:26 +0000
reviewersaswan
bugs1316396
milestone52.0a1
Bug 1316396: Part 3 - Clean up the native messaging Port logic. r?aswan MozReview-Commit-ID: E7ns3ZQl6FN
toolkit/components/extensions/ExtensionChild.jsm
toolkit/components/extensions/ext-c-runtime.js
--- a/toolkit/components/extensions/ExtensionChild.jsm
+++ b/toolkit/components/extensions/ExtensionChild.jsm
@@ -21,16 +21,18 @@ const Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent",
                                   "resource://gre/modules/ExtensionParent.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MessageChannel",
                                   "resource://gre/modules/MessageChannel.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NativeApp",
+                                  "resource://gre/modules/NativeMessaging.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PromiseUtils",
                                   "resource://gre/modules/PromiseUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
                                   "resource://gre/modules/Schemas.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "ParentAPIManager",
                             () => ExtensionParent.ParentAPIManager);
 
@@ -99,16 +101,20 @@ class Port {
       receiveMessage: ({data}) => this.disconnectByOtherEnd(data),
     }, this.handlerBase);
 
     MessageChannel.addListener(this.receiverMMs, "Extension:Port:Disconnect", this.disconnectHandler);
 
     this.context.callOnClose(this);
   }
 
+  static getNextID() {
+    return `${gNextPortId++}-${Services.appinfo.uniqueProcessID}`;
+  }
+
   api() {
     let portObj = Cu.createObjectIn(this.context.cloneScope);
 
     let portError = null;
     let publicAPI = {
       name: this.name,
 
       disconnect: () => {
@@ -256,16 +262,24 @@ class Port {
     this._sendMessage("Extension:Port:Disconnect", error);
   }
 
   close() {
     this.disconnect();
   }
 }
 
+class NativePort extends Port {
+  postMessage(data) {
+    data = NativeApp.encodeMessage(this.context, data);
+
+    return super.postMessage(data);
+  }
+}
+
 /**
  * Each extension context gets its own Messenger object. It handles the
  * basics of sendMessage, onMessage, connect and onConnect.
  *
  * @param {BaseContext} context The context to which this Messenger is tied.
  * @param {Array<nsIMessageListenerManager>} messageManagers
  *     The message managers used to receive messages (e.g. onMessage/onConnect
  *     requests).
@@ -311,16 +325,21 @@ class Messenger {
         } else if (error.result != MessageChannel.RESULT_NO_RESPONSE) {
           return Promise.reject({message: error.message});
         }
       });
 
     return this.context.wrapPromise(promise, responseCallback);
   }
 
+  sendNativeMessage(messageManager, msg, recipient, responseCallback) {
+    msg = NativeApp.encodeMessage(this.context, msg);
+    return this.sendMessage(messageManager, msg, recipient, responseCallback);
+  }
+
   onMessage(name) {
     return new SingletonEventManager(this.context, name, callback => {
       let listener = {
         messageFilterPermissive: this.optionalFilter,
         messageFilterStrict: this.filter,
 
         filterMessage: (sender, recipient) => {
           // Ignore the message if it was sent by this Messenger.
@@ -359,35 +378,48 @@ class Messenger {
 
       MessageChannel.addListener(this.messageManagers, "Extension:Message", listener);
       return () => {
         MessageChannel.removeListener(this.messageManagers, "Extension:Message", listener);
       };
     }).api();
   }
 
-  connectGetRawPort(messageManager, name, recipient) {
-    let portId = `${gNextPortId++}-${Services.appinfo.uniqueProcessID}`;
-    let port = new Port(this.context, messageManager, this.messageManagers, name, portId, null, recipient);
-    let msg = {name, portId};
-    this._sendMessage(messageManager, "Extension:Connect", msg, recipient)
-      .catch(e => {
-        if (e.result === MessageChannel.RESULT_NO_HANDLER) {
-          e = {message: "Could not establish connection. Receiving end does not exist."};
-        } else if (e.result === MessageChannel.RESULT_DISCONNECTED) {
-          e = null;
-        }
-        port.disconnectByOtherEnd(e);
-      });
-    return port;
+  _connect(messageManager, port, recipient) {
+    let msg = {
+      name: port.name,
+      portId: port.id,
+    };
+
+    this._sendMessage(messageManager, "Extension:Connect", msg, recipient).catch(error => {
+      if (error.result === MessageChannel.RESULT_NO_HANDLER) {
+        error = {message: "Could not establish connection. Receiving end does not exist."};
+      } else if (error.result === MessageChannel.RESULT_DISCONNECTED) {
+        error = null;
+      }
+      port.disconnectByOtherEnd(error);
+    });
+
+    return port.api();
   }
 
   connect(messageManager, name, recipient) {
-    let port = this.connectGetRawPort(messageManager, name, recipient);
-    return port.api();
+    let portId = Port.getNextID();
+
+    let port = new Port(this.context, messageManager, this.messageManagers, name, portId, null, recipient);
+
+    return this._connect(messageManager, port, recipient);
+  }
+
+  connectNative(messageManager, name, recipient) {
+    let portId = Port.getNextID();
+
+    let port = new NativePort(this.context, messageManager, this.messageManagers, name, portId, null, recipient);
+
+    return this._connect(messageManager, port, recipient);
   }
 
   onConnect(name) {
     return new SingletonEventManager(this.context, name, callback => {
       let listener = {
         messageFilterPermissive: this.optionalFilter,
         messageFilterStrict: this.filter,
 
--- a/toolkit/components/extensions/ext-c-runtime.js
+++ b/toolkit/components/extensions/ext-c-runtime.js
@@ -1,11 +1,9 @@
 "use strict";
-XPCOMUtils.defineLazyModuleGetter(this, "NativeApp",
-                                  "resource://gre/modules/NativeMessaging.jsm");
 
 function runtimeApiFactory(context) {
   let {extension} = context;
 
   return {
     runtime: {
       onConnect: context.messenger.onConnect("runtime.onConnect"),
 
@@ -57,32 +55,26 @@ function runtimeApiFactory(context) {
         return context.messenger.sendMessage(context.messageManager, message, recipient, responseCallback);
       },
 
       connectNative(application) {
         let recipient = {
           childId: context.childManager.id,
           toNativeApp: application,
         };
-        let rawPort = context.messenger.connectGetRawPort(context.messageManager, "", recipient);
-        let port = rawPort.api();
-        port.postMessage = message => {
-          message = NativeApp.encodeMessage(context, message);
-          rawPort.postMessage(message);
-        };
-        return port;
+
+        return context.messenger.connectNative(context.messageManager, "", recipient);
       },
 
       sendNativeMessage(application, message) {
         let recipient = {
           childId: context.childManager.id,
           toNativeApp: application,
         };
-        message = NativeApp.encodeMessage(context, message);
-        return context.messenger.sendMessage(context.messageManager, message, recipient);
+        return context.messenger.sendNativeMessage(context.messageManager, message, recipient);
       },
 
       get lastError() {
         return context.lastError;
       },
 
       getManifest() {
         return Cu.cloneInto(extension.manifest, context.cloneScope);