Bug 1286746 - Invoke port.onDisconnect if there are no onConnect listeners. r=kmag
☠☠ backed out by b62676e921c5 ☠ ☠
authorRob Wu <rob@robwu.nl>
Fri, 15 Jul 2016 17:46:00 -0700
changeset 349068 562910144a3a32a69af4957e52d250df5a83136e
parent 349067 26f41a685662f89b35dd7a10f8fba0ab128a7c2d
child 349069 d7558f1c86e28d9635b1b6e1d1982fc45da8c9cc
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1286746
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1286746 - Invoke port.onDisconnect if there are no onConnect listeners. r=kmag MozReview-Commit-ID: DPs36oFm25J
toolkit/components/extensions/ExtensionUtils.jsm
toolkit/components/extensions/test/mochitest/mochitest.ini
toolkit/components/extensions/test/mochitest/test_ext_runtime_connect_no_receiver.html
--- a/toolkit/components/extensions/ExtensionUtils.jsm
+++ b/toolkit/components/extensions/ExtensionUtils.jsm
@@ -1141,26 +1141,30 @@ Port.prototype = {
   handleDisconnection() {
     this.messageManager.removeMessageListener(this.disconnectName, this);
     this.context.forgetOnClose(this);
     this.disconnected = true;
   },
 
   receiveMessage(msg) {
     if (msg.name == this.disconnectName) {
-      if (this.disconnected) {
-        return;
-      }
+      this.disconnectByOtherEnd();
+    }
+  },
 
-      for (let listener of this.disconnectListeners) {
-        listener();
-      }
+  disconnectByOtherEnd() {
+    if (this.disconnected) {
+      return;
+    }
 
-      this.handleDisconnection();
+    for (let listener of this.disconnectListeners) {
+      listener();
     }
+
+    this.handleDisconnection();
   },
 
   disconnect() {
     if (this.disconnected) {
       // disconnect() may be called without side effects even after the port is
       // closed - https://developer.chrome.com/extensions/runtime#type-Port
       return;
     }
@@ -1277,18 +1281,18 @@ Messenger.prototype = {
     }).api();
   },
 
   connect(messageManager, name, recipient) {
     // TODO(robwu): Use a process ID instead of the process type. bugzil.la/1287626
     let portId = `${gNextPortId++}-${Services.appinfo.processType}`;
     let port = new Port(this.context, messageManager, name, portId, null);
     let msg = {name, portId};
-    // TODO: Disconnect the port if no response?
-    this._sendMessage(messageManager, "Extension:Connect", msg, recipient);
+    this._sendMessage(messageManager, "Extension:Connect", msg, recipient)
+      .catch(e => port.disconnectByOtherEnd());
     return port.api();
   },
 
   onConnect(name) {
     return new SingletonEventManager(this.context, name, callback => {
       let listener = {
         messageFilterPermissive: this.filter,
 
--- a/toolkit/components/extensions/test/mochitest/mochitest.ini
+++ b/toolkit/components/extensions/test/mochitest/mochitest.ini
@@ -58,16 +58,17 @@ skip-if = buildapp == 'b2g' # runat != d
 [test_ext_localStorage.html]
 [test_ext_onmessage_removelistener.html]
 [test_ext_notifications.html]
 [test_ext_permission_xhr.html]
 skip-if = buildapp == 'b2g' # JavaScript error: jar:remoteopenfile:///data/local/tmp/generated-extension.xpi!/content.js, line 46: NS_ERROR_ILLEGAL_VALUE:
 [test_ext_runtime_connect.html]
 skip-if = (os == 'android' || buildapp == 'b2g') # port.sender.tab is undefined on b2g. Bug 1258975 on android.
 [test_ext_runtime_connect_twoway.html]
+[test_ext_runtime_connect_no_receiver.html]
 skip-if = (os == 'android' || buildapp == 'b2g') # port.sender.tab is undefined on b2g. Bug 1258975 on android.
 [test_ext_runtime_connect2.html]
 skip-if = (os == 'android' || buildapp == 'b2g') # port.sender.tab is undefined on b2g. Bug 1258975 on android.
 [test_ext_runtime_disconnect.html]
 [test_ext_runtime_getPlatformInfo.html]
 [test_ext_runtime_id.html]
 [test_ext_runtime_sendMessage.html]
 [test_ext_runtime_sendMessage_no_receiver.html]
new file mode 100644
--- /dev/null
+++ b/toolkit/components/extensions/test/mochitest/test_ext_runtime_connect_no_receiver.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>WebExtension test</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script>
+  <script type="text/javascript" src="head.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+
+<script>
+"use strict";
+
+add_task(function* test_connect_without_listener() {
+  function backgroundScript() {
+    let port = browser.runtime.connect();
+    port.onDisconnect.addListener(() => {
+      browser.test.notifyPass("port.onDisconnect was called");
+    });
+  }
+  let extensionData = {
+    background: `(${backgroundScript})();`,
+  };
+
+  let extension = ExtensionTestUtils.loadExtension(extensionData);
+  yield extension.startup();
+
+  yield extension.awaitFinish("port.onDisconnect was called");
+
+  yield extension.unload();
+});
+</script>
+</body>