Bug 1335272 - prep: factor out registering about: pages into BTU, r=jaws
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Thu, 02 Feb 2017 14:34:40 +0000
changeset 341289 38740bd3a50e9d9ecec61bedc69092c1f49def88
parent 341288 bebe84133caea1d025c3600dc3bcbaed119bbb50
child 341290 494c40293b333e818e795482aad8a6c713a1cd48
push id86684
push usercbook@mozilla.com
push dateWed, 08 Feb 2017 10:31:03 +0000
treeherdermozilla-inbound@c5b88e4e70f4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1335272
milestone54.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 1335272 - prep: factor out registering about: pages into BTU, r=jaws MozReview-Commit-ID: 2B2j5xcbSWt
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_e10s_about_page_triggeringprincipal.js
browser/base/content/test/general/file_register_about_page.js
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
testing/mochitest/BrowserTestUtils/content/content-about-page-utils.js
testing/mochitest/jar.mn
testing/mochitest/tests/browser/browser.ini
testing/mochitest/tests/browser/browser_BrowserTestUtils.js
testing/mochitest/tests/browser/dummy.html
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -89,19 +89,16 @@ support-files =
   !/toolkit/mozapps/extensions/test/xpinstall/corrupt.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/incompatible.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/installtrigger.html
   !/toolkit/mozapps/extensions/test/xpinstall/redirect.sjs
   !/toolkit/mozapps/extensions/test/xpinstall/restartless-unsigned.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/theme.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/slowinstall.sjs
-  file_about_child.html
-  file_about_parent.html
-  file_register_about_page.js
 
 [browser_aboutAccounts.js]
 skip-if = os == "linux" # Bug 958026
 support-files =
   content_aboutAccounts.js
 [browser_aboutCertError.js]
 [browser_aboutNetError.js]
 [browser_aboutSupport_newtab_security_state.js]
@@ -422,16 +419,19 @@ skip-if = true # Bug 1005420 - fails int
 skip-if = (os == "win" && !debug)
 [browser_web_channel.js]
 [browser_windowopen_reflows.js]
 [browser_zbug569342.js]
 skip-if = e10s || debug # Bug 1094240 - has findbar-related failures
 [browser_registerProtocolHandler_notification.js]
 [browser_addCertException.js]
 [browser_e10s_about_page_triggeringprincipal.js]
+support-files =
+  file_about_child.html
+  file_about_parent.html
 [browser_e10s_switchbrowser.js]
 [browser_e10s_about_process.js]
 [browser_e10s_chrome_process.js]
 [browser_e10s_javascript.js]
 [browser_blockHPKP.js]
 tags = psm
 [browser_windowactivation.js]
 [browser_contextmenu_childprocess.js]
--- a/browser/base/content/test/general/browser_e10s_about_page_triggeringprincipal.js
+++ b/browser/base/content/test/general/browser_e10s_about_page_triggeringprincipal.js
@@ -1,26 +1,24 @@
 "use strict";
-Cu.import("resource://gre/modules/Services.jsm");
+
+const kChildPage = getRootDirectory(gTestPath) + "file_about_child.html";
+const kParentPage = getRootDirectory(gTestPath) + "file_about_parent.html";
 
-registerCleanupFunction(function() {
-  Services.ppmm.broadcastAsyncMessage("AboutPrincipalTest:Unregister");
-  BrowserTestUtils.waitForMessage(Services.ppmm, "AboutPrincipalTest:Unregistered").then(
-    Services.ppmm.removeDelayedProcessScript(
-      "chrome://mochitests/content/browser/browser/base/content/test/general/file_register_about_page.js"
-    )
-  );
-});
+const kAboutPagesRegistered = Promise.all([
+  BrowserTestUtils.registerAboutPage(
+    registerCleanupFunction, "test-about-principal-child", kChildPage,
+    Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD | Ci.nsIAboutModule.ALLOW_SCRIPT),
+  BrowserTestUtils.registerAboutPage(
+    registerCleanupFunction, "test-about-principal-parent", kParentPage,
+    Ci.nsIAboutModule.ALLOW_SCRIPT)
+]);
 
 add_task(function* test_principal_click() {
-  Services.ppmm.loadProcessScript(
-    "chrome://mochitests/content/browser/browser/base/content/test/general/file_register_about_page.js",
-    true
-  );
-
+  yield kAboutPagesRegistered;
   yield BrowserTestUtils.withNewTab("about:test-about-principal-parent", function*(browser) {
     let loadPromise = BrowserTestUtils.browserLoaded(browser, false, "about:test-about-principal-child");
     let myLink = browser.contentDocument.getElementById("aboutchildprincipal");
     myLink.click();
     yield loadPromise;
 
     yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function*() {
       let channel = content.document.docShell.currentDocumentChannel;
@@ -39,16 +37,17 @@ add_task(function* test_principal_click(
       let loadingPrincipal = channel.loadInfo.loadingPrincipal;
       is(loadingPrincipal, null,
          "sanity check - load of TYPE_DOCUMENT must have a null loadingPrincipal");
     });
   });
 });
 
 add_task(function* test_principal_ctrl_click() {
+  yield kAboutPagesRegistered;
   yield SpecialPowers.pushPrefEnv({
     "set": [["security.sandbox.content.level", 1]],
   });
 
   yield BrowserTestUtils.withNewTab("about:test-about-principal-parent", function*(browser) {
     let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:test-about-principal-child");
     // simulate ctrl+click
     BrowserTestUtils.synthesizeMouseAtCenter("#aboutchildprincipal",
@@ -75,16 +74,17 @@ add_task(function* test_principal_ctrl_c
       is(loadingPrincipal, null,
          "sanity check - load of TYPE_DOCUMENT must have a null loadingPrincipal");
     });
     yield BrowserTestUtils.removeTab(tab);
   });
 });
 
 add_task(function* test_principal_right_click_open_link_in_new_tab() {
+  yield kAboutPagesRegistered;
   yield SpecialPowers.pushPrefEnv({
     "set": [["security.sandbox.content.level", 1]],
   });
 
   yield BrowserTestUtils.withNewTab("about:test-about-principal-parent", function*(browser) {
     let loadPromise = BrowserTestUtils.waitForNewTab(gBrowser, "about:test-about-principal-child");
 
     // simulate right-click open link in tab
deleted file mode 100644
--- a/browser/base/content/test/general/file_register_about_page.js
+++ /dev/null
@@ -1,81 +0,0 @@
-const { interfaces: Ci, results: Cr, manager: Cm, utils: Cu } = Components;
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-function AboutPage(chromeURL, aboutHost, classID, description, uriFlags) {
-  this.chromeURL = chromeURL;
-  this.aboutHost = aboutHost;
-  this.classID = Components.ID(classID);
-  this.description = description;
-  this.uriFlags = uriFlags;
-}
-
-AboutPage.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
-  getURIFlags(aURI) { // eslint-disable-line no-unused-vars
-    return this.uriFlags;
-  },
-
-  newChannel(aURI, aLoadInfo) {
-    let newURI = Services.io.newURI(this.chromeURL);
-    let channel = Services.io.newChannelFromURIWithLoadInfo(newURI,
-                                                            aLoadInfo);
-    channel.originalURI = aURI;
-
-    if (this.uriFlags & Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT) {
-      channel.owner = null;
-    }
-    return channel;
-  },
-
-  createInstance(outer, iid) {
-    if (outer !== null) {
-      throw Cr.NS_ERROR_NO_AGGREGATION;
-    }
-    return this.QueryInterface(iid);
-  },
-
-  register() {
-    Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory(
-      this.classID, this.description,
-      "@mozilla.org/network/protocol/about;1?what=" + this.aboutHost, this);
-  },
-
-  unregister() {
-    Cm.QueryInterface(Ci.nsIComponentRegistrar).unregisterFactory(
-      this.classID, this);
-  }
-};
-
-/* exported AboutPrincipalTest */
-var AboutPrincipalTest = {};
-
-XPCOMUtils.defineLazyGetter(AboutPrincipalTest, "aboutChild", () =>
-  new AboutPage("chrome://mochitests/content/browser/browser/base/content/test/general/file_about_child.html",
-                "test-about-principal-child",
-                "{df6cbd19-c95b-4011-874b-315347c0832c}",
-                "About Principal Child Test",
-                Ci.nsIAboutModule.URI_MUST_LOAD_IN_CHILD |
-                Ci.nsIAboutModule.ALLOW_SCRIPT)
-
-);
-
-XPCOMUtils.defineLazyGetter(AboutPrincipalTest, "aboutParent", () =>
-  new AboutPage("chrome://mochitests/content/browser/browser/base/content/test/general/file_about_parent.html",
-                "test-about-principal-parent",
-                "{15e1a03d-9f94-4352-bfb8-94216140d3ab}",
-                "About Principal Parent Test",
-                Ci.nsIAboutModule.ALLOW_SCRIPT)
-);
-
-AboutPrincipalTest.aboutParent.register();
-AboutPrincipalTest.aboutChild.register();
-
-function onUnregisterMessage() {
-  removeMessageListener("AboutPrincipalTest:Unregister", onUnregisterMessage);
-  AboutPrincipalTest.aboutParent.unregister();
-  AboutPrincipalTest.aboutChild.unregister();
-  sendAsyncMessage("AboutPrincipalTest:Unregistered");
-}
-
-addMessageListener("AboutPrincipalTest:Unregister", onUnregisterMessage);
--- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
+++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
@@ -37,16 +37,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 // some cases.
 Cu.permitCPOWsInScope(this);
 
 var gSendCharCount = 0;
 var gSynthesizeKeyCount = 0;
 var gSynthesizeCompositionCount = 0;
 var gSynthesizeCompositionChangeCount = 0;
 
+const kAboutPageRegistrationContentScript =
+  "chrome://mochikit/content/tests/BrowserTestUtils/content-about-page-utils.js";
+
 this.BrowserTestUtils = {
   /**
    * Loads a page in a new tab, executes a Task and closes the tab.
    *
    * @param options
    *        An object  or string.
    *        If this is a string it is the url to open and will be opened in the
    *        currently active browser window.
@@ -1263,9 +1266,67 @@ this.BrowserTestUtils = {
       return new Promise((resolve) => {
         addEventListener("MozAfterPaint", function onPaint() {
           removeEventListener("MozAfterPaint", onPaint);
           resolve();
         })
       });
     });
   },
+
+  _knownAboutPages: new Set(),
+  _loadedAboutContentScript: false,
+  /**
+   * Registers an about: page with particular flags in both the parent
+   * and any content processes. Returns a promise that resolves when
+   * registration is complete.
+   *
+   * @param registerCleanupFunction (Function)
+   *        The test framework doesn't keep its cleanup stuff anywhere accessible,
+   *        so the first argument is a reference to your cleanup registration
+   *        function, allowing us to clean up after you if necessary.
+   * @param aboutModule (String)
+   *        The name of the about page.
+   * @param pageURI (String)
+   *        The URI the about: page should point to.
+   * @param flags (Number)
+   *        The nsIAboutModule flags to use for registration.
+   * @returns Promise that resolves when registration has finished.
+   */
+  registerAboutPage(registerCleanupFunction, aboutModule, pageURI, flags) {
+    // Return a promise that resolves when registration finished.
+    const kRegistrationMsgId = "browser-test-utils:about-registration:registered";
+    let rv = this.waitForMessage(Services.ppmm, kRegistrationMsgId, msg => {
+      return msg.data == aboutModule;
+    });
+    // Load a script that registers our page, then send it a message to execute the registration.
+    if (!this._loadedAboutContentScript) {
+      Services.ppmm.loadProcessScript(kAboutPageRegistrationContentScript, true);
+      this._loadedAboutContentScript = true;
+      registerCleanupFunction(this._removeAboutPageRegistrations.bind(this));
+    }
+    Services.ppmm.broadcastAsyncMessage("browser-test-utils:about-registration:register",
+                                        {aboutModule, pageURI, flags});
+    return rv.then(() => {
+      this._knownAboutPages.add(aboutModule);
+    });
+  },
+
+  unregisterAboutPage(aboutModule) {
+    if (!this._knownAboutPages.has(aboutModule)) {
+      return Promise.reject(new Error("We don't think this about page exists!"));
+    }
+    const kUnregistrationMsgId = "browser-test-utils:about-registration:unregistered";
+    let rv = this.waitForMessage(Services.ppmm, kUnregistrationMsgId, msg => {
+      return msg.data == aboutModule;
+    });
+    Services.ppmm.broadcastAsyncMessage("browser-test-utils:about-registration:unregister",
+                                        aboutModule);
+    return rv.then(() => this._knownAboutPages.delete(aboutModule));
+  },
+
+  *_removeAboutPageRegistrations() {
+    for (let aboutModule of this._knownAboutPages) {
+      yield this.unregisterAboutPage(aboutModule);
+    }
+    Services.ppmm.removeDelayedProcessScript(kAboutPageRegistrationContentScript);
+  },
 };
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/BrowserTestUtils/content/content-about-page-utils.js
@@ -0,0 +1,76 @@
+"use strict";
+
+var {classes: Cc, interfaces: Ci, utils: Cu, manager: Cm} = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+const { generateUUID } = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
+
+function AboutPage(aboutHost, chromeURL, uriFlags) {
+  this.chromeURL = chromeURL;
+  this.aboutHost = aboutHost;
+  this.classID = Components.ID(generateUUID().number);
+  this.description = "BrowserTestUtils: " + aboutHost;
+  this.uriFlags = uriFlags;
+}
+
+AboutPage.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
+  getURIFlags(aURI) { // eslint-disable-line no-unused-vars
+    return this.uriFlags;
+  },
+
+  newChannel(aURI, aLoadInfo) {
+    let newURI = Services.io.newURI(this.chromeURL);
+    let channel = Services.io.newChannelFromURIWithLoadInfo(newURI,
+                                                            aLoadInfo);
+    channel.originalURI = aURI;
+
+    if (this.uriFlags & Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT) {
+      channel.owner = null;
+    }
+    return channel;
+  },
+
+  createInstance(outer, iid) {
+    if (outer !== null) {
+      throw Cr.NS_ERROR_NO_AGGREGATION;
+    }
+    return this.QueryInterface(iid);
+  },
+
+  register() {
+    Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory(
+      this.classID, this.description,
+      "@mozilla.org/network/protocol/about;1?what=" + this.aboutHost, this);
+  },
+
+  unregister() {
+    Cm.QueryInterface(Ci.nsIComponentRegistrar).unregisterFactory(
+      this.classID, this);
+  }
+};
+
+const gRegisteredPages = new Map();
+
+addMessageListener("browser-test-utils:about-registration:register", msg => {
+  let {aboutModule, pageURI, flags} = msg.data;
+  if (gRegisteredPages.has(aboutModule)) {
+    gRegisteredPages.get(aboutModule).unregister();
+  }
+  let moduleObj = new AboutPage(aboutModule, pageURI, flags);
+  moduleObj.register();
+  gRegisteredPages.set(aboutModule, moduleObj);
+  sendAsyncMessage("browser-test-utils:about-registration:registered", aboutModule);
+});
+
+addMessageListener("browser-test-utils:about-registration:unregister", msg => {
+  let aboutModule = msg.data;
+  let moduleObj = gRegisteredPages.get(aboutModule);
+  if (moduleObj) {
+    moduleObj.unregister();
+    gRegisteredPages.delete(aboutModule);
+  }
+  sendAsyncMessage("browser-test-utils:about-registration:unregistered", aboutModule);
+});
--- a/testing/mochitest/jar.mn
+++ b/testing/mochitest/jar.mn
@@ -37,10 +37,11 @@ mochikit.jar:
   content/tests/SimpleTest/TestRunner.js (tests/SimpleTest/TestRunner.js)
   content/tests/SimpleTest/iframe-between-tests.html (tests/SimpleTest/iframe-between-tests.html)
   content/tests/SimpleTest/WindowSnapshot.js (tests/SimpleTest/WindowSnapshot.js)
   content/tests/SimpleTest/MockObjects.js (tests/SimpleTest/MockObjects.js)
   content/tests/SimpleTest/NativeKeyCodes.js (tests/SimpleTest/NativeKeyCodes.js)
   content/tests/SimpleTest/paint_listener.js (tests/SimpleTest/paint_listener.js)
   content/tests/SimpleTest/docshell_helpers.js (../../docshell/test/chrome/docshell_helpers.js)
   content/tests/BrowserTestUtils/content-task.js (BrowserTestUtils/content/content-task.js)
+  content/tests/BrowserTestUtils/content-about-page-utils.js (BrowserTestUtils/content/content-about-page-utils.js)
   content/tests/BrowserTestUtils/content-utils.js (BrowserTestUtils/content/content-utils.js)
 
--- a/testing/mochitest/tests/browser/browser.ini
+++ b/testing/mochitest/tests/browser/browser.ini
@@ -1,16 +1,18 @@
 [DEFAULT]
 support-files =
   head.js
 
 [browser_browserLoaded_content_loaded.js]
 [browser_add_task.js]
 [browser_async.js]
 [browser_BrowserTestUtils.js]
+support-files =
+  dummy.html
 [browser_head.js]
 [browser_pass.js]
 [browser_parameters.js]
 [browser_popupNode.js]
 [browser_popupNode_check.js]
 [browser_privileges.js]
 [browser_sanityException.js]
 [browser_sanityException2.js]
--- a/testing/mochitest/tests/browser/browser_BrowserTestUtils.js
+++ b/testing/mochitest/tests/browser/browser_BrowserTestUtils.js
@@ -42,8 +42,29 @@ add_task(function* () {
 
   cancelled = yield BrowserTestUtils.synthesizeMouseAtCenter("body > div", { type: "mouseup" }, browser);
   details = yield getLastEventDetails(browser);
   is(details, "div,40,84", "synthesizeMouseAtCenter mouseup with complex selector");
   ok(!cancelled, "synthesizeMouseAtCenter mouseup with complex selector cancelled");
 
   gBrowser.removeTab(tab);
 });
+
+add_task(function* () {
+  yield BrowserTestUtils.registerAboutPage(
+    registerCleanupFunction, "about-pages-are-cool",
+    getRootDirectory(gTestPath) + "dummy.html", 0);
+  let tab = yield BrowserTestUtils.openNewForegroundTab(
+    gBrowser, "about:about-pages-are-cool", true);
+  ok(tab, "Successfully created an about: page and loaded it.");
+  yield BrowserTestUtils.removeTab(tab);
+  try {
+    yield BrowserTestUtils.unregisterAboutPage("about-pages-are-cool");
+    ok(true, "Successfully unregistered the about page.");
+  } catch (ex) {
+    ok(false, "Should not throw unregistering a known about: page");
+  }
+  yield BrowserTestUtils.unregisterAboutPage("random-other-about-page").then(() => {
+    ok(false, "Should not have succeeded unregistering an unknown about: page.");
+  }, () => {
+    ok(true, "Should have returned a rejected promise trying to unregister an unknown about page");
+  });
+});
new file mode 100644
--- /dev/null
+++ b/testing/mochitest/tests/browser/dummy.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+  <title>This is a dummy page</title>
+  <meta charset="utf-8">
+  <body>This is a dummy page</body>
+</html>