Bug 1276738 - Ensure that .open() on web content called with chrome privileges results in a new window with the appropriate principal. r?Gijs draft
authorMike Conley <mconley@mozilla.com>
Mon, 02 May 2016 17:36:12 -0400
changeset 374032 806d515d03b2dbfcdc9142dba001159f581aaae4
parent 374031 3988c5288705cca7af38e0e6eda2e9118b1d3cd6
child 374033 1effceea96cc773edb874cf1b068b067a31ee895
push id19904
push usermconley@mozilla.com
push dateWed, 01 Jun 2016 17:55:36 +0000
reviewersGijs
bugs1276738
milestone49.0a1
Bug 1276738 - Ensure that .open() on web content called with chrome privileges results in a new window with the appropriate principal. r?Gijs MozReview-Commit-ID: IG9ioQLTI78
embedding/components/windowwatcher/test/browser.ini
embedding/components/windowwatcher/test/browser_new_content_window_from_chrome_principal.js
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
--- a/embedding/components/windowwatcher/test/browser.ini
+++ b/embedding/components/windowwatcher/test/browser.ini
@@ -1,7 +1,8 @@
 [DEFAULT]
 tags = openwindow
 
 [browser_new_remote_window_flags.js]
 run-if = e10s
+[browser_new_content_window_from_chrome_principal.js]
 [browser_new_sized_window.js]
 skip-if = os == 'win' # Bug 1276802 - Opening windows from content on Windows might not get the size right
new file mode 100644
--- /dev/null
+++ b/embedding/components/windowwatcher/test/browser_new_content_window_from_chrome_principal.js
@@ -0,0 +1,34 @@
+"use strict";
+
+/**
+ * Tests that if chrome-privileged code calls .open() on an
+ * unprivileged window, that the principal in the newly
+ * opened window is appropriately set.
+ */
+add_task(function* test_chrome_opens_window() {
+  // This magic value of 2 means that by default, when content tries
+  // to open a new window, it'll actually open in a new window instead
+  // of a new tab.
+  yield SpecialPowers.pushPrefEnv({"set": [
+    ["browser.link.open_newwindow", 2],
+  ]});
+
+  let newWinPromise = BrowserTestUtils.waitForNewWindow(true, "http://example.com/");
+
+  yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
+    content.open("http://example.com/", "_blank");
+  });
+
+  let win = yield newWinPromise;
+  let browser = win.gBrowser.selectedBrowser;
+
+  yield ContentTask.spawn(browser, null, function*() {
+    Assert.ok(!content.document.nodePrincipal.isSystemPrincipal,
+              "We should not have a system principal.")
+    Assert.equal(content.document.nodePrincipal.origin,
+                 "http://example.com",
+                 "Should have the example.com principal");
+  });
+
+  yield BrowserTestUtils.closeWindow(win);
+});
\ No newline at end of file
--- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
+++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
@@ -274,25 +274,57 @@ this.BrowserTestUtils = {
 
       });
     });
   },
 
   /**
    * Waits for the next browser window to open and be fully loaded.
    *
+   * @param {bool} delayedStartup (optional)
+   *        Whether or not to wait for the browser-delayed-startup-finished
+   *        observer notification before resolving. Defaults to true.
+   * @param {string} initialBrowserLoaded (optional)
+   *        If set, we will wait until the initial browser in the new
+   *        window has loaded a particular page. If unset, the initial
+   *        browser may or may not have finished loading its first page
+   *        when the resulting Promise resolves.
    * @return {Promise}
    *         A Promise which resolves the next time that a DOM window
    *         opens and the delayed startup observer notification fires.
    */
-  waitForNewWindow: Task.async(function* (delayedStartup=true) {
+  waitForNewWindow: Task.async(function* (delayedStartup=true,
+                                          initialBrowserLoaded=null) {
     let win = yield this.domWindowOpened();
 
-    yield TestUtils.topicObserved("browser-delayed-startup-finished",
-                                   subject => subject == win);
+    let promises = [
+      TestUtils.topicObserved("browser-delayed-startup-finished",
+                              subject => subject == win),
+    ];
+
+    if (initialBrowserLoaded) {
+      yield this.waitForEvent(win, "DOMContentLoaded");
+
+      let browser = win.gBrowser.selectedBrowser;
+
+      // Retrieve the given browser's current process type.
+      let process =
+        browser.isRemoteBrowser ? Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
+                                : Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+      if (win.gMultiProcessBrowser &&
+          !E10SUtils.canLoadURIInProcess(initialBrowserLoaded, process)) {
+        yield this.waitForEvent(browser, "XULFrameLoaderCreated");
+      }
+
+      let loadPromise = this.browserLoaded(browser, false, initialBrowserLoaded);
+      promises.push(loadPromise);
+    }
+
+    yield Promise.all(promises);
+
     return win;
   }),
 
   /**
    * Loads a new URI in the given browser and waits until we really started
    * loading. In e10s browser.loadURI() can be an asynchronous operation due
    * to having to switch the browser's remoteness and keep its shistory data.
    *