Bug 1390282 - Allow RemotePageManager to accept an array of URLs
MozReview-Commit-ID: vTQmUDabHI
--- 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>