Bug 1269347 - Part3 Add SDK with embedded webextension test addon. r=krizsa
authorLuca Greco <lgreco@mozilla.com>
Wed, 14 Sep 2016 17:09:22 +0200
changeset 314414 28459fc537c796d0ac0ca76887e82af239cf4451
parent 314413 013eb78e6709ad5ccbfb64dfc3980d8b0756081e
child 314415 9b321d41d837235eecd2d5c9a5b40d861a22d55b
push id20574
push usercbook@mozilla.com
push dateTue, 20 Sep 2016 10:05:16 +0000
treeherderfx-team@14705f779a46 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskrizsa
bugs1269347
milestone51.0a1
Bug 1269347 - Part3 Add SDK with embedded webextension test addon. r=krizsa This commit introduces a new SDK test addon, which tests the behavior of the new SDK module "sdk/webextension", and ensures that the provided API can be used to exchange messages between an SDK module and the WebExtension background page, and between an SDK module and a WebExtension content script. MozReview-Commit-ID: jJWfpF3HQM
addon-sdk/moz.build
addon-sdk/source/test/addons/embedded-webextension/main.js
addon-sdk/source/test/addons/embedded-webextension/package.json
addon-sdk/source/test/addons/embedded-webextension/webextension/background-page.js
addon-sdk/source/test/addons/embedded-webextension/webextension/content-script.js
addon-sdk/source/test/addons/embedded-webextension/webextension/manifest.json
addon-sdk/source/test/addons/jetpack-addon.ini
--- a/addon-sdk/moz.build
+++ b/addon-sdk/moz.build
@@ -27,16 +27,17 @@ addons = [
     'contributors',
     'curly-id',
     'developers',
     'e10s-content',
     'e10s-l10n',
     'e10s-remote',
     'e10s-tabs',
     'e10s',
+    'embedded-webextension',
     'l10n-properties',
     'l10n',
     'layout-change',
     'main',
     'name-in-numbers-plus',
     'name-in-numbers',
     'packaging',
     'packed',
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/main.js
@@ -0,0 +1,159 @@
+const tabs = require("sdk/tabs");
+const webExtension = require('sdk/webextension');
+
+exports.testEmbeddedWebExtensionModuleInitializedException = function (assert) {
+  let actualErr;
+
+  assert.throws(
+    () => webExtension.initFromBootstrapAddonParam({webExtension: null}),
+    /'sdk\/webextension' module has been already initialized/,
+    "Got the expected exception if the module is initialized twice"
+  );
+};
+
+exports.testEmbeddedWebExtensionBackgroungPage = function* (assert) {
+  try {
+    const api = yield webExtension.startup();
+    assert.ok(api, `webextension waitForStartup promise successfully resolved`);
+
+    const apiSecondStartup = yield webExtension.startup();
+    assert.equal(api, apiSecondStartup, "Got the same API object from the second startup call");
+
+    const {browser} = api;
+
+    let messageListener;
+    let waitForBackgroundPageMessage = new Promise((resolve, reject) => {
+      let numExpectedMessage = 2;
+      messageListener = (msg, sender, sendReply) => {
+        numExpectedMessage -= 1;
+        if (numExpectedMessage == 1) {
+          assert.equal(msg, "bg->sdk message",
+                       "Got the expected message from the background page");
+          sendReply("sdk reply");
+        } else if (numExpectedMessage == 0) {
+          assert.equal(msg, "sdk reply",
+                       "The background page received the expected reply message");
+          resolve();
+        } else {
+          console.error("Unexpected message received", {msg,sender, numExpectedMessage});
+          assert.ok(false, `unexpected message received`);
+          reject();
+        }
+      };
+      browser.runtime.onMessage.addListener(messageListener);
+    });
+
+    let portListener;
+    let waitForBackgroundPagePort = new Promise((resolve, reject) => {
+      portListener = (port) => {
+        let numExpectedMessages = 2;
+        port.onMessage.addListener((msg) => {
+          numExpectedMessages -= 1;
+
+          if (numExpectedMessages == 1) {
+            // Check that the legacy context has been able to receive the first port message
+            // and reply with a port message to the background page.
+            assert.equal(msg, "bg->sdk port message",
+                         "Got the expected port message from the background page");
+            port.postMessage("sdk->bg port message");
+          } else if (numExpectedMessages == 0) {
+            // Check that the background page has received the above port message.
+            assert.equal(msg, "bg received sdk->bg port message",
+                         "The background page received the expected port message");
+          }
+        });
+
+        port.onDisconnect.addListener(() => {
+          assert.equal(numExpectedMessages, 0, "Got the expected number of port messages");
+          resolve();
+        });
+      };
+      browser.runtime.onConnect.addListener(portListener);
+    });
+
+    yield Promise.all([
+      waitForBackgroundPageMessage,
+      waitForBackgroundPagePort,
+    ]).then(() => {
+      browser.runtime.onMessage.removeListener(messageListener);
+      browser.runtime.onConnect.removeListener(portListener);
+    });
+
+  } catch (err) {
+    assert.fail(`Unexpected webextension startup exception: ${err} - ${err.stack}`);
+  }
+};
+
+exports.testEmbeddedWebExtensionContentScript = function* (assert, done) {
+  try {
+    const {browser} = yield webExtension.startup();
+    assert.ok(browser, `webextension startup promise resolved successfully to the API object`);
+
+    let messageListener;
+    let waitForContentScriptMessage = new Promise((resolve, reject) => {
+      let numExpectedMessage = 2;
+      messageListener = (msg, sender, sendReply) => {
+        numExpectedMessage -= 1;
+        if (numExpectedMessage == 1) {
+          assert.equal(msg, "content script->sdk message",
+                       "Got the expected message from the content script");
+          sendReply("sdk reply");
+        } else if (numExpectedMessage == 0) {
+          assert.equal(msg, "sdk reply",
+                       "The content script received the expected reply message");
+          resolve();
+        } else {
+          console.error("Unexpected message received", {msg,sender, numExpectedMessage});
+          assert.ok(false, `unexpected message received`);
+          reject();
+        }
+      };
+      browser.runtime.onMessage.addListener(messageListener);
+    });
+
+    let portListener;
+    let waitForContentScriptPort = new Promise((resolve, reject) => {
+      portListener = (port) => {
+        let numExpectedMessages = 2;
+        port.onMessage.addListener((msg) => {
+          numExpectedMessages -= 1;
+
+          if (numExpectedMessages == 1) {
+            assert.equal(msg, "content script->sdk port message",
+                         "Got the expected message from the content script port");
+            port.postMessage("sdk->content script port message");
+          } else if (numExpectedMessages == 0) {
+            assert.equal(msg, "content script received sdk->content script port message",
+                         "The content script received the expected port message");
+          }
+        });
+        port.onDisconnect.addListener(() => {
+          assert.equal(numExpectedMessages, 0, "Got the epected number of port messages");
+          resolve();
+        });
+      };
+      browser.runtime.onConnect.addListener(portListener);
+    });
+
+    let url = "data:text/html;charset=utf-8,<h1>Test Page</h1>";
+
+    var openedTab;
+    tabs.once('open', function onOpen(tab) {
+      openedTab = tab;
+    });
+    tabs.open(url);
+
+    yield Promise.all([
+      waitForContentScriptMessage,
+      waitForContentScriptPort,
+    ]).then(() => {
+      browser.runtime.onMessage.removeListener(messageListener);
+      browser.runtime.onConnect.removeListener(portListener);
+      openedTab.close();
+    });
+  } catch (err) {
+    assert.fail(`Unexpected webextension startup exception: ${err} - ${err.stack}`);
+  }
+};
+
+require("sdk/test/runner").runTestsFromModule(module);
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/package.json
@@ -0,0 +1,6 @@
+{
+  "id": "embedded-webextension@jetpack",
+  "version": "0.1.0",
+  "main": "./main.js",
+  "hasEmbeddedWebExtension": true
+}
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/webextension/background-page.js
@@ -0,0 +1,10 @@
+browser.runtime.sendMessage("bg->sdk message", (reply) => {
+  browser.runtime.sendMessage(reply);
+});
+
+let port = browser.runtime.connect();
+port.onMessage.addListener((msg) => {
+  port.postMessage(`bg received ${msg}`);
+  port.disconnect();
+});
+port.postMessage("bg->sdk port message");
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/webextension/content-script.js
@@ -0,0 +1,10 @@
+browser.runtime.sendMessage("content script->sdk message", (reply) => {
+  browser.runtime.sendMessage(reply);
+});
+
+let port = browser.runtime.connect();
+port.onMessage.addListener((msg) => {
+  port.postMessage(`content script received ${msg}`);
+  port.disconnect();
+});
+port.postMessage("content script->sdk port message");
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/addons/embedded-webextension/webextension/manifest.json
@@ -0,0 +1,18 @@
+{
+  "name": "Test SDK Embedded WebExtension",
+  "description": "",
+  "version": "0.1.0",
+  "applications": {
+    "gecko": {
+      "id": "embedded-webextension@jetpack"
+    }
+  },
+  "manifest_version": 2,
+  "permissions": ["tabs"],
+  "background": {
+    "scripts": ["background-page.js"]
+  },
+  "content_scripts": [
+    {"matches": ["<all_urls>"], "js": ["content-script.js"]}
+  ]
+}
--- a/addon-sdk/source/test/addons/jetpack-addon.ini
+++ b/addon-sdk/source/test/addons/jetpack-addon.ini
@@ -12,16 +12,17 @@ skip-if = true
 [e10s-content.xpi]
 skip-if = true
 [e10s-l10n.xpi]
 skip-if = true
 [e10s-remote.xpi]
 skip-if = true
 [e10s-tabs.xpi]
 skip-if = true
+[embedded-webextension.xpi]
 [l10n.xpi]
 [l10n-properties.xpi]
 [layout-change.xpi]
 [main.xpi]
 [name-in-numbers.xpi]
 [name-in-numbers-plus.xpi]
 [packaging.xpi]
 [packed.xpi]