Bug 1298810: Pass Port object to listeners on native messaging ports. r?rpl draft
authorKris Maglione <maglione.k@gmail.com>
Mon, 29 Aug 2016 13:12:16 -0700
changeset 406881 1ce443724874a1921580942b7719b000abad1318
parent 406880 915bfb19fb561f7dd2e71b79798c30d4a0ff2d6e
child 529776 2de57e814db1654d76af9addcbb3edb488cf093d
push id27858
push usermaglione.k@gmail.com
push dateMon, 29 Aug 2016 20:12:47 +0000
reviewersrpl
bugs1298810
milestone51.0a1
Bug 1298810: Pass Port object to listeners on native messaging ports. r?rpl MozReview-Commit-ID: 1saUOB1jyE1
toolkit/components/extensions/NativeMessaging.jsm
toolkit/components/extensions/test/xpcshell/test_ext_native_messaging.js
--- a/toolkit/components/extensions/NativeMessaging.jsm
+++ b/toolkit/components/extensions/NativeMessaging.jsm
@@ -372,52 +372,55 @@ this.NativeApp = class extends EventEmit
   }
 
   // Called from Context when the extension is shut down.
   close() {
     this._cleanup();
   }
 
   portAPI() {
-    let api = {
+    let port = {
       name: this.name,
 
       disconnect: () => {
         if (this._isDisconnected) {
           throw new this.context.cloneScope.Error("Attempt to disconnect an already disconnected port");
         }
         this._cleanup();
       },
 
       postMessage: msg => {
         this.send(msg);
       },
 
       onDisconnect: new ExtensionUtils.SingletonEventManager(this.context, "native.onDisconnect", fire => {
         let listener = what => {
-          this.context.runSafe(fire);
+          this.context.runSafeWithoutClone(fire, port);
         };
         this.on("disconnect", listener);
         return () => {
           this.off("disconnect", listener);
         };
       }).api(),
 
       onMessage: new ExtensionUtils.SingletonEventManager(this.context, "native.onMessage", fire => {
         let listener = (what, msg) => {
-          this.context.runSafe(fire, msg);
+          msg = Cu.cloneInto(msg, this.context.cloneScope);
+          this.context.runSafeWithoutClone(fire, msg, port);
         };
         this.on("message", listener);
         return () => {
           this.off("message", listener);
         };
       }).api(),
     };
 
-    return Cu.cloneInto(api, this.context.cloneScope, {cloneFunctions: true});
+    port = Cu.cloneInto(port, this.context.cloneScope, {cloneFunctions: true});
+
+    return port;
   }
 
   sendMessage(msg) {
     let responsePromise = new Promise((resolve, reject) => {
       this.on("message", (what, msg) => { resolve(msg); });
       this.on("disconnect", (what, err) => { reject(err); });
     });
 
--- a/toolkit/components/extensions/test/xpcshell/test_ext_native_messaging.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_native_messaging.js
@@ -211,19 +211,24 @@ add_task(function* test_sendNativeMessag
 
   yield extension.unload();
 });
 
 // Test calling Port.disconnect()
 add_task(function* test_disconnect() {
   function background() {
     let port = browser.runtime.connectNative("echo");
-    port.onMessage.addListener(msg => {
+    port.onMessage.addListener((msg, msgPort) => {
+      browser.test.assertEq(port, msgPort, "onMessage handler should receive the port as the second argument");
       browser.test.sendMessage("message", msg);
     });
+    port.onDisconnect.addListener(msgPort => {
+      browser.test.assertEq(port, msgPort, "onDisconnect handler should receive the port as the second argument");
+      browser.test.sendMessage("disconnected");
+    });
     browser.test.onMessage.addListener((what, payload) => {
       if (what == "send") {
         if (payload._json) {
           let json = payload._json;
           payload.toJSON = () => json;
           delete payload._json;
         }
         port.postMessage(payload);
@@ -259,16 +264,18 @@ add_task(function* test_disconnect() {
 
   let procCount = yield getSubprocessCount();
   equal(procCount, 1, "subprocess is running");
 
   extension.sendMessage("disconnect");
   response = yield extension.awaitMessage("disconnect-result");
   equal(response.success, true, "disconnect succeeded");
 
+  yield extension.awaitMessage("disconnected");
+
   do_print("waiting for subprocess to exit");
   yield waitForSubprocessExit();
   procCount = yield getSubprocessCount();
   equal(procCount, 0, "subprocess is no longer running");
 
   extension.sendMessage("disconnect");
   response = yield extension.awaitMessage("disconnect-result");
   equal(response.success, false, "second call to disconnect failed");