Bug 1390282 - Allow RemotePageManager to accept an array of URLs r=mossop
authorahillier <ahillier@mozilla.com>
Tue, 15 Aug 2017 16:05:56 -0400
changeset 375090 7eed04597d5e
parent 375089 c570f065e0ad
child 375091 7c0790a19ee2
push id48918
push userkhudson@mozilla.com
push dateWed, 16 Aug 2017 14:17:35 +0000
treeherderautoland@7eed04597d5e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmossop
bugs1390282
milestone57.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 1390282 - Allow RemotePageManager to accept an array of URLs r=mossop 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>