Bug 1390282 - Allow RemotePageManager to accept an array of URLs draft
authorahillier <ahillier@mozilla.com>
Tue, 15 Aug 2017 16:05:56 -0400
changeset 646901 8e3723771696859a7593b9234c4777a8e91805e0
parent 645963 6213fec03a47275d8fcbf79b951547e3993d677f
child 726351 6c4d3767886dd8fc212ff21998a20fed3e7a2dd6
push id74237
push userbmo:ahillier@mozilla.com
push dateTue, 15 Aug 2017 20:06:49 +0000
bugs1390282
milestone57.0a1
Bug 1390282 - Allow RemotePageManager to accept an array of URLs MozReview-Commit-ID: vTQmUDabHI
toolkit/modules/RemotePageManager.jsm
toolkit/modules/tests/browser/browser.ini
toolkit/modules/tests/browser/browser_RemotePageManager.js
toolkit/modules/tests/browser/testremotepagemanager2.html
--- a/toolkit/modules/RemotePageManager.jsm
+++ b/toolkit/modules/RemotePageManager.jsm
@@ -51,50 +51,56 @@ MessageListener.prototype = {
       return;
 
     this.listeners.get(name).delete(callback);
   },
 }
 
 
 /**
- * Creates a RemotePages object which listens for new remote pages of a
- * particular URL. A "RemotePage:Init" message will be dispatched to this object
- * for every page loaded. Message listeners added to this object receive
- * messages from all loaded pages from the requested url.
+ * Creates a RemotePages object which listens for new remote pages of some
+ * particular URLs. A "RemotePage:Init" message will be dispatched to this
+ * object for every page loaded. Message listeners added to this object receive
+ * messages from all loaded pages from the requested urls.
  */
-this.RemotePages = function(url) {
-  this.url = url;
+this.RemotePages = function(urls) {
+  this.urls = Array.isArray(urls) ? urls : [urls];
   this.messagePorts = new Set();
   this.listener = new MessageListener();
   this.destroyed = false;
 
-  RemotePageManager.addRemotePageListener(url, this.portCreated.bind(this));
+  this.portCreated = this.portCreated.bind(this);
   this.portMessageReceived = this.portMessageReceived.bind(this);
+
+  for (const url of this.urls) {
+    RemotePageManager.addRemotePageListener(url, this.portCreated);
+  }
 }
 
 RemotePages.prototype = {
-  url: null,
+  urls: null,
   messagePorts: null,
   listener: null,
   destroyed: null,
 
   destroy() {
-    RemotePageManager.removeRemotePageListener(this.url);
+    for (const url of this.urls) {
+      RemotePageManager.removeRemotePageListener(url);
+    }
 
     for (let port of this.messagePorts.values()) {
       this.removeMessagePort(port);
     }
 
     this.messagePorts = null;
     this.listener = null;
     this.destroyed = true;
   },
 
-  // Called when a page matching the url has loaded in a frame.
+  // Called when a page matching one of the urls has loaded in a frame.
   portCreated(port) {
     this.messagePorts.add(port);
 
     port.loaded = false;
     port.addMessageListener("RemotePage:Load", this.portMessageReceived);
     port.addMessageListener("RemotePage:Unload", this.portMessageReceived);
 
     for (let name of this.listener.keys()) {
--- a/toolkit/modules/tests/browser/browser.ini
+++ b/toolkit/modules/tests/browser/browser.ini
@@ -1,13 +1,14 @@
 [DEFAULT]
 support-files =
   dummy_page.html
   metadata_*.html
   testremotepagemanager.html
+  testremotepagemanager2.html
   file_WebNavigation_page1.html
   file_WebNavigation_page2.html
   file_WebNavigation_page3.html
   file_WebRequest_page1.html
   file_WebRequest_page2.html
   file_image_good.png
   file_image_bad.png
   file_image_redirect.png
--- a/toolkit/modules/tests/browser/browser_RemotePageManager.js
+++ b/toolkit/modules/tests/browser/browser_RemotePageManager.js
@@ -31,26 +31,26 @@ function waitForPort(url, createTab = tr
       waitForMessage(port, "RemotePage:Load").then(() => resolve(port));
     });
 
     if (createTab)
       gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, url);
   });
 }
 
-function waitForPage(pages) {
+function waitForPage(pages, url = TEST_URL) {
   return new Promise((resolve) => {
     function listener({ target }) {
       pages.removeMessageListener("RemotePage:Init", listener);
 
       waitForMessage(target, "RemotePage:Load").then(() => resolve(target));
     }
 
     pages.addMessageListener("RemotePage:Init", listener);
-    gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, TEST_URL);
+    gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, url);
   });
 }
 
 function swapDocShells(browser1, browser2) {
   // Swap frameLoaders.
   browser1.swapDocShells(browser2);
 
   // Swap permanentKeys.
@@ -354,17 +354,17 @@ add_task(async function check_port_prope
   is(portFromUnload, portFromInit, "got the same port from init and unload");
   checkProperties(portFromUnload, "unloaded port");
   is(portFromInit.loaded, false, "unloaded port is now not loaded");
 
   pages.destroy();
 });
 
 // Test sending messages to all remote pages works
-add_task(async function remote_pages_multiple() {
+add_task(async function remote_pages_multiple_pages() {
   let pages = new RemotePages(TEST_URL);
   let port1 = await waitForPage(pages);
   let port2 = await waitForPage(pages);
 
   let pongPorts = [];
   await new Promise((resolve) => {
     function listener({ name, target, data }) {
       is(name, "Pong", "Should have seen the right response.");
@@ -388,16 +388,55 @@ add_task(async function remote_pages_mul
   // After destroy we should see no messages
   pages.addMessageListener("RemotePage:Unload", failOnMessage);
   pages.destroy();
 
   gBrowser.removeTab(gBrowser.getTabForBrowser(port1.browser));
   gBrowser.removeTab(gBrowser.getTabForBrowser(port2.browser));
 });
 
+// Test that RemotePages with multiple urls works
+add_task(async function remote_pages_multiple_urls() {
+  const TEST_URLS = [TEST_URL, TEST_URL.replace(".html", "2.html")];
+  const pages = new RemotePages(TEST_URLS);
+
+  const ports = [];
+  // Load two pages for each url
+  for (const [i, url] of TEST_URLS.entries()) {
+    const port = await waitForPage(pages, url);
+    is(port.browser, gBrowser.selectedBrowser, `port${i} is for the correct browser`);
+    ports.push(port);
+    ports.push(await waitForPage(pages, url));
+  }
+
+  let unloadPromise = waitForMessage(pages, "RemotePage:Unload", ports.pop());
+  gBrowser.removeCurrentTab();
+  await unloadPromise;
+
+  const pongPorts = new Set();
+  await new Promise(resolve => {
+    function listener({ name, target, data }) {
+      is(name, "Pong", "Should have seen the right response.");
+      is(data.str, "FAKE_DATA", "String should pass through");
+      is(data.counter, 1235, "Counter should be incremented");
+      pongPorts.add(target);
+      if (pongPorts.size === ports.length)
+        resolve();
+    }
+
+    pages.addMessageListener("Pong", listener);
+    pages.sendAsyncMessage("Ping", {str: "FAKE_DATA", counter: 1234});
+  });
+
+  ports.forEach(port => ok(pongPorts.has(port)));
+
+  pages.destroy();
+  ports.forEach(port => gBrowser.removeTab(gBrowser.getTabForBrowser(port.browser)));
+});
+
 // Test sending various types of data across the boundary
 add_task(async function send_data() {
   let port = await waitForPort(TEST_URL);
   is(port.browser, gBrowser.selectedBrowser, "Port is for the correct browser");
 
   let data = {
     integer: 45,
     real: 45.78,
new file mode 100644
--- /dev/null
+++ b/toolkit/modules/tests/browser/testremotepagemanager2.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<!-- A second page to test that RemotePages works with multiple urls -->
+<html>
+<head>
+<script type="text/javascript">
+/* global addMessageListener, sendAsyncMessage */
+
+addMessageListener("Ping", function(message) {
+  sendAsyncMessage("Pong", {
+    str: message.data.str,
+    counter: message.data.counter + 1
+  });
+});
+
+</script>
+</head>
+<body>
+</body>
+</html>