Backed out 25 changesets (bug 1261842, bug 1278985) breaking firefox-ui tests
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 19 Jul 2016 09:12:58 +0200
changeset 305499 ad32bf1994e92f6cbe3e54f30e5f8f804f9efb44
parent 305498 d9b88cb3db769b183fb5ea8ba19beaac562153f1
child 305500 717184f2678e716b237a331128182869da72f943
push id79596
push usercbook@mozilla.com
push dateTue, 19 Jul 2016 07:13:21 +0000
treeherdermozilla-inbound@ad32bf1994e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1261842, 1278985
milestone50.0a1
backs outbb6c6889b802f469103df297e7c2fb417ec2961d
c14ccfac7b4b635cad9f728b85767deef68078be
d6ffc9db53461550f8965e3587244b5b9d68eab6
2a1acfd17baf3a269719c70cdd5b273e8b344b41
968e7b3b73fbc288cdda9b0ba82857065e00d956
8d708922e47ac2a5c56a8bceded6a84701536e17
0a08398b508752250588f9b46726ad90ec51637b
b2e910bb1d726562548eba1148a81ec37300fb7b
f6062f1139114f586e3ea9f6d946766f63dedb1d
07b259eb7121dde270818a3ca280cd658b83c795
970cbbb3a658336a8a70cfea01ba5a6afa3ae58b
b6f7395d2bbff04ba48419d30ebecf848771e9fc
20eb3987a721a2c0a312868cf52dbf2f43563236
6eaa642a93e1707ae917f9e6f61242ecef36c658
855931929739ab4f44ff92f7549b4d80348b580b
1240345f5624539c14543dc21888ce1f74f9059b
ce46ebf231c1d679c9bc7abc28f774538b5a1362
8d34b61fbfb395d6816c45dcc1f45901e627c478
9d8a382c5b1dcbaa07cb827e86652065f147f368
e2472a4cc209e0be8a083dd254965598d41f53c6
e91913cd64b8bebe80c661935adee644f24c6055
4cf843a05a68d55d1686d5cf347864563a623f97
cbdc0deb92bd5bcbae0be65c7bbd5ad020f7a153
a94e6a85c93170ef6b40065bb1834167547acd03
3b5b92f04ea56dcf8fb123585a6ea2eaba550614
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
Backed out 25 changesets (bug 1261842, bug 1278985) breaking firefox-ui tests Backed out changeset bb6c6889b802 (bug 1261842) Backed out changeset c14ccfac7b4b (bug 1261842) Backed out changeset d6ffc9db5346 (bug 1261842) Backed out changeset 2a1acfd17baf (bug 1261842) Backed out changeset 968e7b3b73fb (bug 1261842) Backed out changeset 8d708922e47a (bug 1261842) Backed out changeset 0a08398b5087 (bug 1261842) Backed out changeset b2e910bb1d72 (bug 1261842) Backed out changeset f6062f113911 (bug 1261842) Backed out changeset 07b259eb7121 (bug 1261842) Backed out changeset 970cbbb3a658 (bug 1261842) Backed out changeset b6f7395d2bbf (bug 1261842) Backed out changeset 20eb3987a721 (bug 1261842) Backed out changeset 6eaa642a93e1 (bug 1261842) Backed out changeset 855931929739 (bug 1261842) Backed out changeset 1240345f5624 (bug 1261842) Backed out changeset ce46ebf231c1 (bug 1261842) Backed out changeset 8d34b61fbfb3 (bug 1261842) Backed out changeset 9d8a382c5b1d (bug 1261842) Backed out changeset e2472a4cc209 (bug 1261842) Backed out changeset e91913cd64b8 (bug 1261842) Backed out changeset 4cf843a05a68 (bug 1261842) Backed out changeset cbdc0deb92bd (bug 1261842) Backed out changeset a94e6a85c931 (bug 1261842) Backed out changeset 3b5b92f04ea5 (bug 1278985)
browser/base/content/browser.js
browser/base/content/test/general/browser.ini
browser/base/content/test/general/browser_bug495058.js
browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js
browser/components/privatebrowsing/test/browser/browser.ini
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_toggle.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_noSessionRestoreMenuOption.js
browser/components/privatebrowsing/test/browser/browser_privatebrowsing_nonbrowser.js
browser/components/sessionstore/SessionStore.jsm
browser/components/sessionstore/test/browser_394759_behavior.js
browser/components/sessionstore/test/browser_423132.js
browser/components/sessionstore/test/browser_async_window_flushing.js
browser/components/sessionstore/test/browser_windowStateContainer.js
docshell/base/nsIDocShellTreeOwner.idl
dom/base/nsGlobalWindow.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/workers/ServiceWorkerClients.cpp
embedding/browser/nsDocShellTreeOwner.cpp
embedding/components/windowwatcher/moz.build
embedding/components/windowwatcher/nsPIWindowWatcher.idl
embedding/components/windowwatcher/nsWindowWatcher.cpp
embedding/components/windowwatcher/nsWindowWatcher.h
embedding/components/windowwatcher/test/browser.ini
embedding/components/windowwatcher/test/browser_new_content_window_chromeflags.js
embedding/nsIWindowCreator2.idl
testing/marionette/listener.js
testing/talos/talos/pageloader/chrome/pageloader.js
testing/talos/talos/pageloader/install.rdf
testing/talos/talos/pageloader/pageloader-signed.xpi
toolkit/components/extensions/Extension.jsm
toolkit/components/startup/nsAppStartup.cpp
xpfe/appshell/moz.build
xpfe/appshell/nsChromeTreeOwner.cpp
xpfe/appshell/nsContentTreeOwner.cpp
xpfe/appshell/nsIXULBrowserWindow.idl
xpfe/appshell/nsIXULWindow.idl
xpfe/appshell/nsXULWindow.cpp
xpfe/appshell/nsXULWindow.h
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -909,40 +909,16 @@ function RedirectLoad({ target: browser,
       }
     };
     Services.obs.addObserver(delayedStartupFinished,
                              "browser-delayed-startup-finished",
                              false);
   }
 }
 
-addEventListener("DOMContentLoaded", function onDCL() {
-  removeEventListener("DOMContentLoaded", onDCL);
-
-  // There are some windows, like macBrowserOverlay.xul, that
-  // load browser.js, but never load tabbrowser.xml. We can ignore
-  // those cases.
-  if (!gBrowser || !gBrowser.updateBrowserRemoteness) {
-    return;
-  }
-
-  window.QueryInterface(Ci.nsIInterfaceRequestor)
-        .getInterface(nsIWebNavigation)
-        .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
-        .QueryInterface(Ci.nsIInterfaceRequestor)
-        .getInterface(Ci.nsIXULWindow)
-        .XULBrowserWindow = window.XULBrowserWindow;
-  window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
-    new nsBrowserAccess();
-
-  let initBrowser =
-    document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
-  gBrowser.updateBrowserRemoteness(initBrowser, gMultiProcessBrowser);
-});
-
 var gBrowserInit = {
   delayedStartupFinished: false,
 
   onLoad: function() {
     gBrowser.addEventListener("DOMUpdatePageReport", gPopupBlockerObserver, false);
 
     Services.obs.addObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed", false);
 
@@ -963,21 +939,29 @@ var gBrowserInit = {
     RefreshBlocker.init();
 
     let mm = window.getGroupMessageManager("browsers");
     mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
     mm.loadFrameScript("chrome://browser/content/content.js", true);
     mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
     mm.loadFrameScript("chrome://global/content/manifestMessages.js", true);
 
+    window.messageManager.addMessageListener("Browser:LoadURI", RedirectLoad);
+
     // initialize observers and listeners
     // and give C++ access to gBrowser
     XULBrowserWindow.init();
-
-    window.messageManager.addMessageListener("Browser:LoadURI", RedirectLoad);
+    window.QueryInterface(Ci.nsIInterfaceRequestor)
+          .getInterface(nsIWebNavigation)
+          .QueryInterface(Ci.nsIDocShellTreeItem).treeOwner
+          .QueryInterface(Ci.nsIInterfaceRequestor)
+          .getInterface(Ci.nsIXULWindow)
+          .XULBrowserWindow = window.XULBrowserWindow;
+    window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow =
+      new nsBrowserAccess();
 
     if (!gMultiProcessBrowser) {
       // There is a Content:Click message manually sent from content.
       Cc["@mozilla.org/eventlistenerservice;1"]
         .getService(Ci.nsIEventListenerService)
         .addSystemEventListener(gBrowser, "click", contentAreaClick, true);
     }
 
@@ -1114,38 +1098,33 @@ var gBrowserInit = {
           window.arguments[0] = null;
         }
 
         // Stop the about:blank load
         gBrowser.stop();
         // make sure it has a docshell
         gBrowser.docShell;
 
-        // We must set usercontextid before updateBrowserRemoteness()
-        // so that the newly created remote tab child has correct usercontextid
-        if (tabToOpen.hasAttribute("usercontextid")) {
-          let usercontextid = tabToOpen.getAttribute("usercontextid");
-          gBrowser.selectedBrowser.setAttribute("usercontextid", usercontextid);
-        }
-
         // If the browser that we're swapping in was remote, then we'd better
         // be able to support remote browsers, and then make our selectedTab
         // remote.
         try {
           if (tabToOpen.linkedBrowser.isRemoteBrowser) {
             if (!gMultiProcessBrowser) {
               throw new Error("Cannot drag a remote browser into a window " +
                               "without the remote tabs load context.");
             }
+
+            // We must set usercontextid before updateBrowserRemoteness()
+            // so that the newly created remote tab child has correct usercontextid
+            if (tabToOpen.hasAttribute("usercontextid")) {
+              let usercontextid = tabToOpen.getAttribute("usercontextid");
+              gBrowser.selectedBrowser.setAttribute("usercontextid", usercontextid);
+            }
             gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true);
-          } else if (gBrowser.selectedBrowser.isRemoteBrowser) {
-            // If the browser is remote, then it's implied that
-            // gMultiProcessBrowser is true. We need to flip the remoteness
-            // of this tab to false in order for the tab drag to work.
-            gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, false);
           }
           gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, tabToOpen);
         } catch(e) {
           Cu.reportError(e);
         }
       }
       // window.arguments[2]: referrer (nsIURI | string)
       //                 [3]: postData (nsIInputStream)
@@ -4214,25 +4193,20 @@ var XULBrowserWindow = {
 
   setJSStatus: function () {
     // unsupported
   },
 
   forceInitialBrowserRemote: function() {
     let initBrowser =
       document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
+    gBrowser.updateBrowserRemoteness(initBrowser, true);
     return initBrowser.frameLoader.tabParent;
   },
 
-  forceInitialBrowserNonRemote: function() {
-    let initBrowser =
-      document.getAnonymousElementByAttribute(gBrowser, "anonid", "initialBrowser");
-    gBrowser.updateBrowserRemoteness(initBrowser, false);
-  },
-
   setDefaultStatus: function (status) {
     this.defaultStatus = status;
     this.updateStatusField();
   },
 
   setOverLink: function (url, anchorElt) {
     // Encode bidirectional formatting characters.
     // (RFC 3987 sections 3.2 and 4.1 paragraph 6)
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -274,17 +274,16 @@ tags = mcb
 [browser_bug1015721.js]
 skip-if = os == 'win'
 [browser_bug1064280_changeUrlInPinnedTab.js]
 [browser_accesskeys.js]
 [browser_clipboard.js]
 subsuite = clipboard
 [browser_clipboard_pastefile.js]
 [browser_contentAreaClick.js]
-skip-if = e10s # Clicks in content don't go through contentAreaClick with e10s.
 [browser_contextmenu.js]
 tags = fullscreen
 skip-if = toolkit == "gtk2" || toolkit == "gtk3" # disabled on Linux due to bug 513558
 [browser_contextmenu_input.js]
 skip-if = toolkit == "gtk2" || toolkit == "gtk3" # disabled on Linux due to bug 513558
 [browser_ctrlTab.js]
 [browser_datachoices_notification.js]
 skip-if = !datareporting
--- a/browser/base/content/test/general/browser_bug495058.js
+++ b/browser/base/content/test/general/browser_bug495058.js
@@ -10,29 +10,41 @@ const URIS = [
 ];
 
 add_task(function*() {
   for (let uri of URIS) {
     let tab = gBrowser.addTab();
     yield BrowserTestUtils.loadURI(tab.linkedBrowser, uri);
 
     let win = gBrowser.replaceTabWithWindow(tab);
-    yield TestUtils.topicObserved("browser-delayed-startup-finished",
-                                  subject => subject == win);
+    yield BrowserTestUtils.waitForEvent(win, "load");
+
     tab = win.gBrowser.selectedTab;
 
-    // BrowserTestUtils doesn't get the add-on shims, which means that
-    // MozAfterPaint won't get shimmed over if we add an event handler
-    // for it in the parent.
-    if (tab.linkedBrowser.isRemoteBrowser) {
-      yield BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "MozAfterPaint");
-    } else {
-      yield BrowserTestUtils.waitForEvent(tab.linkedBrowser, "MozAfterPaint");
+    // By default, we'll wait for MozAfterPaint to come up through the
+    // browser element. We'll handle the e10s case in the next block.
+    let contentPainted = BrowserTestUtils.waitForEvent(tab.linkedBrowser,
+                                                       "MozAfterPaint");
+
+    let delayedStartup =
+      TestUtils.topicObserved("browser-delayed-startup-finished",
+                              subject => subject == win);
+
+    if (gMultiProcessBrowser &&
+        E10SUtils.canLoadURIInProcess(uri, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT)) {
+      // Until bug 1261842 is fixed, the initial browser is going to be
+      // non-remote. If we're transitioning to a URL that can be loaded
+      // remotely, we'll need to wait until that remoteness switch is done
+      // before we send any framescripts down to the browser.
+      yield BrowserTestUtils.waitForEvent(tab, "TabRemotenessChange");
+      contentPainted = BrowserTestUtils.contentPainted(tab.linkedBrowser);
     }
 
+    yield Promise.all([delayedStartup, contentPainted]);
+
     Assert.equal(win.gBrowser.currentURI.spec, uri, uri + ": uri loaded in detached tab");
     Assert.equal(win.document.activeElement, win.gBrowser.selectedBrowser, uri + ": browser is focused");
     Assert.equal(win.gURLBar.value, "", uri + ": urlbar is empty");
     Assert.ok(win.gURLBar.placeholder, uri + ": placeholder text is present");
 
     yield BrowserTestUtils.closeWindow(win);
   }
 });
--- a/browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js
+++ b/browser/base/content/test/general/browser_testOpenNewRemoteTabsFromNonRemoteBrowsers.js
@@ -33,23 +33,23 @@ registerCleanupFunction(() => {
   Services.prefs.clearUserPref(OPEN_LOCATION_PREF);
 });
 
 /**
  * Test that if we open a new tab from a link in a non-remote
  * browser in an e10s window, that the new tab will load properly.
  */
 add_task(function* test_new_tab() {
-  let normalWindow = yield BrowserTestUtils.openNewBrowserWindow({
-    remote: true,
-  });
-  let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({
+  let normalWindow = yield promiseOpenAndLoadWindow({
+    remote: true
+  }, true);
+  let privateWindow = yield promiseOpenAndLoadWindow({
     remote: true,
     private: true,
-  });
+  }, true);
 
   for (let testWindow of [normalWindow, privateWindow]) {
     yield promiseWaitForFocus(testWindow);
     let testBrowser = testWindow.gBrowser.selectedBrowser;
     info("Preparing non-remote browser");
     yield prepareNonRemoteBrowser(testWindow, testBrowser);
     info("Non-remote browser prepared - sending frame script");
 
@@ -75,20 +75,20 @@ add_task(function* test_new_tab() {
 });
 
 /**
  * Test that if we open a new window from a link in a non-remote
  * browser in an e10s window, that the new window is not an e10s
  * window. Also tests with a private browsing window.
  */
 add_task(function* test_new_window() {
-  let normalWindow = yield BrowserTestUtils.openNewBrowserWindow({
+  let normalWindow = yield promiseOpenAndLoadWindow({
     remote: true
   }, true);
-  let privateWindow = yield BrowserTestUtils.openNewBrowserWindow({
+  let privateWindow = yield promiseOpenAndLoadWindow({
     remote: true,
     private: true,
   }, true);
 
   // Fiddle with the prefs so that we open target="_blank" links
   // in new windows instead of new tabs.
   Services.prefs.setIntPref(OPEN_LOCATION_PREF,
                             Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW);
--- a/browser/components/privatebrowsing/test/browser/browser.ini
+++ b/browser/components/privatebrowsing/test/browser/browser.ini
@@ -19,17 +19,16 @@ support-files =
 [browser_privatebrowsing_DownloadLastDirWithCPS.js]
 [browser_privatebrowsing_about.js]
 tags = trackingprotection
 [browser_privatebrowsing_aboutHomeButtonAfterWindowClose.js]
 [browser_privatebrowsing_aboutSessionRestore.js]
 [browser_privatebrowsing_cache.js]
 [browser_privatebrowsing_certexceptionsui.js]
 [browser_privatebrowsing_concurrent.js]
-[browser_privatebrowsing_context_and_chromeFlags.js]
 [browser_privatebrowsing_crh.js]
 [browser_privatebrowsing_downloadLastDir.js]
 [browser_privatebrowsing_downloadLastDir_c.js]
 [browser_privatebrowsing_downloadLastDir_toggle.js]
 [browser_privatebrowsing_geoprompt.js]
 [browser_privatebrowsing_lastpbcontextexited.js]
 [browser_privatebrowsing_localStorage.js]
 [browser_privatebrowsing_localStorage_before_after.js]
deleted file mode 100644
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_context_and_chromeFlags.js
+++ /dev/null
@@ -1,60 +0,0 @@
-"use strict";
-
-/**
- * Given some window in the parent process, ensure that
- * the nsIXULWindow has the CHROME_PRIVATE_WINDOW chromeFlag,
- * and that the usePrivateBrowsing property is set to true on
- * both the window's nsILoadContext, as well as on the initial
- * browser's content docShell nsILoadContext.
- *
- * @param win (nsIDOMWindow)
- *        An nsIDOMWindow in the parent process.
- * @return Promise
- */
-function assertWindowIsPrivate(win) {
-  let winDocShell = win.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIDocShell);
-  let chromeFlags = winDocShell.QueryInterface(Ci.nsIDocShellTreeItem)
-                               .treeOwner
-                               .QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIXULWindow)
-                               .chromeFlags;
-
-  if (!win.gBrowser.selectedBrowser.hasContentOpener) {
-    Assert.ok(chromeFlags & Ci.nsIWebBrowserChrome.CHROME_PRIVATE_WINDOW,
-              "Should have the private window chrome flag");
-  }
-
-  let loadContext = winDocShell.QueryInterface(Ci.nsILoadContext);
-  Assert.ok(loadContext.usePrivateBrowsing,
-            "The parent window should be using private browsing");
-
-  return ContentTask.spawn(win.gBrowser.selectedBrowser, null, function*() {
-    let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
-    Assert.ok(loadContext.usePrivateBrowsing,
-              "Content docShell should be using private browsing");
-  });
-}
-
-/**
- * Tests that chromeFlags bits and the nsILoadContext.usePrivateBrowsing
- * attribute are properly set when opening a new private browsing
- * window.
- */
-add_task(function* test_context_and_chromeFlags() {
-  let win = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
-  yield assertWindowIsPrivate(win);
-
-  let browser = win.gBrowser.selectedBrowser;
-
-  let newWinPromise = BrowserTestUtils.waitForNewWindow();
-  yield ContentTask.spawn(browser, null, function*() {
-    content.open("http://example.com", "_blank", "width=100,height=100");
-  });
-
-  let win2 = yield newWinPromise;
-  yield assertWindowIsPrivate(win2);
-
-  yield BrowserTestUtils.closeWindow(win2);
-  yield BrowserTestUtils.closeWindow(win);
-});
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_toggle.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_downloadLastDir_toggle.js
@@ -1,105 +1,97 @@
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/DownloadLastDir.jsm");
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-/**
- * Tests how the browser remembers the last download folder
- * from download to download, with a particular emphasis
- * on how it behaves when private browsing windows open.
- */
-add_task(function* test_downloads_last_dir_toggle() {
+function test() {
+  waitForExplicitFinish();
+
+  let FileUtils =
+    Cu.import("resource://gre/modules/FileUtils.jsm", {}).FileUtils;
+  let DownloadLastDir =
+    Cu.import("resource://gre/modules/DownloadLastDir.jsm", {}).DownloadLastDir;
+
   let tmpDir = FileUtils.getDir("TmpD", [], true);
   let dir1 = newDirectory();
 
   registerCleanupFunction(function () {
     Services.prefs.clearUserPref("browser.download.lastDir");
     dir1.remove(true);
   });
 
-  let win = yield BrowserTestUtils.openNewBrowserWindow();
-  let gDownloadLastDir = new DownloadLastDir(win);
-  is(typeof gDownloadLastDir, "object",
-     "gDownloadLastDir should be a valid object");
-  is(gDownloadLastDir.file, null,
-     "gDownloadLastDir.file should be null to start with");
+  function testOnWindow(aPrivate, aCallback) {
+    whenNewWindowLoaded({private: aPrivate}, function(win) {
+      let gDownloadLastDir = new DownloadLastDir(win);
+      aCallback(win, gDownloadLastDir);
+      gDownloadLastDir.cleanupPrivateFile();
+      win.close();
+    });
+  }
 
-  gDownloadLastDir.file = tmpDir;
-  is(gDownloadLastDir.file.path, tmpDir.path,
-     "LastDir should point to the temporary directory");
-  isnot(gDownloadLastDir.file, tmpDir,
-        "gDownloadLastDir.file should not be pointing to the tmpDir");
-
-  gDownloadLastDir.file = 1; // not an nsIFile
-  is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
+  function checkDownloadLastDirInit(aWin, gDownloadLastDir, aCallback) {
+    is(typeof gDownloadLastDir, "object",
+       "gDownloadLastDir should be a valid object");
+    is(gDownloadLastDir.file, null,
+       "gDownloadLastDir.file should be null to start with");
 
-  gDownloadLastDir.file = tmpDir;
-  clearHistory();
-  is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
-
-  gDownloadLastDir.file = tmpDir;
-  yield BrowserTestUtils.closeWindow(win);
+    gDownloadLastDir.file = tmpDir;
+    is(gDownloadLastDir.file.path, tmpDir.path,
+       "LastDir should point to the temporary directory");
+    isnot(gDownloadLastDir.file, tmpDir,
+          "gDownloadLastDir.file should not be pointing to the tmpDir");
 
-  info("Opening the first private window");
-  yield testHelper({ private: true, expectedDir: tmpDir });
-  info("Opening a non-private window");
-  yield testHelper({ private: false, expectedDir: tmpDir });
-  info("Opening a private window and setting download directory");
-  yield testHelper({ private: true, setDir: dir1, expectedDir: dir1 });
-  info("Opening a non-private window and checking download directory");
-  yield testHelper({ private: false, expectedDir: tmpDir });
-  info("Opening private window and clearing history");
-  yield testHelper({ private: true, clearHistory: true, expectedDir: null });
-  info("Opening a non-private window and checking download directory");
-  yield testHelper({ private: true, expectedDir: null });
-});
+    gDownloadLastDir.file = 1; // not an nsIFile
+    is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
+
+    gDownloadLastDir.file = tmpDir;
+    clearHistory();
+    is(gDownloadLastDir.file, null, "gDownloadLastDir.file should be null");
+
+    gDownloadLastDir.file = tmpDir;
+    aCallback();
+  }
 
-/**
- * Opens a new window and performs some test actions on it based
- * on the options object that have been passed in.
- *
- * @param options (Object)
- *        An object with the following properties:
- *
- *        clearHistory (bool, optional):
- *          Whether or not to simulate clearing session history.
- *          Defaults to false.
- *
- *        setDir (nsIFile, optional):
- *          An nsIFile for setting the last download directory.
- *          If not set, the load download directory is not changed.
- *
- *        expectedDir (nsIFile, expectedDir):
- *          An nsIFile for what we expect the last download directory
- *          should be. The nsIFile is not compared directly - only
- *          paths are compared. If expectedDir is not set, then the
- *          last download directory is expected to be null.
- *
- * @returns Promise
- */
-function testHelper(options) {
-  return new Task.spawn(function() {
-    let win = yield BrowserTestUtils.openNewBrowserWindow(options);
-    let gDownloadLastDir = new DownloadLastDir(win);
+  function checkDownloadLastDir(aWin, gDownloadLastDir, aLastDir, aUpdate, aCallback) {
+    if (aUpdate)
+      gDownloadLastDir.file = aLastDir;
+    is(gDownloadLastDir.file.path, aLastDir.path,
+       "gDownloadLastDir should point to the expected last directory");
+    isnot(gDownloadLastDir.file, aLastDir,
+          "gDownloadLastDir.file should not be pointing to the last directory");
+    aCallback();
+  }
+
+  function checkDownloadLastDirNull(aWin, gDownloadLastDir, aCallback) {
+    is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
+    aCallback();
+  }
 
-    if (options.clearHistory) {
-      clearHistory();
-    }
-
-    if (options.setDir) {
-      gDownloadLastDir.file = options.setDir;
-    }
-
-    let expectedDir = options.expectedDir;
-
-    if (expectedDir) {
-      is(gDownloadLastDir.file.path, expectedDir.path,
-         "gDownloadLastDir should point to the expected last directory");
-      isnot(gDownloadLastDir.file, expectedDir,
-            "gDownloadLastDir.file should not be pointing to the last directory");
-    } else {
-      is(gDownloadLastDir.file, null, "gDownloadLastDir should be null");
-    }
-
-    gDownloadLastDir.cleanupPrivateFile();
-    yield BrowserTestUtils.closeWindow(win);
+  testOnWindow(false, function(win, downloadDir) {
+    checkDownloadLastDirInit(win, downloadDir, function() {
+      testOnWindow(true, function(win, downloadDir) {
+        checkDownloadLastDir(win, downloadDir, tmpDir, false, function() {
+          testOnWindow(false, function(win, downloadDir) {
+            checkDownloadLastDir(win, downloadDir, tmpDir, false, function() {
+              testOnWindow(true, function(win, downloadDir) {
+                checkDownloadLastDir(win, downloadDir, dir1, true, function() {
+                  testOnWindow(false, function(win, downloadDir) {
+                    checkDownloadLastDir(win, downloadDir, tmpDir, false, function() {
+                      testOnWindow(true, function(win, downloadDir) {
+                        clearHistory();
+                        checkDownloadLastDirNull(win, downloadDir, function() {
+                          testOnWindow(false, function(win, downloadDir) {
+                            checkDownloadLastDirNull(win, downloadDir, finish);
+                          });
+                        });
+                      });
+                    });
+                  });
+                });
+              });
+            });
+          });
+        });
+      });
+    });
   });
 }
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_noSessionRestoreMenuOption.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_noSessionRestoreMenuOption.js
@@ -1,23 +1,34 @@
-"use strict";
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This test checks that the Session Restore menu option is not enabled in private mode
+
+function test() {
+  waitForExplicitFinish();
 
-/**
- * Tests that if we open a tab within a private browsing window, and then
- * close that private browsing window, that subsequent private browsing
- * windows do not allow the command for restoring the last session.
- */
-add_task(function* test_no_session_restore_menu_option() {
-  let win = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
-  ok(true, "The first private window got loaded");
-  win.gBrowser.addTab("about:mozilla");
-  yield BrowserTestUtils.closeWindow(win);
+  function testNoSessionRestoreMenuItem() { 
+    let win = OpenBrowserWindow({private: true});
+    win.addEventListener("load", function onLoad() {
+      win.removeEventListener("load", onLoad, false);
+      ok(true, "The second private window got loaded");
+      let srCommand = win.document.getElementById("Browser:RestoreLastSession");
+      ok(srCommand, "The Session Restore command should exist");
+      is(PrivateBrowsingUtils.isWindowPrivate(win), true,
+         "PrivateBrowsingUtils should report the correct per-window private browsing status");
+      is(srCommand.hasAttribute("disabled"), true,
+         "The Session Restore command should be disabled in private browsing mode");
+      win.close();
+      finish();
+    }, false);
+  }
 
-  win = yield BrowserTestUtils.openNewBrowserWindow({ private: true });
-  let srCommand = win.document.getElementById("Browser:RestoreLastSession");
-  ok(srCommand, "The Session Restore command should exist");
-  is(PrivateBrowsingUtils.isWindowPrivate(win), true,
-     "PrivateBrowsingUtils should report the correct per-window private browsing status");
-  is(srCommand.hasAttribute("disabled"), true,
-     "The Session Restore command should be disabled in private browsing mode");
-
-  yield BrowserTestUtils.closeWindow(win);
-});
+  let win = OpenBrowserWindow({private: true});
+  win.addEventListener("load", function onload() {
+    win.removeEventListener("load", onload, false);
+    ok(true, "The first private window got loaded");
+    win.gBrowser.addTab("about:mozilla");
+    win.close();
+    testNoSessionRestoreMenuItem();
+  }, false);
+}
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_nonbrowser.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_nonbrowser.js
@@ -1,19 +1,34 @@
-"use strict";
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function test() {
+  waitForExplicitFinish();
+
+  let windowsToClose = [];
+  registerCleanupFunction(function() {
+    windowsToClose.forEach(function(win) {
+      win.close();
+    });
+  });
 
-/**
- * Tests that we fire the last-pb-context-exited observer notification
- * when the last private browsing window closes, even if a chrome window
- * was opened from that private browsing window.
- */
-add_task(function* () {
-  let win = yield BrowserTestUtils.openNewBrowserWindow({private: true});
-  let chromeWin = win.open("chrome://browser/content/places/places.xul", "_blank",
-    "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
-  yield BrowserTestUtils.waitForEvent(chromeWin, "load");
-  let obsPromise = TestUtils.topicObserved("last-pb-context-exited");
-  yield BrowserTestUtils.closeWindow(win);
-  yield obsPromise;
-  Assert.ok(true, "Got the last-pb-context-exited notification");
-  chromeWin.close();
-});
+  let win = OpenBrowserWindow({private: true});
+  win.addEventListener("load", function onLoad() {
+    win.removeEventListener("load", onLoad, false);
+    let chromeWin = win.open("chrome://browser/content/places/places.xul",
+      "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
+    chromeWin.addEventListener("load", function chromeWinLoad() {
+      chromeWin.removeEventListener("load", chromeWinLoad, false);
+      win.close();
+    }, false);
+    windowsToClose.push(chromeWin);
+  }, false);
 
+  let observer = function() {
+    is(true, true, "observer fired");
+    Services.obs.removeObserver(observer, "last-pb-context-exited");
+    executeSoon(finish);
+  };
+  Services.obs.addObserver(observer, "last-pb-context-exited", false);
+  windowsToClose.push(win);
+}
\ No newline at end of file
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -3209,28 +3209,16 @@ var SessionStoreInternal = {
 
     let restoreImmediately = options.restoreImmediately;
     let loadArguments = options.loadArguments;
     let browser = tab.linkedBrowser;
     let window = tab.ownerGlobal;
     let tabbrowser = window.gBrowser;
     let forceOnDemand = options.forceOnDemand;
 
-    // If the browser we're attempting to restore happens to be
-    // remote, we need to flip it back to non-remote if it's going
-    // to go into the pending background tab state. This is to make
-    // sure that the background tab can't crash if it hasn't yet
-    // been restored. Normally, when a window is restored, the tabs
-    // that SessionStore inserts are non-remote - but the initial
-    // browser is, by default, remote, so this check and flip is
-    // mostly for that case.
-    if (browser.isRemoteBrowser && (!restoreImmediately || forceOnDemand)) {
-      tabbrowser.updateBrowserRemoteness(browser, false);
-    }
-
     // Increase the busy state counter before modifying the tab.
     this._setWindowStateBusy(window);
 
     // It's important to set the window state to dirty so that
     // we collect their data for the first time when saving state.
     DirtyWindows.add(window);
 
     // In case we didn't collect/receive data for any tabs yet we'll have to
--- a/browser/components/sessionstore/test/browser_394759_behavior.js
+++ b/browser/components/sessionstore/test/browser_394759_behavior.js
@@ -21,19 +21,26 @@
  */
 function testWindows(windowsToOpen, expectedResults) {
   return Task.spawn(function*() {
     for (let winData of windowsToOpen) {
       let features = "chrome,dialog=no," +
                      (winData.isPopup ? "all=no" : "all");
       let url = "http://example.com/?window=" + windowsToOpen.length;
 
-      let openWindowPromise = BrowserTestUtils.waitForNewWindow(true, url);
+      let openWindowPromise = BrowserTestUtils.waitForNewWindow();
       openDialog(getBrowserURL(), "", features, url);
       let win = yield openWindowPromise;
+      yield BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser);
+
+      if (win.gMultiProcessBrowser) {
+        let tab = win.gBrowser.selectedTab;
+        yield promiseTabRestored(tab);
+      }
+
       yield BrowserTestUtils.closeWindow(win);
     }
 
     let closedWindowData = JSON.parse(ss.getClosedWindowData());
     let numPopups = closedWindowData.filter(function(el, i, arr) {
       return el.isPopup;
     }).length;
     let numNormal = ss.getClosedWindowCount() - numPopups;
--- a/browser/components/sessionstore/test/browser_423132.js
+++ b/browser/components/sessionstore/test/browser_423132.js
@@ -68,14 +68,19 @@ function test() {
           cs.removeAll();
           BrowserTestUtils.closeWindow(newWin).then(finish);
         };
 
         function flushAndReady() {
           TabStateFlusher.flush(newWin.gBrowser.selectedBrowser).then(ready);
         }
 
-        flushAndReady();
+        if (newWin.gMultiProcessBrowser) {
+          let tab = newWin.gBrowser.selectedTab;
+          promiseTabRestored(tab).then(flushAndReady);
+        } else {
+          flushAndReady();
+        }
       }, true, testURL);
     });
   }, false);
 }
 
--- a/browser/components/sessionstore/test/browser_async_window_flushing.js
+++ b/browser/components/sessionstore/test/browser_async_window_flushing.js
@@ -31,16 +31,25 @@ add_task(function* test_add_interesting_
 
   // Send a message that will cause the content to change its location
   // to someplace more interesting. We've disabled auto updates from
   // the browser, so the parent won't know about this
   yield ContentTask.spawn(browser, PAGE, function*(PAGE) {
     content.location = PAGE;
   });
 
+  // for e10s, this will cause a remoteness switch, since the
+  // initial browser in a newly opened window will not be remote.
+  // We need to wait for that remoteness change before we attach
+  // our OnHistoryReplaceEntry listener.
+  if (gMultiProcessBrowser) {
+    yield BrowserTestUtils.waitForEvent(newWin.gBrowser.selectedTab,
+                                        "TabRemotenessChange");
+  }
+
   yield promiseContentMessage(browser, "ss-test:OnHistoryReplaceEntry");
 
   // Clear out the userTypedValue so that the new window looks like
   // it's really not worth restoring.
   browser.userTypedValue = null;
 
   // Once the domWindowClosed Promise resolves, the window should
   // have closed, and SessionStore's onClose handler should have just
--- a/browser/components/sessionstore/test/browser_windowStateContainer.js
+++ b/browser/components/sessionstore/test/browser_windowStateContainer.js
@@ -1,14 +1,15 @@
 "use strict";
 
 requestLongerTimeout(2);
 
 add_task(function* () {
-  let win = yield BrowserTestUtils.openNewBrowserWindow();
+  let win = window.openDialog(location, "_blank", "chrome,all,dialog=no");
+  yield promiseWindowLoaded(win);
 
   // Create 4 tabs with different userContextId.
   for (let userContextId = 1; userContextId < 5; userContextId++) {
     let tab = win.gBrowser.addTab("http://example.com/", {userContextId});
     yield promiseBrowserLoaded(tab.linkedBrowser);
     yield TabStateFlusher.flush(tab.linkedBrowser);
   }
 
@@ -20,17 +21,18 @@ add_task(function* () {
 
   let winState = JSON.parse(ss.getWindowState(win));
 
   for (let i = 0; i < 4; i++) {
     Assert.equal(winState.windows[0].tabs[i].userContextId, i + 1,
                  "1st Window: tabs[" + i + "].userContextId should exist.");
   }
 
-  let win2 = yield BrowserTestUtils.openNewBrowserWindow();
+  let win2 = window.openDialog(location, "_blank", "chrome,all,dialog=no");
+  yield promiseWindowLoaded(win2);
 
   // Create tabs with different userContextId, but this time we create them with
   // fewer tabs and with different order with win.
   for (let userContextId = 3; userContextId > 0; userContextId--) {
     let tab = win2.gBrowser.addTab("http://example.com/", {userContextId});
     yield promiseBrowserLoaded(tab.linkedBrowser);
     yield TabStateFlusher.flush(tab.linkedBrowser);
   }
@@ -62,34 +64,35 @@ add_task(function* () {
                  "The document has the correct userContextId");
   });
 
   yield BrowserTestUtils.closeWindow(win);
   yield BrowserTestUtils.closeWindow(win2);
 });
 
 add_task(function* () {
-  let win = yield BrowserTestUtils.openNewBrowserWindow();
-  yield TabStateFlusher.flush(win.gBrowser.selectedBrowser);
+  let win = window.openDialog(location, "_blank", "chrome,all,dialog=no");
+  yield promiseWindowLoaded(win);
 
   let tab = win.gBrowser.addTab("http://example.com/", { userContextId: 1 });
   yield promiseBrowserLoaded(tab.linkedBrowser);
   yield TabStateFlusher.flush(tab.linkedBrowser);
 
   // win should have 1 default tab, and 1 container tab.
   Assert.equal(win.gBrowser.tabs.length, 2, "win should have 2 tabs");
 
   let winState = JSON.parse(ss.getWindowState(win));
 
   for (let i = 0; i < 2; i++) {
     Assert.equal(winState.windows[0].tabs[i].userContextId, i,
                  "1st Window: tabs[" + i + "].userContextId should be " + i);
   }
 
-  let win2 = yield BrowserTestUtils.openNewBrowserWindow();
+  let win2 = window.openDialog(location, "_blank", "chrome,all,dialog=no");
+  yield promiseWindowLoaded(win2);
 
   let tab2 = win2.gBrowser.addTab("http://example.com/", { userContextId : 1 });
   yield promiseBrowserLoaded(tab2.linkedBrowser);
   yield TabStateFlusher.flush(tab2.linkedBrowser);
 
   // Move the first normal tab to end, so the first tab of win2 will be a
   // container tab.
   win2.gBrowser.moveTabTo(win2.gBrowser.tabs[0], win2.gBrowser.tabs.length - 1);
--- a/docshell/base/nsIDocShellTreeOwner.idl
+++ b/docshell/base/nsIDocShellTreeOwner.idl
@@ -76,36 +76,16 @@ interface nsIDocShellTreeOwner : nsISupp
 
 	/*
 	Tells the tree owner to size its window or parent window in such a way
 	that the shell passed along will be the size specified.
 	*/
 	void sizeShellTo(in nsIDocShellTreeItem shell, in long cx, in long cy);
 
 	/*
-	Gets the size of the primary content area in CSS pixels. This should work
-	for both in-process and out-of-process content areas.
-	*/
-	void getPrimaryContentSize(out long width, out long height);
-	/*
-	Sets the size of the primary content area in CSS pixels. This should work
-	for both in-process and out-of-process content areas.
-	*/
-	void setPrimaryContentSize(in long width, in long height);
-
-	/*
-	Gets the size of the root docshell in CSS pixels.
-	*/
-	void getRootShellSize(out long width, out long height);
-	/*
-	Sets the size of the root docshell in CSS pixels.
-	*/
-	void setRootShellSize(in long width, in long height);
-
-	/*
 	Sets the persistence of different attributes of the window.
 	*/
 	void setPersistence(in boolean aPersistPosition,
                             in boolean aPersistSize,
                             in boolean aPersistSizeMode);
 
 	/*
 	Gets the current persistence states of the window.
@@ -113,15 +93,9 @@ interface nsIDocShellTreeOwner : nsISupp
 	void getPersistence(out boolean aPersistPosition,
                             out boolean aPersistSize,
                             out boolean aPersistSizeMode);
 
 	/*
 	Gets the number of targettable docshells.
 	*/
 	readonly attribute unsigned long targetableShellCount;
-
-	/*
-	Returns true if there is a primary content shell or a primary
-	tab parent.
-	*/
-	readonly attribute bool hasPrimaryContent;
 };
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -11828,17 +11828,17 @@ nsGlobalWindow::OpenInternal(const nsASt
     // dialog is open.
     nsAutoPopupStatePusher popupStatePusher(openAbused, true);
 
     if (!aCalledNoScript) {
       // We asserted at the top of this function that aNavigate is true for
       // !aCalledNoScript.
       rv = pwwatch->OpenWindow2(AsOuter(), url.get(), name_ptr,
                                 options_ptr, /* aCalledFromScript = */ true,
-                                aDialog, aNavigate, argv,
+                                aDialog, aNavigate, nullptr, argv,
                                 1.0f, 0, getter_AddRefs(domReturn));
     } else {
       // Force a system caller here so that the window watcher won't screw us
       // up.  We do NOT want this case looking at the JS context on the stack
       // when searching.  Compare comments on
       // nsIDOMWindow::OpenWindow and nsIWindowWatcher::OpenWindow.
 
       // Note: Because nsWindowWatcher is so broken, it's actually important
@@ -11848,17 +11848,17 @@ nsGlobalWindow::OpenInternal(const nsASt
       Maybe<AutoNoJSAPI> nojsapi;
       if (!aContentModal) {
         nojsapi.emplace();
       }
 
 
       rv = pwwatch->OpenWindow2(AsOuter(), url.get(), name_ptr,
                                 options_ptr, /* aCalledFromScript = */ false,
-                                aDialog, aNavigate, aExtraArgument,
+                                aDialog, aNavigate, nullptr, aExtraArgument,
                                 1.0f, 0, getter_AddRefs(domReturn));
 
     }
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // success!
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -857,17 +857,17 @@ ContentChild::ProvideWindowCommon(TabChi
         cv->GetFullZoom(&fullZoom);
       }
     }
 
     nsresult rv;
     if (!SendCreateWindow(aTabOpener, newChild, renderFrame,
                           aChromeFlags, aCalledFromJS, aPositionSpecified,
                           aSizeSpecified,
-                          features,
+                          name, features,
                           baseURIString,
                           openerDocShell
                             ? openerDocShell->GetOriginAttributes()
                             : DocShellOriginAttributes(),
                           fullZoom,
                           &rv,
                           aWindowIsNew,
                           &frameScripts,
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5281,30 +5281,30 @@ ContentParent::DeallocPWebBrowserPersist
 bool
 ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
                                 PBrowserParent* aNewTab,
                                 PRenderFrameParent* aRenderFrame,
                                 const uint32_t& aChromeFlags,
                                 const bool& aCalledFromJS,
                                 const bool& aPositionSpecified,
                                 const bool& aSizeSpecified,
+                                const nsString& aName,
                                 const nsCString& aFeatures,
                                 const nsCString& aBaseURI,
                                 const DocShellOriginAttributes& aOpenerOriginAttributes,
                                 const float& aFullZoom,
                                 nsresult* aResult,
                                 bool* aWindowIsNew,
                                 InfallibleTArray<FrameScriptInfo>* aFrameScripts,
                                 nsCString* aURLToLoad,
                                 TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                 uint64_t* aLayersId)
 {
   // We always expect to open a new window here. If we don't, it's an error.
   *aWindowIsNew = true;
-  *aResult = NS_OK;
 
   // The content process should never be in charge of computing whether or
   // not a window should be private or remote - the parent will do that.
   const uint32_t badFlags =
         nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
       | nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW
       | nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME
       | nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
@@ -5316,16 +5316,23 @@ ContentParent::RecvCreateWindow(PBrowser
   if (aThisTab) {
     thisTabParent = TabParent::GetFrom(aThisTab);
   }
 
   if (NS_WARN_IF(thisTabParent && thisTabParent->IsMozBrowserOrApp())) {
     return false;
   }
 
+  nsCOMPtr<nsPIWindowWatcher> pwwatch =
+    do_GetService(NS_WINDOWWATCHER_CONTRACTID, aResult);
+
+  if (NS_WARN_IF(NS_FAILED(*aResult))) {
+    return true;
+  }
+
   TabParent* newTab = TabParent::GetFrom(aNewTab);
   MOZ_ASSERT(newTab);
 
   // Content has requested that we open this new content window, so
   // we must have an opener.
   newTab->SetHasContentOpener(true);
 
   nsCOMPtr<nsIContent> frame;
@@ -5409,32 +5416,53 @@ ContentParent::RecvCreateWindow(PBrowser
     }
 
     return true;
   }
 
   nsCOMPtr<mozIDOMWindowProxy> window;
   TabParent::AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
 
-  nsCOMPtr<nsPIWindowWatcher> pwwatch =
-    do_GetService(NS_WINDOWWATCHER_CONTRACTID, aResult);
-
-  if (NS_WARN_IF(NS_FAILED(*aResult))) {
+  const char* features = aFeatures.IsVoid() ? nullptr : aFeatures.get();
+
+  *aResult = pwwatch->OpenWindow2(parent, nullptr,
+                                  aName.IsVoid() ?
+                                    nullptr :
+                                    NS_ConvertUTF16toUTF8(aName).get(),
+                                  features, aCalledFromJS,
+                                  false, false, thisTabParent, nullptr,
+                                  aFullZoom, 1, getter_AddRefs(window));
+
+  if (NS_WARN_IF(!window)) {
+    return true;
+  }
+
+  *aResult = NS_ERROR_FAILURE;
+  auto* pwindow = nsPIDOMWindowOuter::From(window);
+  nsCOMPtr<nsIDocShell> windowDocShell = pwindow->GetDocShell();
+  if (NS_WARN_IF(!windowDocShell)) {
+    return true;
+  }
+
+  nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
+  windowDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
+
+  nsCOMPtr<nsIXULWindow> xulWin = do_GetInterface(treeOwner);
+  if (NS_WARN_IF(!xulWin)) {
+    return true;
+  }
+
+  nsCOMPtr<nsIXULBrowserWindow> xulBrowserWin;
+  xulWin->GetXULBrowserWindow(getter_AddRefs(xulBrowserWin));
+  if (NS_WARN_IF(!xulBrowserWin)) {
     return true;
   }
 
   nsCOMPtr<nsITabParent> newRemoteTab;
-  if (!thisTabParent) {
-    // Because we weren't passed an opener tab, the content process has asked us
-    // to open a new window that is unrelated to a pre-existing tab.
-    *aResult = pwwatch->OpenWindowWithoutParent(getter_AddRefs(newRemoteTab));
-  } else {
-    *aResult = pwwatch->OpenWindowWithTabParent(thisTabParent, aFeatures, aCalledFromJS,
-                                                aFullZoom, getter_AddRefs(newRemoteTab));
-  }
+  *aResult = xulBrowserWin->ForceInitialBrowserRemote(getter_AddRefs(newRemoteTab));
 
   if (NS_WARN_IF(NS_FAILED(*aResult))) {
     return true;
   }
 
   MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab);
 
   newTab->SwapFrameScriptsFrom(*aFrameScripts);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -555,16 +555,17 @@ public:
 
   virtual bool RecvCreateWindow(PBrowserParent* aThisTabParent,
                                 PBrowserParent* aOpener,
                                 layout::PRenderFrameParent* aRenderFrame,
                                 const uint32_t& aChromeFlags,
                                 const bool& aCalledFromJS,
                                 const bool& aPositionSpecified,
                                 const bool& aSizeSpecified,
+                                const nsString& aName,
                                 const nsCString& aFeatures,
                                 const nsCString& aBaseURI,
                                 const DocShellOriginAttributes& aOpenerOriginAttributes,
                                 const float& aFullZoom,
                                 nsresult* aResult,
                                 bool* aWindowIsNew,
                                 InfallibleTArray<FrameScriptInfo>* aFrameScripts,
                                 nsCString* aURLToLoad,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -1137,16 +1137,17 @@ parent:
 
     sync CreateWindow(nullable PBrowser aThisTab,
                       PBrowser aNewTab,
                       PRenderFrame aRenderFrame,
                       uint32_t aChromeFlags,
                       bool aCalledFromJS,
                       bool aPositionSpecified,
                       bool aSizeSpecified,
+                      nsString aName,
                       nsCString aFeatures,
                       nsCString aBaseURI,
                       DocShellOriginAttributes aOpenerOriginAttributes,
                       float aFullZoom)
       returns (nsresult rv,
                bool windowOpened,
                FrameScriptInfo[] frameScripts,
                nsCString urlToLoad,
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -601,17 +601,17 @@ private:
       nsCString spec;
       uri->GetSpec(spec);
 
       nsCOMPtr<mozIDOMWindowProxy> newWindow;
       pwwatch->OpenWindow2(nullptr,
                            spec.get(),
                            nullptr,
                            nullptr,
-                           false, false, true, nullptr, 1.0f, 0,
+                           false, false, true, nullptr, nullptr, 1.0f, 0,
                            getter_AddRefs(newWindow));
       nsCOMPtr<nsPIDOMWindowOuter> pwindow = nsPIDOMWindowOuter::From(newWindow);
       pwindow.forget(aWindow);
       return NS_OK;
     }
 
     // Find the most recent browser window and open a new tab in it.
     nsCOMPtr<nsPIDOMWindowOuter> browserWindow =
--- a/embedding/browser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/nsDocShellTreeOwner.cpp
@@ -439,44 +439,16 @@ nsDocShellTreeOwner::GetPrimaryTabParent
   }
 
   nsCOMPtr<nsITabParent> tab = mPrimaryTabParent;
   tab.forget(aTab);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocShellTreeOwner::GetPrimaryContentSize(int32_t* aWidth,
-                                           int32_t* aHeight)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsDocShellTreeOwner::SetPrimaryContentSize(int32_t aWidth,
-                                           int32_t aHeight)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsDocShellTreeOwner::GetRootShellSize(int32_t* aWidth,
-                                      int32_t* aHeight)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsDocShellTreeOwner::SetRootShellSize(int32_t aWidth,
-                                      int32_t aHeight)
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
 nsDocShellTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
                                  int32_t aCX, int32_t aCY)
 {
   nsCOMPtr<nsIWebBrowserChrome> webBrowserChrome = GetWebBrowserChrome();
 
   NS_ENSURE_STATE(mTreeOwner || webBrowserChrome);
 
   if (mTreeOwner) {
@@ -560,23 +532,16 @@ nsDocShellTreeOwner::GetTargetableShellC
     mTreeOwner->GetTargetableShellCount(aResult);
   } else {
     *aResult = 0;
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDocShellTreeOwner::GetHasPrimaryContent(bool* aResult)
-{
-  *aResult = mPrimaryTabParent || mPrimaryContentShell;
-  return NS_OK;
-}
-
 //*****************************************************************************
 // nsDocShellTreeOwner::nsIBaseWindow
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsDocShellTreeOwner::InitWindow(nativeWindow aParentNativeWindow,
                                 nsIWidget* aParentWidget, int32_t aX,
                                 int32_t aY, int32_t aCX, int32_t aCY)
--- a/embedding/components/windowwatcher/moz.build
+++ b/embedding/components/windowwatcher/moz.build
@@ -40,10 +40,8 @@ FINAL_LIBRARY = 'xul'
 # For nsJSUtils
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
 ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']
-
-include('/ipc/chromium/chromium-config.mozbuild')
--- a/embedding/components/windowwatcher/nsPIWindowWatcher.idl
+++ b/embedding/components/windowwatcher/nsPIWindowWatcher.idl
@@ -49,16 +49,19 @@ interface nsPIWindowWatcher : nsISupport
       @param aName window name from JS window.open. can be null.  If a window
              with this name already exists, the openWindow call may just load
              aUrl in it (if aUrl is not null) and return it.
       @param aFeatures window features from JS window.open. can be null.
       @param aCalledFromScript true if we were called from script.
       @param aDialog use dialog defaults (see nsIDOMWindow::openDialog)
       @param aNavigate true if we should navigate the new window to the
              specified URL.
+      @param aOpeningTab the nsITabParent that is opening the new window. The
+                         nsITabParent is a remote tab belonging to aParent. Can
+                         be nullptr if this window is not being opened from a tab.
       @param aArgs Window argument
       @param aOpenerFullZoom the full zoom multiplier for the opener window.
                              this can be null in the single process case where
                              the opener full zoom is obtained from aParent.
       @return the new window
 
       @note This method may examine the JS context stack for purposes of
             determining the security context to use for the search for a given
@@ -69,52 +72,21 @@ interface nsPIWindowWatcher : nsISupport
             aParent).  This is not guaranteed, however.
   */
   [optional_argc]
   mozIDOMWindowProxy openWindow2(in mozIDOMWindowProxy aParent, in string aUrl,
                                  in string aName, in string aFeatures,
                                  in boolean aCalledFromScript,
                                  in boolean aDialog,
                                  in boolean aNavigate,
+                                 in nsITabParent aOpeningTab,
                                  in nsISupports aArgs,
                                  [optional] in float aOpenerFullZoom);
 
   /**
-   * Opens a new window using the most recent non-private browser
-   * window as its parent.
-   *
-   * @return the nsITabParent of the initial browser for the newly opened
-   *         window.
-   */
-  nsITabParent openWindowWithoutParent();
-
-  /**
-   * Opens a new window so that the window that aOpeningTab belongs to
-   * is set as the parent window. The newly opened window will also
-   * inherit load context information from aOpeningTab.
-   *
-   * @param aOpeningTab
-   *        The nsITabParent that is requesting the new window be opened.
-   * @param aFeatures
-   *        Window features if called with window.open or similar.
-   * @param aCalledFromJS
-   *        True if called via window.open or similar.
-   * @param aOpenerFullZoom
-   *        The current zoom multiplier for the opener tab. This is then
-   *        applied to the newly opened window.
-   *
-   * @return the nsITabParent of the initial browser for the newly opened
-   *         window.
-   */
-  nsITabParent openWindowWithTabParent(in nsITabParent aOpeningTab,
-                                       in ACString aFeatures,
-                                       in boolean aCalledFromJS,
-                                       in float aOpenerFullZoom);
-
-  /**
    * Find a named docshell tree item amongst all windows registered
    * with the window watcher.  This may be a subframe in some window,
    * for example.
    *
    * @param aName the name of the window.  Must not be null.
    * @param aRequestor the tree item immediately making the request.
    *        We should make sure to not recurse down into its findItemWithName
    *        method.
--- a/embedding/components/windowwatcher/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/nsWindowWatcher.cpp
@@ -59,19 +59,16 @@
 #include "nsPresContext.h"
 #include "nsContentUtils.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsSandboxFlags.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/DOMStorage.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/TabParent.h"
-#include "nsIXULWindow.h"
-#include "nsIXULBrowserWindow.h"
 
 #ifdef USEWEAKREFS
 #include "nsIWeakReference.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
@@ -366,17 +363,17 @@ nsWindowWatcher::OpenWindow(mozIDOMWindo
   uint32_t argc = 0;
   if (argv) {
     argv->GetLength(&argc);
   }
   bool dialog = (argc != 0);
 
   return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
                             /* calledFromJS = */ false, dialog,
-                            /* navigate = */ true, argv,
+                            /* navigate = */ true, nullptr, argv,
                             /* openerFullZoom = */ nullptr, aResult);
 }
 
 struct SizeSpec
 {
   SizeSpec()
     : mLeftSpecified(false)
     , mTopSpecified(false)
@@ -423,16 +420,17 @@ struct SizeSpec
 NS_IMETHODIMP
 nsWindowWatcher::OpenWindow2(mozIDOMWindowProxy* aParent,
                              const char* aUrl,
                              const char* aName,
                              const char* aFeatures,
                              bool aCalledFromScript,
                              bool aDialog,
                              bool aNavigate,
+                             nsITabParent* aOpeningTab,
                              nsISupports* aArguments,
                              float aOpenerFullZoom,
                              uint8_t aOptionalArgc,
                              mozIDOMWindowProxy** aResult)
 {
   nsCOMPtr<nsIArray> argv = ConvertArgsToArray(aArguments);
 
   uint32_t argc = 0;
@@ -445,17 +443,17 @@ nsWindowWatcher::OpenWindow2(mozIDOMWind
   // called from script.  Fixing this is bug 779939.
   bool dialog = aDialog;
   if (!aCalledFromScript) {
     dialog = argc > 0;
   }
 
   return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
                             aCalledFromScript, dialog,
-                            aNavigate, argv,
+                            aNavigate, aOpeningTab, argv,
                             aOptionalArgc >= 1 ? &aOpenerFullZoom : nullptr,
                             aResult);
 }
 
 // This static function checks if the aDocShell uses an UserContextId equal to
 // the userContextId of subjectPrincipal, if not null.
 static bool
 CheckUserContextCompatibility(nsIDocShell* aDocShell)
@@ -483,280 +481,104 @@ CheckUserContextCompatibility(nsIDocShel
 
   uint32_t principalUserContextId;
   nsresult rv = subjectPrincipal->GetUserContextId(&principalUserContextId);
   NS_ENSURE_SUCCESS(rv, false);
 
   return principalUserContextId == userContextId;
 }
 
-NS_IMETHODIMP
-nsWindowWatcher::OpenWindowWithoutParent(nsITabParent** aResult)
-{
-  return OpenWindowWithTabParent(nullptr, EmptyCString(), true, 1.0f, aResult);
-}
-
-nsresult
-nsWindowWatcher::CreateChromeWindow(const nsACString& aFeatures,
-                                    nsIWebBrowserChrome* aParentChrome,
-                                    uint32_t aChromeFlags,
-                                    uint32_t aContextFlags,
-                                    nsITabParent* aOpeningTabParent,
-                                    nsIWebBrowserChrome** aResult)
-{
-  nsCOMPtr<nsIWindowCreator2> windowCreator2(do_QueryInterface(mWindowCreator));
-  if (NS_WARN_IF(!windowCreator2)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  // B2G multi-screen support. mozDisplayId is returned from the
-  // "display-changed" event, it is also platform-dependent.
-#ifdef MOZ_WIDGET_GONK
-  int retval = WinHasOption(aFeatures, "mozDisplayId", 0, nullptr);
-  windowCreator2->SetScreenId(retval);
-#endif
-
-  bool cancel = false;
-  nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
-  nsresult rv =
-    windowCreator2->CreateChromeWindow2(aParentChrome, aChromeFlags, aContextFlags,
-                                        aOpeningTabParent, &cancel,
-                                        getter_AddRefs(newWindowChrome));
-
-  if (NS_SUCCEEDED(rv) && cancel) {
-    newWindowChrome = nullptr;
-    return NS_ERROR_ABORT;
-  }
-
-  newWindowChrome.forget(aResult);
-  return NS_OK;
-}
-
-/**
- * Disable persistence of size/position in popups (determined by
- * determining whether the features parameter specifies width or height
- * in any way). We consider any overriding of the window's size or position
- * in the open call as disabling persistence of those attributes.
- * Popup windows (which should not persist size or position) generally set
- * the size.
- *
- * @param aFeatures
- *        The features string that was used to open the window.
- * @param aTreeOwner
- *        The nsIDocShellTreeOwner of the newly opened window. If null,
- *        this function is a no-op.
- */
-void
-nsWindowWatcher::MaybeDisablePersistence(const nsACString& aFeatures,
-                                         nsIDocShellTreeOwner* aTreeOwner)
-{
-  if (!aTreeOwner) {
-    return;
-  }
-
- // At the moment, the strings "height=" or "width=" never happen
- // outside a size specification, so we can do this the Q&D way.
-  if (PL_strcasestr(aFeatures.BeginReading(), "width=") ||
-      PL_strcasestr(aFeatures.BeginReading(), "height=")) {
-    aTreeOwner->SetPersistence(false, false, false);
-  }
-}
-
-NS_IMETHODIMP
-nsWindowWatcher::OpenWindowWithTabParent(nsITabParent* aOpeningTabParent,
-                                         const nsACString& aFeatures,
-                                         bool aCalledFromJS,
-                                         float aOpenerFullZoom,
-                                         nsITabParent** aResult)
-{
-  MOZ_ASSERT(XRE_IsParentProcess());
-  MOZ_ASSERT(mWindowCreator);
-
-  if (!nsContentUtils::IsSafeToRunScript()) {
-    nsContentUtils::WarnScriptWasIgnored(nullptr);
-    return NS_ERROR_FAILURE;
-  }
-
-  if (NS_WARN_IF(!mWindowCreator)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  bool isPrivateBrowsingWindow =
-    Preferences::GetBool("browser.privatebrowsing.autostart");
-
-  nsCOMPtr<nsPIDOMWindowOuter> parentWindowOuter;
-  if (aOpeningTabParent) {
-    // We need to examine the window that aOpeningTabParent belongs to in
-    // order to inform us of what kind of window we're going to open.
-    TabParent* openingTab = TabParent::GetFrom(aOpeningTabParent);
-    parentWindowOuter = openingTab->GetParentWindowOuter();
-
-    // Propagate the privacy status of the parent window, if
-    // available, to the child.
-    if (!isPrivateBrowsingWindow) {
-      nsCOMPtr<nsILoadContext> parentContext = openingTab->GetLoadContext();
-      if (parentContext) {
-        isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing();
-      }
-    }
-  }
-
-  if (!parentWindowOuter) {
-    // We couldn't find a browser window for the opener, so either we
-    // never were passed aOpeningTabParent, the window is closed,
-    // or it's in the process of closing. Either way, we'll use
-    // the most recently opened browser window instead.
-    parentWindowOuter = nsContentUtils::GetMostRecentNonPBWindow();
-  }
-
-  if (NS_WARN_IF(!parentWindowOuter)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
-  GetWindowTreeOwner(parentWindowOuter, getter_AddRefs(parentTreeOwner));
-  if (NS_WARN_IF(!parentTreeOwner)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  nsCOMPtr<nsIWindowCreator2> windowCreator2(do_QueryInterface(mWindowCreator));
-  if (NS_WARN_IF(!windowCreator2)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  uint32_t contextFlags = 0;
-  if (parentWindowOuter->IsLoadingOrRunningTimeout()) {
-    contextFlags |=
-            nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT;
-  }
-
-  uint32_t chromeFlags = CalculateChromeFlagsForChild(aFeatures);
-
-  // A content process has asked for a new window, which implies
-  // that the new window will need to be remote.
-  chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
-
-  nsCOMPtr<nsIWebBrowserChrome> parentChrome(do_GetInterface(parentTreeOwner));
-  nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
-
-  CreateChromeWindow(aFeatures, parentChrome, chromeFlags, contextFlags,
-                     aOpeningTabParent, getter_AddRefs(newWindowChrome));
-
-  if (NS_WARN_IF(!newWindowChrome)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  nsCOMPtr<nsIDocShellTreeItem> chromeTreeItem = do_GetInterface(newWindowChrome);
-  if (NS_WARN_IF(!chromeTreeItem)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  nsCOMPtr<nsIDocShellTreeOwner> chromeTreeOwner;
-  chromeTreeItem->GetTreeOwner(getter_AddRefs(chromeTreeOwner));
-  if (NS_WARN_IF(!chromeTreeOwner)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  nsCOMPtr<nsILoadContext> chromeContext = do_QueryInterface(chromeTreeItem);
-  if (NS_WARN_IF(!chromeContext)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  chromeContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
-
-  // Tabs opened from a content process can only open new windows
-  // that will also run with out-of-process tabs.
-  chromeContext->SetRemoteTabs(true);
-
-  MaybeDisablePersistence(aFeatures, chromeTreeOwner);
-
-  SizeSpec sizeSpec;
-  CalcSizeSpec(aFeatures, sizeSpec);
-  SizeOpenedWindow(chromeTreeOwner, parentWindowOuter, false, sizeSpec,
-                   &aOpenerFullZoom);
-
-  nsCOMPtr<nsITabParent> newTabParent;
-  chromeTreeOwner->GetPrimaryTabParent(getter_AddRefs(newTabParent));
-  if (NS_WARN_IF(!newTabParent)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  newTabParent.forget(aResult);
-  return NS_OK;
-}
-
 nsresult
 nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
                                     const char* aUrl,
                                     const char* aName,
                                     const char* aFeatures,
                                     bool aCalledFromJS,
                                     bool aDialog,
                                     bool aNavigate,
+                                    nsITabParent* aOpeningTab,
                                     nsIArray* aArgv,
                                     float* aOpenerFullZoom,
                                     mozIDOMWindowProxy** aResult)
 {
   nsresult rv = NS_OK;
   bool isNewToplevelWindow = false;
   bool windowIsNew = false;
   bool windowNeedsName = false;
   bool windowIsModal = false;
   bool uriToLoadIsChrome = false;
   bool windowIsModalContentDialog = false;
 
+  // Opening tabs are only ever passed to OpenWindowInternal if we're opening
+  // a window from a remote tab.
+  bool openedFromRemoteTab = !!aOpeningTab;
+
   uint32_t chromeFlags;
   nsAutoString name;          // string version of aName
   nsAutoCString features;     // string version of aFeatures
   nsCOMPtr<nsIURI> uriToLoad; // from aUrl, if any
   nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner; // from the parent window, if any
   nsCOMPtr<nsIDocShellTreeItem> newDocShellItem; // from the new window
 
   nsCOMPtr<nsPIDOMWindowOuter> parent =
     aParent ? nsPIDOMWindowOuter::From(aParent) : nullptr;
 
+  // When the opener is a remote tab, the url passed from the child process
+  // isn't actually used. This code needs some serious refactoring.
+  MOZ_ASSERT_IF(openedFromRemoteTab, !aUrl);
+  MOZ_ASSERT_IF(openedFromRemoteTab, XRE_IsParentProcess());
   NS_ENSURE_ARG_POINTER(aResult);
   *aResult = 0;
 
   if (!nsContentUtils::IsSafeToRunScript()) {
     nsContentUtils::WarnScriptWasIgnored(nullptr);
     return NS_ERROR_FAILURE;
   }
 
   GetWindowTreeOwner(parent, getter_AddRefs(parentTreeOwner));
 
   // We expect TabParent to have provided us the absolute URI of the window
   // we're to open, so there's no need to call URIfromURL (or more importantly,
   // to check for a chrome URI, which cannot be opened from a remote tab).
-  if (aUrl) {
+  if (aUrl && !openedFromRemoteTab) {
     rv = URIfromURL(aUrl, aParent, getter_AddRefs(uriToLoad));
     if (NS_FAILED(rv)) {
       return rv;
     }
     uriToLoad->SchemeIs("chrome", &uriToLoadIsChrome);
   }
 
   bool nameSpecified = false;
   if (aName) {
     CopyUTF8toUTF16(aName, name);
     nameSpecified = true;
   } else {
     name.SetIsVoid(true);
   }
 
+  bool featuresSpecified = false;
   if (aFeatures) {
     features.Assign(aFeatures);
+    featuresSpecified = true;
     features.StripWhitespace();
   } else {
     features.SetIsVoid(true);
   }
 
-  // try to find an extant window with the given name
-  nsCOMPtr<nsPIDOMWindowOuter> foundWindow = SafeGetWindowByName(name, aParent);
-  GetWindowTreeItem(foundWindow, getter_AddRefs(newDocShellItem));
+  // We only want to check for existing named windows if:
+  // a) We're the child process
+  // b) We're the parent process, and aOpeningTab wasn't passed
+  //    in.
+  // This is because when using child processes, the parent process shouldn't
+  // know or care about names - unless we're opening named windows from chrome.
+  if (!aOpeningTab) {
+    // try to find an extant window with the given name
+    nsCOMPtr<nsPIDOMWindowOuter> foundWindow = SafeGetWindowByName(name, aParent);
+    GetWindowTreeItem(foundWindow, getter_AddRefs(newDocShellItem));
+  }
 
   // Do sandbox checks here, instead of waiting until nsIDocShell::LoadURI.
   // The state of the window can change before this call and if we are blocked
   // because of sandboxing, we wouldn't want that to happen.
   nsCOMPtr<nsPIDOMWindowOuter> parentWindow =
     aParent ? nsPIDOMWindowOuter::From(aParent) : nullptr;
   nsCOMPtr<nsIDocShell> parentDocShell;
   if (parentWindow) {
@@ -771,62 +593,58 @@ nsWindowWatcher::OpenWindowInternal(mozI
 
   // no extant window? make a new one.
 
   // If no parent, consider it chrome when running in the parent process.
   bool hasChromeParent = XRE_IsContentProcess() ? false : true;
   if (aParent) {
     // Check if the parent document has chrome privileges.
     nsIDocument* doc = parentWindow->GetDoc();
-    hasChromeParent = doc && nsContentUtils::IsChromeDoc(doc);
+    hasChromeParent =
+      doc && nsContentUtils::IsChromeDoc(doc) && !openedFromRemoteTab;
   }
 
-  bool isCallerChrome = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
-
-  // Make sure we calculate the chromeFlags *before* we push the
+  // Make sure we call CalculateChromeFlags() *before* we push the
   // callee context onto the context stack so that
-  // the calculation sees the actual caller when doing its
+  // CalculateChromeFlags() sees the actual caller when doing its
   // security checks.
-  if (isCallerChrome && XRE_IsParentProcess()) {
-    chromeFlags = CalculateChromeFlagsForParent(aParent, features,
-                                                aDialog, uriToLoadIsChrome,
-                                                hasChromeParent, aCalledFromJS);
-  } else {
-    chromeFlags = CalculateChromeFlagsForChild(features);
+  chromeFlags = CalculateChromeFlags(aParent, features.get(), featuresSpecified,
+                                     aDialog, uriToLoadIsChrome,
+                                     hasChromeParent, aCalledFromJS,
+                                     openedFromRemoteTab);
 
-    // Until ShowModalDialog is removed, it's still possible for content to
-    // request dialogs, but only in single-process mode.
-    if (aDialog) {
-      MOZ_ASSERT(XRE_IsParentProcess());
-      chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
-    }
-  }
+  // If we are opening a window from a remote browser, the resulting window
+  // should also be remote.
+  MOZ_ASSERT_IF(openedFromRemoteTab,
+                chromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
 
   // If we're not called through our JS version of the API, and we got
   // our internal modal option, treat the window we're opening as a
   // modal content window (and set the modal chrome flag).
   if (!aCalledFromJS && aArgv &&
-      WinHasOption(features, "-moz-internal-modal", 0, nullptr)) {
+      WinHasOption(features.get(), "-moz-internal-modal", 0, nullptr)) {
     windowIsModalContentDialog = true;
 
     // CHROME_MODAL gets inherited by dependent windows, which affects various
     // platform-specific window state (especially on OSX). So we need some way
     // to determine that this window was actually opened by nsGlobalWindow::
     // ShowModalDialog(), and that somebody is actually going to be watching
     // for return values and all that.
     chromeFlags |= nsIWebBrowserChrome::CHROME_MODAL_CONTENT_WINDOW;
     chromeFlags |= nsIWebBrowserChrome::CHROME_MODAL;
   }
 
   SizeSpec sizeSpec;
-  CalcSizeSpec(features, sizeSpec);
+  CalcSizeSpec(features.get(), sizeSpec);
 
   nsCOMPtr<nsIScriptSecurityManager> sm(
     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
 
+  bool isCallerChrome =
+    nsContentUtils::LegacyIsCallerChromeOrNativeCode() && !openedFromRemoteTab;
 
   // XXXbz Why is an AutoJSAPI good enough here?  Wouldn't AutoEntryScript (so
   // we affect the entry global) make more sense?  Or do we just want to affect
   // GetSubjectPrincipal()?
   dom::AutoJSAPI jsapiChromeGuard;
 
   bool windowTypeIsChrome =
     chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
@@ -1004,33 +822,39 @@ nsWindowWatcher::OpenWindowInternal(mozI
           popupConditions = !isCallerChrome;
         }
 
         if (popupConditions) {
           contextFlags |=
             nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT;
         }
 
-        rv = CreateChromeWindow(features, parentChrome, chromeFlags, contextFlags,
-                                nullptr, getter_AddRefs(newChrome));
+        // B2G multi-screen support. mozDisplayId is returned from the
+        // "display-changed" event, it is also platform-dependent.
+#ifdef MOZ_WIDGET_GONK
+        int retval = WinHasOption(features.get(), "mozDisplayId", 0, nullptr);
+        windowCreator2->SetScreenId(retval);
+#endif
+
 
+        bool cancel = false;
+        rv = windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags,
+                                                 contextFlags, uriToLoad,
+                                                 aOpeningTab, &cancel,
+                                                 getter_AddRefs(newChrome));
+        if (NS_SUCCEEDED(rv) && cancel) {
+          newChrome = 0; // just in case
+          rv = NS_ERROR_ABORT;
+        }
       } else {
         rv = mWindowCreator->CreateChromeWindow(parentChrome, chromeFlags,
                                                 getter_AddRefs(newChrome));
       }
 
       if (newChrome) {
-        nsCOMPtr<nsIXULWindow> xulWin = do_GetInterface(newChrome);
-        if (xulWin) {
-          nsCOMPtr<nsIXULBrowserWindow> xulBrowserWin;
-          xulWin->GetXULBrowserWindow(getter_AddRefs(xulBrowserWin));
-          if (xulBrowserWin) {
-            xulBrowserWin->ForceInitialBrowserNonRemote();
-          }
-        }
         /* It might be a chrome nsXULWindow, in which case it won't have
             an nsIDOMWindow (primary content shell). But in that case, it'll
             be able to hand over an nsIDocShellTreeItem directly. */
         nsCOMPtr<nsPIDOMWindowOuter> newWindow(do_GetInterface(newChrome));
         if (newWindow) {
           GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem));
         }
         if (!newDocShellItem) {
@@ -1063,20 +887,35 @@ nsWindowWatcher::OpenWindowInternal(mozI
     }
   }
 
   rv = ReadyOpenedDocShellItem(newDocShellItem, parentWindow, windowIsNew, aResult);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
+  /* disable persistence of size/position in popups (determined by
+     determining whether the features parameter specifies width or height
+     in any way). We consider any overriding of the window's size or position
+     in the open call as disabling persistence of those attributes.
+     Popup windows (which should not persist size or position) generally set
+     the size. */
   if (isNewToplevelWindow) {
-    nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
-    newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner));
-    MaybeDisablePersistence(features, newTreeOwner);
+    /* at the moment, the strings "height=" or "width=" never happen
+       outside a size specification, so we can do this the Q&D way. */
+
+    if (PL_strcasestr(features.get(), "width=") ||
+        PL_strcasestr(features.get(), "height=")) {
+
+      nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
+      newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner));
+      if (newTreeOwner) {
+        newTreeOwner->SetPersistence(false, false, false);
+      }
+    }
   }
 
   if ((aDialog || windowIsModalContentDialog) && aArgv) {
     // Set the args on the new window.
     nsCOMPtr<nsPIDOMWindowOuter> piwin(do_QueryInterface(*aResult));
     NS_ENSURE_TRUE(piwin, NS_ERROR_UNEXPECTED);
 
     rv = piwin->SetArguments(aArgv);
@@ -1242,20 +1081,18 @@ nsWindowWatcher::OpenWindowInternal(mozI
                                        getter_AddRefs(storage));
       if (storage) {
         newStorageManager->CloneStorage(storage);
       }
     }
   }
 
   if (isNewToplevelWindow) {
-    nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
-    newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner));
-    SizeOpenedWindow(newTreeOwner, aParent, isCallerChrome, sizeSpec,
-                     aOpenerFullZoom);
+    SizeOpenedDocShellItem(newDocShellItem, aParent, isCallerChrome, sizeSpec,
+                           aOpenerFullZoom);
   }
 
   // XXXbz isn't windowIsModal always true when windowIsModalContentDialog?
   if (windowIsModal || windowIsModalContentDialog) {
     nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
     newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner));
     nsCOMPtr<nsIWebBrowserChrome> newChrome(do_GetInterface(newTreeOwner));
 
@@ -1699,51 +1536,118 @@ nsWindowWatcher::URIfromURL(const char* 
       baseURI = doc->GetDocBaseURI();
     }
   }
 
   // build and return the absolute URI
   return NS_NewURI(aURI, aURL, baseURI);
 }
 
-#define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag)                       \
-  prefBranch->GetBoolPref(feature, &forceEnable);                     \
-  if (forceEnable && !aDialog && !aHasChromeParent && !aChromeURL) {  \
-    chromeFlags |= flag;                                              \
-  } else {                                                            \
-    chromeFlags |=                                                    \
-      WinHasOption(aFeatures, feature, 0, &presenceFlag) ? flag : 0;  \
+#define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag)                            \
+  prefBranch->GetBoolPref(feature, &forceEnable);                              \
+  if (forceEnable && !(aDialog && !openedFromContentScript) &&                 \
+      !(!openedFromContentScript && aHasChromeParent) && !aChromeURL) {        \
+    chromeFlags |= flag;                                                       \
+  } else {                                                                     \
+    chromeFlags |=                                                             \
+      WinHasOption(aFeatures, feature, 0, &presenceFlag) ? flag : 0;           \
   }
 
+/**
+ * Calculate the chrome bitmask from a string list of features.
+ * @param aParent the opener window
+ * @param aFeatures a string containing a list of named chrome features
+ * @param aNullFeatures true if aFeatures was a null pointer (which fact
+ *                      is lost by its conversion to a string in the caller)
+ * @param aDialog affects the assumptions made about unnamed features
+ * @return the chrome bitmask
+ */
 // static
 uint32_t
-nsWindowWatcher::CalculateChromeFlagsHelper(uint32_t aInitialFlags,
-                                            const nsACString& aFeatures,
-                                            bool& presenceFlag,
-                                            bool aDialog,
-                                            bool aHasChromeParent,
-                                            bool aChromeURL)
+nsWindowWatcher::CalculateChromeFlags(mozIDOMWindowProxy* aParent,
+                                      const char* aFeatures,
+                                      bool aFeaturesSpecified,
+                                      bool aDialog,
+                                      bool aChromeURL,
+                                      bool aHasChromeParent,
+                                      bool aCalledFromJS,
+                                      bool aOpenedFromRemoteTab)
 {
-  uint32_t chromeFlags = aInitialFlags;
+  const bool inContentProcess = XRE_IsContentProcess();
+  uint32_t chromeFlags = 0;
+
+  if (!aFeaturesSpecified || !aFeatures) {
+    chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
+    if (aDialog) {
+      chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
+                     nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
+    }
+
+    if (inContentProcess) {
+      return chromeFlags;
+    }
+  } else {
+    chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
+  }
+
+  bool openedFromContentScript =
+    aOpenedFromRemoteTab ? aCalledFromJS
+                         : !nsContentUtils::LegacyIsCallerChromeOrNativeCode();
+
+  /* This function has become complicated since browser windows and
+     dialogs diverged. The difference is, browser windows assume all
+     chrome not explicitly mentioned is off, if the features string
+     is not null. Exceptions are some OS border chrome new with Mozilla.
+     Dialogs interpret a (mostly) empty features string to mean
+     "OS's choice," and also support an "all" flag explicitly disallowed
+     in the standards-compliant window.(normal)open. */
+
+  bool presenceFlag = false;
+  if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag)) {
+    chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
+  }
+
+  /* Next, allow explicitly named options to override the initial settings */
+
+  if (!inContentProcess && !openedFromContentScript) {
+    // Determine whether the window is a private browsing window
+    chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag) ?
+      nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW : 0;
+    chromeFlags |= WinHasOption(aFeatures, "non-private", 0, &presenceFlag) ?
+      nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW : 0;
+  }
+
+  if (!inContentProcess) {
+    // Determine whether the window should have remote tabs.
+    bool remote = BrowserTabsRemoteAutostart();
+
+    if (!openedFromContentScript) {
+      if (remote) {
+        remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag);
+      } else {
+        remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag);
+      }
+    }
+
+    if (remote) {
+      chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
+    }
+  }
 
   nsresult rv;
+
   nsCOMPtr<nsIPrefBranch> prefBranch;
   nsCOMPtr<nsIPrefService> prefs =
     do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
-
-  NS_ENSURE_SUCCESS(rv, nsIWebBrowserChrome::CHROME_DEFAULT);
+  NS_ENSURE_SUCCESS(rv, true);
 
   rv = prefs->GetBranch("dom.disable_window_open_feature.",
                         getter_AddRefs(prefBranch));
-
-  NS_ENSURE_SUCCESS(rv, nsIWebBrowserChrome::CHROME_DEFAULT);
+  NS_ENSURE_SUCCESS(rv, true);
 
-  // NS_CALCULATE_CHROME_FLAG_FOR requires aFeatures, forceEnable, aDialog
-  // aHasChromeParent, aChromeURL, presenceFlag and chromeFlags to be in
-  // scope.
   bool forceEnable = false;
 
   NS_CALCULATE_CHROME_FLAG_FOR("titlebar",
                                nsIWebBrowserChrome::CHROME_TITLEBAR);
   NS_CALCULATE_CHROME_FLAG_FOR("close",
                                nsIWebBrowserChrome::CHROME_WINDOW_CLOSE);
   NS_CALCULATE_CHROME_FLAG_FOR("toolbar",
                                nsIWebBrowserChrome::CHROME_TOOLBAR);
@@ -1760,161 +1664,37 @@ nsWindowWatcher::CalculateChromeFlagsHel
   NS_CALCULATE_CHROME_FLAG_FOR("minimizable",
                                nsIWebBrowserChrome::CHROME_WINDOW_MIN);
 
   // default scrollbar to "on," unless explicitly turned off
   if (WinHasOption(aFeatures, "scrollbars", 1, &presenceFlag) || !presenceFlag) {
     chromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS;
   }
 
-  return chromeFlags;
-}
-
-// static
-uint32_t
-nsWindowWatcher::EnsureFlagsSafeForContent(uint32_t aChromeFlags,
-                                           bool aChromeURL)
-{
-  aChromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
-  aChromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
-  aChromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
-  aChromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
-  aChromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_POPUP;
-  /* Untrusted script is allowed to pose modal windows with a chrome
-     scheme. This check could stand to be better. But it effectively
-     prevents untrusted script from opening modal windows in general
-     while still allowing alerts and the like. */
-  if (!aChromeURL) {
-    aChromeFlags &= ~(nsIWebBrowserChrome::CHROME_MODAL |
-                     nsIWebBrowserChrome::CHROME_OPENAS_CHROME);
-  }
-
-  if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) {
-    aChromeFlags &= ~nsIWebBrowserChrome::CHROME_DEPENDENT;
-  }
-
-  return aChromeFlags;
-}
-
-/**
- * Calculate the chrome bitmask from a string list of features requested
- * from a child process. Feature strings that are restricted to the parent
- * process are ignored here.
- * @param aFeatures a string containing a list of named features
- * @return the chrome bitmask
- */
-// static
-uint32_t
-nsWindowWatcher::CalculateChromeFlagsForChild(const nsACString& aFeatures)
-{
-  if (aFeatures.IsVoid()) {
-    return nsIWebBrowserChrome::CHROME_ALL;
-  }
-
-  bool presenceFlag = false;
-  uint32_t chromeFlags = CalculateChromeFlagsHelper(
-    nsIWebBrowserChrome::CHROME_WINDOW_BORDERS, aFeatures, presenceFlag);
-
-  return EnsureFlagsSafeForContent(chromeFlags);
-}
-
-/**
- * Calculate the chrome bitmask from a string list of features for a new
- * privileged window.
- * @param aParent the opener window
- * @param aFeatures a string containing a list of named chrome features
- * @param aDialog affects the assumptions made about unnamed features
- * @param aChromeURL true if the window is being sent to a chrome:// URL
- * @param aHasChromeParent true if the parent window is privileged
- * @param aCalledFromJS true if the window open request came from script.
- * @return the chrome bitmask
- */
-// static
-uint32_t
-nsWindowWatcher::CalculateChromeFlagsForParent(mozIDOMWindowProxy* aParent,
-                                               const nsACString& aFeatures,
-                                               bool aDialog,
-                                               bool aChromeURL,
-                                               bool aHasChromeParent,
-                                               bool aCalledFromJS)
-{
-  MOZ_ASSERT(XRE_IsParentProcess());
-  MOZ_ASSERT(nsContentUtils::LegacyIsCallerChromeOrNativeCode());
-
-  uint32_t chromeFlags = 0;
-
-  // The features string is made void by OpenWindowInternal
-  // if nullptr was originally passed as the features string.
-  if (aFeatures.IsVoid()) {
-    chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
-    if (aDialog) {
-      chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
-                     nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
-    }
-  } else {
-    chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
-  }
-
-  /* This function has become complicated since browser windows and
-     dialogs diverged. The difference is, browser windows assume all
-     chrome not explicitly mentioned is off, if the features string
-     is not null. Exceptions are some OS border chrome new with Mozilla.
-     Dialogs interpret a (mostly) empty features string to mean
-     "OS's choice," and also support an "all" flag explicitly disallowed
-     in the standards-compliant window.(normal)open. */
-
-  bool presenceFlag = false;
-  if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag)) {
-    chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
-  }
-
-  /* Next, allow explicitly named options to override the initial settings */
-  chromeFlags = CalculateChromeFlagsHelper(chromeFlags, aFeatures, presenceFlag,
-                                           aDialog, aHasChromeParent, aChromeURL);
-
-  // Determine whether the window is a private browsing window
-  chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag) ?
-    nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW : 0;
-  chromeFlags |= WinHasOption(aFeatures, "non-private", 0, &presenceFlag) ?
-    nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW : 0;
-
-  // Determine whether the window should have remote tabs.
-  bool remote = BrowserTabsRemoteAutostart();
-
-  if (remote) {
-    remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag);
-  } else {
-    remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag);
-  }
-
-  if (remote) {
-    chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
-  }
-
   chromeFlags |= WinHasOption(aFeatures, "popup", 0, &presenceFlag) ?
     nsIWebBrowserChrome::CHROME_WINDOW_POPUP : 0;
 
   /* OK.
      Normal browser windows, in spite of a stated pattern of turning off
      all chrome not mentioned explicitly, will want the new OS chrome (window
      borders, titlebars, closebox) on, unless explicitly turned off.
      Dialogs, on the other hand, take the absence of any explicit settings
      to mean "OS' choice." */
 
   // default titlebar and closebox to "on," if not mentioned at all
   if (!(chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_POPUP)) {
-    if (!PL_strcasestr(aFeatures.BeginReading(), "titlebar")) {
+    if (!PL_strcasestr(aFeatures, "titlebar")) {
       chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
     }
-    if (!PL_strcasestr(aFeatures.BeginReading(), "close")) {
+    if (!PL_strcasestr(aFeatures, "close")) {
       chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
     }
   }
 
-  if (aDialog && !aFeatures.IsVoid() && !presenceFlag) {
+  if (aDialog && aFeaturesSpecified && !presenceFlag) {
     chromeFlags = nsIWebBrowserChrome::CHROME_DEFAULT;
   }
 
   /* Finally, once all the above normal chrome has been divined, deal
      with the features that are more operating hints than appearance
      instructions. (Note modality implies dependence.) */
 
   if (WinHasOption(aFeatures, "alwaysLowered", 0, nullptr) ||
@@ -1937,85 +1717,109 @@ nsWindowWatcher::CalculateChromeFlagsFor
     nsIWebBrowserChrome::CHROME_DEPENDENT : 0;
   chromeFlags |= WinHasOption(aFeatures, "modal", 0, nullptr) ?
     (nsIWebBrowserChrome::CHROME_MODAL | nsIWebBrowserChrome::CHROME_DEPENDENT) : 0;
 
   /* On mobile we want to ignore the dialog window feature, since the mobile UI
      does not provide any affordance for dialog windows. This does not interfere
      with dialog windows created through openDialog. */
   bool disableDialogFeature = false;
-  nsCOMPtr<nsIPrefBranch> branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
-
+  nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
   branch->GetBoolPref("dom.disable_window_open_dialog_feature",
                       &disableDialogFeature);
 
+  if (openedFromContentScript) {
+    // If the caller context is content, we do not support the
+    // dialog feature. See bug 1095236.
+    disableDialogFeature = true;
+  }
+
   if (!disableDialogFeature) {
     chromeFlags |= WinHasOption(aFeatures, "dialog", 0, nullptr) ?
       nsIWebBrowserChrome::CHROME_OPENAS_DIALOG : 0;
   }
 
   /* and dialogs need to have the last word. assume dialogs are dialogs,
      and opened as chrome, unless explicitly told otherwise. */
   if (aDialog) {
-    if (!PL_strcasestr(aFeatures.BeginReading(), "dialog")) {
+    if (!PL_strcasestr(aFeatures, "dialog")) {
       chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
     }
-    if (!PL_strcasestr(aFeatures.BeginReading(), "chrome")) {
+    if (!PL_strcasestr(aFeatures, "chrome")) {
       chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
     }
   }
 
   /* missing
      chromeFlags->copy_history
    */
 
   // Check security state for use in determing window dimensions
-  if (!aHasChromeParent) {
-    chromeFlags = EnsureFlagsSafeForContent(chromeFlags, aChromeURL);
+  if (openedFromContentScript || !aHasChromeParent) {
+    // If priv check fails (or if we're called from chrome, but the
+    // parent is not a chrome window), set all elements to minimum
+    // reqs., else leave them alone.
+    chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
+    chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
+    chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
+    chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
+    chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_POPUP;
+    /* Untrusted script is allowed to pose modal windows with a chrome
+       scheme. This check could stand to be better. But it effectively
+       prevents untrusted script from opening modal windows in general
+       while still allowing alerts and the like. */
+    if (!aChromeURL)
+      chromeFlags &= ~(nsIWebBrowserChrome::CHROME_MODAL |
+                       nsIWebBrowserChrome::CHROME_OPENAS_CHROME);
+  }
+
+  if (!(chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) {
+    // Remove the dependent flag if we're not opening as chrome
+    chromeFlags &= ~nsIWebBrowserChrome::CHROME_DEPENDENT;
   }
 
   // Disable CHROME_OPENAS_DIALOG if the window is inside <iframe mozbrowser>.
   // It's up to the embedder to interpret what dialog=1 means.
   nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
   if (docshell && docshell->GetIsInMozBrowserOrApp()) {
     chromeFlags &= ~nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
   }
 
   return chromeFlags;
 }
 
 // static
 int32_t
-nsWindowWatcher::WinHasOption(const nsACString& aOptions, const char* aName,
+nsWindowWatcher::WinHasOption(const char* aOptions, const char* aName,
                               int32_t aDefault, bool* aPresenceFlag)
 {
-  if (aOptions.IsEmpty()) {
+  if (!aOptions) {
     return 0;
   }
 
-  const char* options = aOptions.BeginReading();
   char* comma;
   char* equal;
   int32_t found = 0;
 
 #ifdef DEBUG
-  NS_ASSERTION(nsAutoCString(aOptions).FindCharInSet(" \n\r\t") == kNotFound,
+  nsAutoCString options(aOptions);
+  NS_ASSERTION(options.FindCharInSet(" \n\r\t") == kNotFound,
                "There should be no whitespace in this string!");
 #endif
 
   while (true) {
-    comma = PL_strchr(options, ',');
+    comma = PL_strchr(aOptions, ',');
     if (comma) {
       *comma = '\0';
     }
-    equal = PL_strchr(options, '=');
+    equal = PL_strchr(aOptions, '=');
     if (equal) {
       *equal = '\0';
     }
-    if (nsCRT::strcasecmp(options, aName) == 0) {
+    if (nsCRT::strcasecmp(aOptions, aName) == 0) {
       if (aPresenceFlag) {
         *aPresenceFlag = true;
       }
       if (equal)
         if (*(equal + 1) == '*') {
           found = aDefault;
         } else if (nsCRT::strcasecmp(equal + 1, "yes") == 0) {
           found = 1;
@@ -2030,17 +1834,17 @@ nsWindowWatcher::WinHasOption(const nsAC
       *equal = '=';
     }
     if (comma) {
       *comma = ',';
     }
     if (found || !comma) {
       break;
     }
-    options = comma + 1;
+    aOptions = comma + 1;
   }
   return found;
 }
 
 /* try to find an nsIDocShellTreeItem with the given name in any
    known open window. a failure to find the item will not
    necessarily return a failure method value. check aFoundItem.
 */
@@ -2189,17 +1993,17 @@ nsWindowWatcher::ReadyOpenedDocShellItem
     }
     rv = CallQueryInterface(piOpenedWindow, aOpenedWindow);
   }
   return rv;
 }
 
 // static
 void
-nsWindowWatcher::CalcSizeSpec(const nsACString& aFeatures, SizeSpec& aResult)
+nsWindowWatcher::CalcSizeSpec(const char* aFeatures, SizeSpec& aResult)
 {
   // Parse position spec, if any, from aFeatures
   bool present;
   int32_t temp;
 
   present = false;
   if ((temp = WinHasOption(aFeatures, "left", 0, &present)) || present) {
     aResult.mLeft = temp;
@@ -2252,95 +2056,81 @@ nsWindowWatcher::CalcSizeSpec(const nsAC
       aResult.mUseDefaultHeight = true;
     } else {
       aResult.mInnerHeight = temp;
     }
     aResult.mInnerHeightSpecified = true;
   }
 }
 
-/* Size and position a new window according to aSizeSpec. This method
+/* Size and position the new window according to aSizeSpec. This method
    is assumed to be called after the window has already been given
    a default position and size; thus its current position and size are
    accurate defaults. The new window is made visible at method end.
-   @param aTreeOwner
-          The top-level nsIDocShellTreeOwner of the newly opened window.
-   @param aParent (optional)
-          The parent window from which to inherit zoom factors from if
-          aOpenerFullZoom isn't passed.
-   @param aIsCallerChrome
-          True if the code requesting the new window is privileged.
-   @param aSizeSpec
-          The size that the new window should be.
-   @param aOpenerFullZoom
-          An optional pointer to a zoom factor to scale the content
-          to.
 */
 void
-nsWindowWatcher::SizeOpenedWindow(nsIDocShellTreeOwner* aTreeOwner,
-                                  mozIDOMWindowProxy* aParent,
-                                  bool aIsCallerChrome,
-                                  const SizeSpec& aSizeSpec,
-                                  float* aOpenerFullZoom)
+nsWindowWatcher::SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
+                                        mozIDOMWindowProxy* aParent,
+                                        bool aIsCallerChrome,
+                                        const SizeSpec& aSizeSpec,
+                                        float* aOpenerFullZoom)
 {
-  // We should only be sizing top-level windows if we're in the parent
-  // process.
-  MOZ_ASSERT(XRE_IsParentProcess());
-
   // position and size of window
   int32_t left = 0, top = 0, width = 100, height = 100;
   // difference between chrome and content size
   int32_t chromeWidth = 0, chromeHeight = 0;
   // whether the window size spec refers to chrome or content
   bool sizeChromeWidth = true, sizeChromeHeight = true;
 
   // get various interfaces for aDocShellItem, used throughout this method
-  nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(aTreeOwner));
+  nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
+  aDocShellItem->GetTreeOwner(getter_AddRefs(treeOwner));
+  nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(treeOwner));
   if (!treeOwnerAsWin) { // we'll need this to actually size the docshell
     return;
   }
 
   double openerZoom = aOpenerFullZoom ? *aOpenerFullZoom : 1.0;
   if (aParent && !aOpenerFullZoom) {
     nsCOMPtr<nsPIDOMWindowOuter> piWindow = nsPIDOMWindowOuter::From(aParent);
     if (nsIDocument* doc = piWindow->GetDoc()) {
       if (nsIPresShell* shell = doc->GetShell()) {
         if (nsPresContext* presContext = shell->GetPresContext()) {
           openerZoom = presContext->GetFullZoom();
         }
       }
     }
   }
 
-  double scale = 1.0;
+  double scale;
   treeOwnerAsWin->GetUnscaledDevicePixelsPerCSSPixel(&scale);
 
   /* The current position and size will be unchanged if not specified
      (and they fit entirely onscreen). Also, calculate the difference
      between chrome and content sizes on aDocShellItem's window.
      This latter point becomes important if chrome and content
      specifications are mixed in aFeatures, and when bringing the window
      back from too far off the right or bottom edges of the screen. */
 
   treeOwnerAsWin->GetPositionAndSize(&left, &top, &width, &height);
   left = NSToIntRound(left / scale);
   top = NSToIntRound(top / scale);
   width = NSToIntRound(width / scale);
   height = NSToIntRound(height / scale);
   {
-    int32_t contentWidth, contentHeight;
-    bool hasPrimaryContent = false;
-    aTreeOwner->GetHasPrimaryContent(&hasPrimaryContent);
-    if (hasPrimaryContent) {
-      aTreeOwner->GetPrimaryContentSize(&contentWidth, &contentHeight);
-    } else {
-      aTreeOwner->GetRootShellSize(&contentWidth, &contentHeight);
+    // scope shellWindow why not
+    nsCOMPtr<nsIBaseWindow> shellWindow(do_QueryInterface(aDocShellItem));
+    if (shellWindow) {
+      int32_t cox, coy;
+      double shellScale;
+      shellWindow->GetSize(&cox, &coy);
+      shellWindow->GetUnscaledDevicePixelsPerCSSPixel(&shellScale);
+      chromeWidth = width - NSToIntRound(cox / shellScale);
+      chromeHeight = height - NSToIntRound(coy / shellScale);
     }
-    chromeWidth = width - contentWidth;
-    chromeHeight = height - contentHeight;
   }
 
   // Set up left/top
   if (aSizeSpec.mLeftSpecified) {
     left = NSToIntRound(aSizeSpec.mLeft * openerZoom);
   }
 
   if (aSizeSpec.mTopSpecified) {
@@ -2382,16 +2172,17 @@ nsWindowWatcher::SizeOpenedWindow(nsIDoc
   if (aIsCallerChrome) {
     // Only enable special priveleges for chrome when chrome calls
     // open() on a chrome window
     nsCOMPtr<nsIDOMChromeWindow> chromeWin(do_QueryInterface(aParent));
     enabled = !aParent || chromeWin;
   }
 
   if (!enabled) {
+
     // Security check failed.  Ensure all args meet minimum reqs.
 
     int32_t oldTop = top, oldLeft = left;
 
     // We'll also need the screen dimensions
     nsCOMPtr<nsIScreen> screen;
     nsCOMPtr<nsIScreenManager> screenMgr(
       do_GetService("@mozilla.org/gfx/screenmanager;1"));
@@ -2480,23 +2271,17 @@ nsWindowWatcher::SizeOpenedWindow(nsIDoc
     // wherever it really ended up
     treeOwnerAsWin->GetUnscaledDevicePixelsPerCSSPixel(&scale);
   }
   if (aSizeSpec.SizeSpecified()) {
     /* Prefer to trust the interfaces, which think in terms of pure
        chrome or content sizes. If we have a mix, use the chrome size
        adjusted by the chrome/content differences calculated earlier. */
     if (!sizeChromeWidth && !sizeChromeHeight) {
-      bool hasPrimaryContent = false;
-      aTreeOwner->GetHasPrimaryContent(&hasPrimaryContent);
-      if (hasPrimaryContent) {
-        aTreeOwner->SetPrimaryContentSize(width * scale, height * scale);
-      } else {
-        aTreeOwner->SetRootShellSize(width * scale, height * scale);
-      }
+      treeOwner->SizeShellTo(aDocShellItem, width * scale, height * scale);
     } else {
       if (!sizeChromeWidth) {
         width += chromeWidth;
       }
       if (!sizeChromeHeight) {
         height += chromeHeight;
       }
       treeOwnerAsWin->SetSize(width * scale, height * scale, false);
--- a/embedding/components/windowwatcher/nsWindowWatcher.h
+++ b/embedding/components/windowwatcher/nsWindowWatcher.h
@@ -77,72 +77,51 @@ protected:
   // (which means called from script) or called via OpenWindow.
   nsresult OpenWindowInternal(mozIDOMWindowProxy* aParent,
                               const char* aUrl,
                               const char* aName,
                               const char* aFeatures,
                               bool aCalledFromJS,
                               bool aDialog,
                               bool aNavigate,
+                              nsITabParent* aOpeningTab,
                               nsIArray* aArgv,
                               float* aOpenerFullZoom,
                               mozIDOMWindowProxy** aResult);
 
   static nsresult URIfromURL(const char* aURL,
                              mozIDOMWindowProxy* aParent,
                              nsIURI** aURI);
 
-  static uint32_t CalculateChromeFlagsForChild(const nsACString& aFeaturesStr);
-
-  static uint32_t CalculateChromeFlagsForParent(mozIDOMWindowProxy* aParent,
-                                                const nsACString& aFeaturesStr,
-                                                bool aDialog,
-                                                bool aChromeURL,
-                                                bool aHasChromeParent,
-                                                bool aCalledFromJS);
-
-  static int32_t WinHasOption(const nsACString& aOptions, const char* aName,
+  static uint32_t CalculateChromeFlags(mozIDOMWindowProxy* aParent,
+                                       const char* aFeatures,
+                                       bool aFeaturesSpecified,
+                                       bool aDialog,
+                                       bool aChromeURL,
+                                       bool aHasChromeParent,
+                                       bool aCalledFromJS,
+                                       bool aOpenedFromRemoteTab);
+  static int32_t WinHasOption(const char* aOptions, const char* aName,
                               int32_t aDefault, bool* aPresenceFlag);
   /* Compute the right SizeSpec based on aFeatures */
-  static void CalcSizeSpec(const nsACString& aFeatures, SizeSpec& aResult);
+  static void CalcSizeSpec(const char* aFeatures, SizeSpec& aResult);
   static nsresult ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
                                           nsPIDOMWindowOuter* aParent,
                                           bool aWindowIsNew,
                                           mozIDOMWindowProxy** aOpenedWindow);
-  static void SizeOpenedWindow(nsIDocShellTreeOwner* aTreeOwner,
-                               mozIDOMWindowProxy* aParent,
-                               bool aIsCallerChrome,
-                               const SizeSpec& aSizeSpec,
-                               float* aOpenerFullZoom);
+  static void SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
+                                     mozIDOMWindowProxy* aParent,
+                                     bool aIsCallerChrome,
+                                     const SizeSpec& aSizeSpec,
+                                     float* aOpenerFullZoom);
   static void GetWindowTreeItem(mozIDOMWindowProxy* aWindow,
                                 nsIDocShellTreeItem** aResult);
   static void GetWindowTreeOwner(nsPIDOMWindowOuter* aWindow,
                                  nsIDocShellTreeOwner** aResult);
 
-private:
-  nsresult CreateChromeWindow(const nsACString& aFeatures,
-                              nsIWebBrowserChrome* aParentChrome,
-                              uint32_t aChromeFlags,
-                              uint32_t aContextFlags,
-                              nsITabParent* aOpeningTabParent,
-                              nsIWebBrowserChrome** aResult);
-
-  void MaybeDisablePersistence(const nsACString& aFeatures,
-                               nsIDocShellTreeOwner* aTreeOwner);
-
-  static uint32_t CalculateChromeFlagsHelper(uint32_t aInitialFlags,
-                                             const nsACString& aFeatures,
-                                             bool &presenceFlag,
-                                             bool aDialog = false,
-                                             bool aHasChromeParent = false,
-                                             bool aChromeURL = false);
-  static uint32_t EnsureFlagsSafeForContent(uint32_t aChromeFlags,
-                                            bool aChromeURL = false);
-
-protected:
   nsTArray<nsWatcherWindowEnumerator*> mEnumeratorList;
   nsWatcherWindowEntry* mOldestWindow;
   mozilla::Mutex mListLock;
 
   nsCOMPtr<nsIWindowCreator> mWindowCreator;
 };
 
 #endif
--- a/embedding/components/windowwatcher/test/browser.ini
+++ b/embedding/components/windowwatcher/test/browser.ini
@@ -1,9 +1,8 @@
 [DEFAULT]
 tags = openwindow
 
-[browser_new_content_window_chromeflags.js]
 [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
deleted file mode 100644
--- a/embedding/components/windowwatcher/test/browser_new_content_window_chromeflags.js
+++ /dev/null
@@ -1,278 +0,0 @@
-/**
- * Tests that chromeFlags are set properly on windows that are
- * being opened from content.
- */
-
-// The following features set chrome flags on new windows and are
-// supported by web content. The schema for each property on this
-// object is as follows:
-//
-// <feature string>: {
-//   flag: <associated nsIWebBrowserChrome flag>,
-//   defaults_to: <what this feature defaults to normally>
-// }
-const ALLOWED = {
-  "toolbar": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_TOOLBAR,
-    defaults_to: true,
-  },
-  "personalbar": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_PERSONAL_TOOLBAR,
-    defaults_to: true,
-  },
-  "menubar": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_MENUBAR,
-    defaults_to: true,
-  },
-  "scrollbars": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_SCROLLBARS,
-    defaults_to: false,
-  },
-  "minimizable": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_MIN,
-    defaults_to: true,
-  },
-};
-
-// Construct a features string that flips all ALLOWED features
-// to not be their defaults.
-const ALLOWED_STRING = Object.keys(ALLOWED).map(feature => {
-  let toValue = ALLOWED[feature].defaults_to ? "no" : "yes";
-  return `${feature}=${toValue}`;
-}).join(",");
-
-// The following are not allowed from web content, at least
-// in the default case (since some are disabled by default
-// via the dom.disable_window_open_feature pref branch).
-const DISALLOWED = {
-  "location": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_LOCATIONBAR,
-    defaults_to: true,
-  },
-  "chrome": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_OPENAS_CHROME,
-    defaults_to: false,
-  },
-  "dialog": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_OPENAS_DIALOG,
-    defaults_to: false,
-  },
-  "private": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_PRIVATE_WINDOW,
-    defaults_to: false,
-  },
-  "non-private": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_NON_PRIVATE_WINDOW,
-    defaults_to: false,
-  },
-  // "all":
-  //   checked manually, since this is an aggregate
-  //   flag.
-  //
-  // "remote":
-  //   checked manually, since its default value will
-  //   depend on whether or not e10s is enabled by default.
-  "popup": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_POPUP,
-    defaults_to: false,
-  },
-  "alwaysLowered": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_LOWERED,
-    defaults_to: false,
-  },
-  "z-lock": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_LOWERED, // Renamed to alwaysLowered
-    defaults_to: false,
-  },
-  "alwaysRaised": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_RAISED,
-    defaults_to: false,
-  },
-  "macsuppressanimation": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_MAC_SUPPRESS_ANIMATION,
-    defaults_to: false,
-  },
-  "extrachrome": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_EXTRA,
-    defaults_to: false,
-  },
-  "centerscreen": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_CENTER_SCREEN,
-    defaults_to: false,
-  },
-  "dependent": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_DEPENDENT,
-    defaults_to: false,
-  },
-  "modal": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_MODAL,
-    defaults_to: false,
-  },
-  "titlebar": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_TITLEBAR,
-    defaults_to: true,
-  },
-  "close": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_CLOSE,
-    defaults_to: true,
-  },
-  "resizable": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_WINDOW_RESIZE,
-    defaults_to: true,
-  },
-  "status": {
-    flag: Ci.nsIWebBrowserChrome.CHROME_STATUSBAR,
-    defaults_to: true,
-  },
-};
-
-// Construct a features string that flips all DISALLOWED features
-// to not be their defaults.
-const DISALLOWED_STRING = Object.keys(DISALLOWED).map(feature => {
-  let toValue = DISALLOWED[feature].defaults_to ? "no" : "yes";
-  return `${feature}=${toValue}`;
-}).join(",");
-
-const FEATURES = [ALLOWED_STRING, DISALLOWED_STRING].join(",");
-
-const SCRIPT_PAGE = `data:text/html,<script>window.open("about:blank", "_blank", "${FEATURES}");</script>`;
-const SCRIPT_PAGE_FOR_CHROME_ALL = `data:text/html,<script>window.open("about:blank", "_blank", "all");</script>`;
-
-// 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.
-Services.prefs.setIntPref("browser.link.open_newwindow", 2);
-registerCleanupFunction(() => {
-  Services.prefs.clearUserPref("browser.link.open_newwindow");
-});
-
-/**
- * Given some nsIDOMWindow for a window running in the parent
- * process, return the nsIWebBrowserChrome chrome flags for
- * the associated XUL window.
- *
- * @param win (nsIDOMWindow)
- *        Some window in the parent process.
- * @returns int
- */
-function getParentChromeFlags(win) {
-  return win.QueryInterface(Ci.nsIInterfaceRequestor)
-            .getInterface(Ci.nsIWebNavigation)
-            .QueryInterface(Ci.nsIDocShellTreeItem)
-            .treeOwner
-            .QueryInterface(Ci.nsIInterfaceRequestor)
-            .getInterface(Ci.nsIXULWindow)
-            .chromeFlags;
-}
-
-/**
- * For some chromeFlags, ensures that flags that are in the
- * ALLOWED group were modified, and that flags in the DISALLOWED
- * group were not modified.
- *
- * @param chromeFlags (int)
- *        Some chromeFlags to check.
- */
-function assertContentFlags(chromeFlags) {
-  for (let feature in ALLOWED) {
-    let flag = ALLOWED[feature].flag;
-
-    if (ALLOWED[feature].defaults_to) {
-      // The feature is supposed to default to true, so we should
-      // have been able to flip it off.
-      Assert.ok(!(chromeFlags & flag),
-                `Expected feature ${feature} to be disabled`);
-    } else {
-      // The feature is supposed to default to false, so we should
-      // have been able to flip it on.
-      Assert.ok((chromeFlags & flag),
-                `Expected feature ${feature} to be enabled`);
-    }
-  }
-
-  for (let feature in DISALLOWED) {
-    let flag = DISALLOWED[feature].flag;
-    if (DISALLOWED[feature].defaults_to) {
-      // The feature is supposed to default to true, so it should
-      // stay true.
-      Assert.ok((chromeFlags & flag),
-                `Expected feature ${feature} to be unchanged`);
-    } else {
-      // The feature is supposed to default to false, so it should
-      // stay false.
-      Assert.ok(!(chromeFlags & flag),
-                `Expected feature ${feature} to be unchanged`);
-    }
-  }
-}
-
-/**
- * Opens a window from content using window.open with the
- * features computed from ALLOWED and DISALLOWED. The computed
- * feature string attempts to flip every feature away from their
- * default.
- */
-add_task(function* test_new_remote_window_flags() {
-  let newWinPromise = BrowserTestUtils.waitForNewWindow();
-
-  yield BrowserTestUtils.withNewTab({
-    gBrowser,
-    url: SCRIPT_PAGE,
-  }, function*(browser) {
-    let win = yield newWinPromise;
-    let parentChromeFlags = getParentChromeFlags(win);
-    assertContentFlags(parentChromeFlags);
-
-    if (win.gMultiProcessBrowser) {
-      Assert.ok(parentChromeFlags &
-                Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW,
-                "Should be remote by default");
-    } else {
-      Assert.ok(!(parentChromeFlags &
-                  Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW),
-                "Should not be remote by default");
-    }
-
-    // Confusingly, chromeFlags also exist in the content process
-    // as part of the TabChild, so we have to check those too.
-    let b = win.gBrowser.selectedBrowser;
-    let contentChromeFlags = yield ContentTask.spawn(b, null, function*() {
-      docShell.QueryInterface(Ci.nsIInterfaceRequestor);
-      try {
-        // This will throw if we're not a remote browser.
-        return docShell.getInterface(Ci.nsITabChild)
-                       .QueryInterface(Ci.nsIWebBrowserChrome)
-                       .chromeFlags;
-      } catch(e) {
-        // This must be a non-remote browser...
-        return docShell.QueryInterface(Ci.nsIDocShellTreeItem)
-                       .treeOwner
-                       .QueryInterface(Ci.nsIWebBrowserChrome)
-                       .chromeFlags;
-      }
-    });
-
-    assertContentFlags(contentChromeFlags);
-    Assert.ok(!(contentChromeFlags &
-                Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW),
-              "Should not be remote in the content process.");
-
-    yield BrowserTestUtils.closeWindow(win);
-  });
-
-  // We check "all" manually, since that's an aggregate flag
-  // and doesn't fit nicely into the ALLOWED / DISALLOWED scheme
-  newWinPromise = BrowserTestUtils.waitForNewWindow();
-
-  yield BrowserTestUtils.withNewTab({
-    gBrowser,
-    url: SCRIPT_PAGE_FOR_CHROME_ALL,
-  }, function*(browser) {
-    let win = yield newWinPromise;
-    let parentChromeFlags = getParentChromeFlags(win);
-    Assert.notEqual((parentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_ALL),
-                    Ci.nsIWebBrowserChrome.CHROME_ALL,
-                    "Should not have been able to set CHROME_ALL");
-    yield BrowserTestUtils.closeWindow(win);
-  });
-});
--- a/embedding/nsIWindowCreator2.idl
+++ b/embedding/nsIWindowCreator2.idl
@@ -35,27 +35,33 @@ interface nsIWindowCreator2 : nsIWindowC
   /** Create a new window. Gecko will/may call this method, if made
       available to it, to create new windows.
       @param parent Parent window, if any. Null if not. The newly created
                     window should be made a child/dependent window of
                     the parent, if any (and if the concept applies
                     to the underlying OS).
       @param chromeFlags Chrome features from nsIWebBrowserChrome
       @param contextFlags Flags about the context of the window being created.
+      @param uri The URL for which this window is intended. It can be null
+                 or zero-length. The implementation of this interface
+                 may use the URL to help determine what sort of window
+                 to open or whether to cancel window creation. It will not
+                 load the URL.
       @param aOpeningTab The TabParent that is trying to open this new chrome
                          window. Can be nullptr.
       @param cancel Return |true| to reject window creation. If true the
                     implementation has determined the window should not
                     be created at all. The caller should not default
                     to any possible backup scheme for creating the window.
       @return the new window. Will be null if canceled or an error occurred.
   */
   nsIWebBrowserChrome createChromeWindow2(in nsIWebBrowserChrome parent,
                                           in uint32_t chromeFlags,
                                           in uint32_t contextFlags,
+                                          in nsIURI uri,
                                           in nsITabParent aOpeningTab,
                                           out boolean cancel);
 
   /**
    * B2G multi-screen support. When open another top-level window on b2g,
    * a screen ID is needed for identifying which screen this window is
    * opened to.
    * @param aScreenId Differentiate screens of windows. It is platform-
--- a/testing/marionette/listener.js
+++ b/testing/marionette/listener.js
@@ -25,18 +25,16 @@ Cu.import("chrome://marionette/content/i
 Cu.import("chrome://marionette/content/logging.js");
 Cu.import("chrome://marionette/content/proxy.js");
 Cu.import("chrome://marionette/content/simpletest.js");
 
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-Cu.importGlobalProperties(["URL"]);
-
 var contentLog = new logging.ContentLogger();
 
 var isB2G = false;
 
 var marionetteTestName;
 var winUtil = content.QueryInterface(Ci.nsIInterfaceRequestor)
     .getInterface(Ci.nsIDOMWindowUtils);
 var listenerId = null; // unique ID of this listener
@@ -924,50 +922,44 @@ function pollForReadyState(msg, start, c
 /**
  * Navigate to the given URL.  The operation will be performed on the
  * current browsing context, which means it handles the case where we
  * navigate within an iframe.  All other navigation is handled by the
  * driver (in chrome space).
  */
 function get(msg) {
   let start = new Date().getTime();
-  let requestedURL = new URL(msg.json.url).toString();
 
   // Prevent DOMContentLoaded events from frames from invoking this
   // code, unless the event is coming from the frame associated with
   // the current window (i.e. someone has used switch_to_frame).
   onDOMContentLoaded = function onDOMContentLoaded(event) {
-    let correctFrame =
-      !event.originalTarget.defaultView.frameElement ||
-      event.originalTarget.defaultView.frameElement == curContainer.frame.frameElement;
-
-    let correctURL = curContainer.frame.location == requestedURL;
-
-    if (correctFrame && correctURL) {
+    if (!event.originalTarget.defaultView.frameElement ||
+        event.originalTarget.defaultView.frameElement == curContainer.frame.frameElement) {
       pollForReadyState(msg, start, () => {
         removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
       });
     }
   };
 
   function timerFunc() {
     removeEventListener("DOMContentLoaded", onDOMContentLoaded, false);
     sendError(new TimeoutError("Error loading page, timed out (onDOMContentLoaded)"), msg.json.command_id);
   }
   if (msg.json.pageTimeout != null) {
     navTimer.initWithCallback(timerFunc, msg.json.pageTimeout, Ci.nsITimer.TYPE_ONE_SHOT);
   }
   addEventListener("DOMContentLoaded", onDOMContentLoaded, false);
   if (isB2G) {
-    curContainer.frame.location = requestedURL;
+    curContainer.frame.location = msg.json.url;
   } else {
     // We need to move to the top frame before navigating
     sendSyncMessage("Marionette:switchedToFrame", { frameValue: null });
     curContainer.frame = content;
-    curContainer.frame.location = requestedURL;
+    curContainer.frame.location = msg.json.url;
   }
 }
 
  /**
  * Cancel the polling and remove the event listener associated with a current
  * navigation request in case we're interupted by an onbeforeunload handler
  * and navigation doesn't complete.
  */
--- a/testing/talos/talos/pageloader/chrome/pageloader.js
+++ b/testing/talos/talos/pageloader/chrome/pageloader.js
@@ -224,33 +224,34 @@ function plInit() {
         function firstPageCanLoadAsRemote() {
           return E10SUtils.canLoadURIInProcess(pageUrls[0], Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
         }
 
         // do this half a second after load, because we need to be
         // able to resize the window and not have it get clobbered
         // by the persisted values
         setTimeout(function () {
-                     // For e10s windows, since bug 1261842, the initial browser is remote unless
-                     // it attempts to browse to a URI that should be non-remote (landed at bug 1047603).
-                     //
-                     // However, when it loads such URI and reinitializes as non-remote, we lose the
+                     // For e10s windows, the initial browser is not remote until it attempts to
+                     // browse to a URI that should be remote (landed at bug 1047603).
+                     // However, when it loads such URI and reinitialize as remote, we lose the
                      // load listener and the injected tpRecordTime.
+                     // The same thing happens if the initial browser starts as remote but the
+                     // first page is not-remote (such as with TART/CART which load a chrome URI).
                      //
                      // The preferred pageloader behaviour in e10s is to run the pages as as remote,
                      // so if the page can load as remote, we will load it as remote.
                      //
                      // It also probably means that per test (or, in fact, per pageloader browser
                      // instance which adds the load listener and injects tpRecordTime), all the
                      // pages should be able to load in the same mode as the initial page - due
                      // to this reinitialization on the switch.
                      if (browserWindow.gMultiProcessBrowser) {
-                       if (!firstPageCanLoadAsRemote())
-                         browserWindow.XULBrowserWindow.forceInitialBrowserNonRemote();
-                       // Implicit else: initial browser in e10s is remote by default.
+                       if (firstPageCanLoadAsRemote())
+                         browserWindow.XULBrowserWindow.forceInitialBrowserRemote();
+                       // Implicit else: initial browser in e10s is non-remote by default.
                      }
 
                      browserWindow.resizeTo(winWidth, winHeight);
                      browserWindow.moveTo(0, 0);
                      browserWindow.focus();
 
                      content = browserWindow.getBrowser();
                      gUseE10S = !gDisableE10S || (plPageFlags() & EXECUTE_SCROLL_TEST) ||
--- a/testing/talos/talos/pageloader/install.rdf
+++ b/testing/talos/talos/pageloader/install.rdf
@@ -1,15 +1,15 @@
 <?xml version="1.0"?>
 
 <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:em="http://www.mozilla.org/2004/em-rdf#">
   <Description about="urn:mozilla:install-manifest">
     <em:id>pageloader@mozilla.org</em:id>
-    <em:version>1.0.10</em:version>
+    <em:version>1.0.9</em:version>
     <em:targetApplication>
       <Description>
         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
         <em:minVersion>44.0</em:minVersion>
         <em:maxVersion>*</em:maxVersion>
       </Description>
     </em:targetApplication>
     <!-- Front End MetaData -->
index 325e71a4c4e742a52f361c6a42cbfd5bcd8bfb16..cc0778d7614a19ae9a22d2c0dd14f7aecca8c468
GIT binary patch
literal 29213
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
HA4mTIxjQ=|
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -20,17 +20,16 @@ const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.importGlobalProperties(["TextEncoder"]);
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/ExtensionContent.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "EventEmitter",
                                   "resource://devtools/shared/event-emitter.js");
 XPCOMUtils.defineLazyModuleGetter(this, "Locale",
                                   "resource://gre/modules/Locale.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Log",
                                   "resource://gre/modules/Log.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MatchGlobs",
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -609,17 +609,17 @@ nsAppStartup::GetInterrupted(bool *aInte
 //
 
 NS_IMETHODIMP
 nsAppStartup::CreateChromeWindow(nsIWebBrowserChrome *aParent,
                                  uint32_t aChromeFlags,
                                  nsIWebBrowserChrome **_retval)
 {
   bool cancel;
-  return CreateChromeWindow2(aParent, aChromeFlags, 0, nullptr, &cancel, _retval);
+  return CreateChromeWindow2(aParent, aChromeFlags, 0, 0, nullptr, &cancel, _retval);
 }
 
 
 //
 // nsAppStartup->nsIWindowCreator2
 //
 
 NS_IMETHODIMP
@@ -632,16 +632,17 @@ nsAppStartup::SetScreenId(uint32_t aScre
 
   return appShell->SetScreenId(aScreenId);
 }
 
 NS_IMETHODIMP
 nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent,
                                   uint32_t aChromeFlags,
                                   uint32_t aContextFlags,
+                                  nsIURI *aURI,
                                   nsITabParent *aOpeningTab,
                                   bool *aCancel,
                                   nsIWebBrowserChrome **_retval)
 {
   NS_ENSURE_ARG_POINTER(aCancel);
   NS_ENSURE_ARG_POINTER(_retval);
   *aCancel = false;
   *_retval = 0;
--- a/xpfe/appshell/moz.build
+++ b/xpfe/appshell/moz.build
@@ -33,10 +33,8 @@ UNIFIED_SOURCES += [
     'nsXULWindow.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-include('/ipc/chromium/chromium-config.mozbuild')
\ No newline at end of file
--- a/xpfe/appshell/nsChromeTreeOwner.cpp
+++ b/xpfe/appshell/nsChromeTreeOwner.cpp
@@ -264,48 +264,16 @@ nsChromeTreeOwner::TabParentRemoved(nsIT
 
 NS_IMETHODIMP
 nsChromeTreeOwner::GetPrimaryTabParent(nsITabParent** aTab)
 {
   NS_ENSURE_STATE(mXULWindow);
   return mXULWindow->GetPrimaryTabParent(aTab);
 }
 
-NS_IMETHODIMP
-nsChromeTreeOwner::GetPrimaryContentSize(int32_t* aWidth,
-                                         int32_t* aHeight)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->GetPrimaryContentSize(aWidth, aHeight);
-}
-
-NS_IMETHODIMP
-nsChromeTreeOwner::SetPrimaryContentSize(int32_t aWidth,
-                                         int32_t aHeight)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->SetPrimaryContentSize(aWidth, aHeight);
-}
-
-NS_IMETHODIMP
-nsChromeTreeOwner::GetRootShellSize(int32_t* aWidth,
-                                    int32_t* aHeight)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->GetRootShellSize(aWidth, aHeight);
-}
-
-NS_IMETHODIMP
-nsChromeTreeOwner::SetRootShellSize(int32_t aWidth,
-                                    int32_t aHeight)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->SetRootShellSize(aWidth, aHeight);
-}
-
 NS_IMETHODIMP nsChromeTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
    int32_t aCX, int32_t aCY)
 {
    NS_ENSURE_STATE(mXULWindow);
    return mXULWindow->SizeShellTo(aShellItem, aCX, aCY);
 }
 
 NS_IMETHODIMP
@@ -376,23 +344,16 @@ nsChromeTreeOwner::GetPersistence(bool* 
 
 NS_IMETHODIMP
 nsChromeTreeOwner::GetTargetableShellCount(uint32_t* aResult)
 {
   *aResult = 0;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsChromeTreeOwner::GetHasPrimaryContent(bool* aResult)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->GetHasPrimaryContent(aResult);
-}
-
 //*****************************************************************************
 // nsChromeTreeOwner::nsIBaseWindow
 //*****************************************************************************   
 
 NS_IMETHODIMP nsChromeTreeOwner::InitWindow(nativeWindow aParentNativeWindow,
    nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy)   
 {
    // Ignore widget parents for now.  Don't think those are a vaild thing to call.
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -329,48 +329,16 @@ nsContentTreeOwner::TabParentRemoved(nsI
 
 NS_IMETHODIMP
 nsContentTreeOwner::GetPrimaryTabParent(nsITabParent** aTab)
 {
   NS_ENSURE_STATE(mXULWindow);
   return mXULWindow->GetPrimaryTabParent(aTab);
 }
 
-NS_IMETHODIMP
-nsContentTreeOwner::GetPrimaryContentSize(int32_t* aWidth,
-                                          int32_t* aHeight)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->GetPrimaryContentSize(aWidth, aHeight);
-}
-
-NS_IMETHODIMP
-nsContentTreeOwner::SetPrimaryContentSize(int32_t aWidth,
-                                          int32_t aHeight)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->SetPrimaryContentSize(aWidth, aHeight);
-}
-
-NS_IMETHODIMP
-nsContentTreeOwner::GetRootShellSize(int32_t* aWidth,
-                                     int32_t* aHeight)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->GetRootShellSize(aWidth, aHeight);
-}
-
-NS_IMETHODIMP
-nsContentTreeOwner::SetRootShellSize(int32_t aWidth,
-                                     int32_t aHeight)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->SetRootShellSize(aWidth, aHeight);
-}
-
 NS_IMETHODIMP nsContentTreeOwner::SizeShellTo(nsIDocShellTreeItem* aShellItem,
    int32_t aCX, int32_t aCY)
 {
    NS_ENSURE_STATE(mXULWindow);
    return mXULWindow->SizeShellTo(aShellItem, aCX, aCY);
 }
 
 NS_IMETHODIMP
@@ -471,23 +439,16 @@ nsContentTreeOwner::GetPersistence(bool*
 NS_IMETHODIMP
 nsContentTreeOwner::GetTargetableShellCount(uint32_t* aResult)
 {
   NS_ENSURE_STATE(mXULWindow);
   *aResult = mXULWindow->mTargetableShells.Count();
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsContentTreeOwner::GetHasPrimaryContent(bool* aResult)
-{
-  NS_ENSURE_STATE(mXULWindow);
-  return mXULWindow->GetHasPrimaryContent(aResult);
-}
-
 //*****************************************************************************
 // nsContentTreeOwner::nsIWebBrowserChrome3
 //*****************************************************************************   
 
 NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal(const nsAString &originalTarget,
                                                         nsIURI *linkURI,
                                                         nsIDOMNode *linkNode,
                                                         bool isAppTab,
--- a/xpfe/appshell/nsIXULBrowserWindow.idl
+++ b/xpfe/appshell/nsIXULBrowserWindow.idl
@@ -43,17 +43,16 @@ interface nsIXULBrowserWindow : nsISuppo
 
   /**
    * Find the initial browser of the window and set its remote attribute.
    * This can be used to ensure that there is a remote browser in a new
    * window when it first spawns.
    *
    */
   nsITabParent forceInitialBrowserRemote();
-  void forceInitialBrowserNonRemote();
 
   /**
    * Determines whether a load should continue.
    *
    * @param aDocShell
    *        The docshell performing the load.
    * @param aURI
    *        The URI being loaded.
--- a/xpfe/appshell/nsIXULWindow.idl
+++ b/xpfe/appshell/nsIXULWindow.idl
@@ -130,36 +130,17 @@ interface nsIXULWindow : nsISupports
   /**
    * Back-door method to force application of chrome flags at a particular
    * time.  Do NOT call this unless you know what you're doing!  In particular,
    * calling this when this XUL window doesn't yet have a document in its
    * docshell could cause problems.
    */
   [noscript] void applyChromeFlags();
 
+
   /**
-   * Given the dimensions of some content area held within this
-   * XUL window, and assuming that that content area will change
-   * its dimensions in linear proportion to the dimensions of this
-   * XUL window, changes the size of the XUL window so that the
-   * content area reaches a particular size.
-   *
-   * We need to supply the content area dimensions because sometimes
-   * the child's nsDocShellTreeOwner needs to propagate a SizeShellTo
-   * call to the parent. But the shellItem argument of the call will
-   * not be available on the parent side.
-   *
+   * Sometimes the child's nsDocShellTreeOwner needs to propogate a SizeShellTo call to the parent. But the
+   * shellItem argument of the call will not be available on the parent side, so we pass its dimensions here.
    * Note: this is an internal method, other consumers should never call this.
-   *
-   * @param aDesiredWidth
-   *        The desired width of the content area in device pixels.
-   * @param aDesiredHeight
-   *        The desired height of the content area in device pixels.
-   * @param shellItemWidth
-   *        The current width of the content area.
-   * @param shellItemHeight
-   *        The current height of the content area.
    */
-  [noscript, notxpcom] void sizeShellToWithLimit(in int32_t aDesiredWidth,
-                                                 in int32_t aDesiredHeight,
-                                                 in int32_t shellItemWidth,
-                                                 in int32_t shellItemHeight);
+  [noscript, notxpcom] void sizeShellToWithLimit(in int32_t aCx, in int32_t aCy,
+                                                 in int32_t shellItemCx, in int32_t shellItemCy);
 };
--- a/xpfe/appshell/nsXULWindow.cpp
+++ b/xpfe/appshell/nsXULWindow.cpp
@@ -56,17 +56,16 @@
 #include "prenv.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/BarProps.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/ScriptSettings.h"
-#include "mozilla/dom/TabParent.h"
 
 using namespace mozilla;
 using dom::AutoNoJSAPI;
 
 #define SIZEMODE_NORMAL     NS_LITERAL_STRING("normal")
 #define SIZEMODE_MAXIMIZED  NS_LITERAL_STRING("maximized")
 #define SIZEMODE_MINIMIZED  NS_LITERAL_STRING("minimized")
 #define SIZEMODE_FULLSCREEN NS_LITERAL_STRING("fullscreen")
@@ -1797,107 +1796,16 @@ nsresult nsXULWindow::ContentShellRemove
     if (!curItem || SameCOMIdentity(curItem, aContentShell)) {
       mTargetableShells.RemoveObjectAt(i);
     }
   }
   
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULWindow::GetPrimaryContentSize(int32_t* aWidth,
-                                   int32_t* aHeight)
-{
-  if (mPrimaryTabParent) {
-    return GetPrimaryTabParentSize(aWidth, aHeight);
-  } else if (mPrimaryContentShell) {
-    return GetPrimaryContentShellSize(aWidth, aHeight);
-  }
-  return NS_ERROR_UNEXPECTED;
-}
-
-nsresult
-nsXULWindow::GetPrimaryTabParentSize(int32_t* aWidth,
-                                     int32_t* aHeight)
-{
-  TabParent* tabParent = TabParent::GetFrom(mPrimaryTabParent);
-  Element* element = tabParent->GetOwnerElement();
-  NS_ENSURE_STATE(element);
-
-  *aWidth = element->ClientWidth();
-  *aHeight = element->ClientHeight();
-  return NS_OK;
-}
-
-nsresult
-nsXULWindow::GetPrimaryContentShellSize(int32_t* aWidth,
-                                        int32_t* aHeight)
-{
-  NS_ENSURE_STATE(mPrimaryContentShell);
-
-  nsCOMPtr<nsIBaseWindow> shellWindow(do_QueryInterface(mPrimaryContentShell));
-  NS_ENSURE_STATE(shellWindow);
-
-  int32_t devicePixelWidth, devicePixelHeight;
-  double shellScale = 1.0;
-  // We want to return CSS pixels. First, we get device pixels
-  // from the content area...
-  shellWindow->GetSize(&devicePixelWidth, &devicePixelHeight);
-  // And then get the device pixel scaling factor. Dividing device
-  // pixels by this scaling factor gives us CSS pixels.
-  shellWindow->GetUnscaledDevicePixelsPerCSSPixel(&shellScale);
-  *aWidth = NSToIntRound(devicePixelWidth / shellScale);
-  *aHeight = NSToIntRound(devicePixelHeight / shellScale);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXULWindow::SetPrimaryContentSize(int32_t aWidth,
-                                   int32_t aHeight)
-{
-  if (mPrimaryTabParent) {
-    return SetPrimaryTabParentSize(aWidth, aHeight);
-  } else if (mPrimaryContentShell) {
-    return SizeShellTo(mPrimaryContentShell, aWidth, aHeight);
-  }
-  return NS_ERROR_UNEXPECTED;
-}
-
-nsresult
-nsXULWindow::SetPrimaryTabParentSize(int32_t aWidth,
-                                     int32_t aHeight)
-{
-  int32_t shellWidth, shellHeight;
-  GetPrimaryTabParentSize(&shellWidth, &shellHeight);
-
-  double scale = 1.0;
-  GetUnscaledDevicePixelsPerCSSPixel(&scale);
-
-  SizeShellToWithLimit(aWidth, aHeight,
-                       shellWidth * scale, shellHeight * scale);
-  return NS_OK;
-}
-
-nsresult
-nsXULWindow::GetRootShellSize(int32_t* aWidth,
-                              int32_t* aHeight)
-{
-  nsCOMPtr<nsIBaseWindow> shellAsWin = do_QueryInterface(mDocShell);
-  NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE);
-  return shellAsWin->GetSize(aWidth, aHeight);
-}
-
-nsresult
-nsXULWindow::SetRootShellSize(int32_t aWidth,
-                              int32_t aHeight)
-{
-  nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = do_QueryInterface(mDocShell);
-  return SizeShellTo(docShellAsItem, aWidth, aHeight);
-}
-
 NS_IMETHODIMP nsXULWindow::SizeShellTo(nsIDocShellTreeItem* aShellItem,
    int32_t aCX, int32_t aCY)
 {
   // XXXTAB This is wrong, we should actually reflow based on the passed in
   // shell.  For now we are hacking and doing delta sizing.  This is bad
   // because it assumes all size we add will go to the shell which probably
   // won't happen.
 
@@ -2008,30 +1916,24 @@ NS_IMETHODIMP nsXULWindow::CreateNewCont
     AutoNoJSAPI nojsapi;
     nsIThread *thread = NS_GetCurrentThread();
     while (xulWin->IsLocked()) {
       if (!NS_ProcessNextEvent(thread))
         break;
     }
   }
 
-  NS_ENSURE_STATE(xulWin->mPrimaryContentShell || xulWin->mPrimaryTabParent);
+  NS_ENSURE_STATE(xulWin->mPrimaryContentShell);
 
   *_retval = newWindow;
   NS_ADDREF(*_retval);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULWindow::GetHasPrimaryContent(bool* aResult)
-{
-  *aResult = mPrimaryTabParent || mPrimaryContentShell;
-  return NS_OK;
-}
-
 void nsXULWindow::EnableParent(bool aEnable)
 {
   nsCOMPtr<nsIBaseWindow> parentWindow;
   nsCOMPtr<nsIWidget>     parentWidget;
 
   parentWindow = do_QueryReferent(mParentWindow);
   if (parentWindow)
     parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
@@ -2275,36 +2177,34 @@ NS_IMETHODIMP nsXULWindow::GetXULBrowser
 }
 
 NS_IMETHODIMP nsXULWindow::SetXULBrowserWindow(nsIXULBrowserWindow * aXULBrowserWindow)
 {
   mXULBrowserWindow = aXULBrowserWindow;
   return NS_OK;
 }
 
-void nsXULWindow::SizeShellToWithLimit(int32_t aDesiredWidth,
-                                       int32_t aDesiredHeight,
-                                       int32_t shellItemWidth,
-                                       int32_t shellItemHeight)
+void nsXULWindow::SizeShellToWithLimit(int32_t aCX, int32_t aCY,
+                                       int32_t shellItemCx, int32_t shellItemCy)
 {
-  int32_t widthDelta = aDesiredWidth - shellItemWidth;
-  int32_t heightDelta = aDesiredHeight - shellItemHeight;
+  int32_t widthDelta = aCX - shellItemCx;
+  int32_t heightDelta = aCY - shellItemCy;
 
   if (widthDelta || heightDelta) {
-    int32_t winWidth = 0;
-    int32_t winHeight = 0;
+    int32_t winCX = 0;
+    int32_t winCY = 0;
 
-    GetSize(&winWidth, &winHeight);
+    GetSize(&winCX, &winCY);
     // There's no point in trying to make the window smaller than the
-    // desired content area size --- that's not likely to work. This whole
+    // desired docshell size --- that's not likely to work. This whole
     // function assumes that the outer docshell is adding some constant
-    // "border" chrome to the content area.
-    winWidth = std::max(winWidth + widthDelta, aDesiredWidth);
-    winHeight = std::max(winHeight + heightDelta, aDesiredHeight);
-    SetSize(winWidth, winHeight, true);
+    // "border" chrome to aShellItem.
+    winCX = std::max(winCX + widthDelta, aCX);
+    winCY = std::max(winCY + heightDelta, aCY);
+    SetSize(winCX, winCY, true);
   }
 }
 
 //*****************************************************************************
 //*** nsContentShellInfo: Object Management
 //*****************************************************************************   
 
 nsContentShellInfo::nsContentShellInfo(const nsAString& aID,
--- a/xpfe/appshell/nsXULWindow.h
+++ b/xpfe/appshell/nsXULWindow.h
@@ -104,31 +104,21 @@ protected:
    NS_IMETHOD GetWindowDOMWindow(mozIDOMWindowProxy** aDOMWindow);
    mozilla::dom::Element* GetWindowDOMElement() const;
 
    // See nsIDocShellTreeOwner for docs on next two methods
    nsresult ContentShellAdded(nsIDocShellTreeItem* aContentShell,
                                           bool aPrimary, bool aTargetable,
                                           const nsAString& aID);
    nsresult ContentShellRemoved(nsIDocShellTreeItem* aContentShell);
-   NS_IMETHOD GetPrimaryContentSize(int32_t* aWidth,
-                                    int32_t* aHeight);
-   NS_IMETHOD SetPrimaryContentSize(int32_t aWidth,
-                                    int32_t aHeight);
-   nsresult GetRootShellSize(int32_t* aWidth,
-                             int32_t* aHeight);
-   nsresult SetRootShellSize(int32_t aWidth,
-                             int32_t aHeight);
-
    NS_IMETHOD SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX, 
       int32_t aCY);
    NS_IMETHOD ExitModalLoop(nsresult aStatus);
    NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval);
    NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval);
-   NS_IMETHOD GetHasPrimaryContent(bool* aResult);
 
    void       EnableParent(bool aEnable);
    bool       ConstrainToZLevel(bool aImmediate, nsWindowZ *aPlacement,
                                 nsIWidget *aReqBelow, nsIWidget **aActualBelow);
    void       PlaceWindowLayersBehind(uint32_t aLowLevel, uint32_t aHighLevel,
                                       nsIXULWindow *aBehind);
    void       SetContentScrollbarVisibility(bool aVisible);
    bool       GetContentScrollbarVisibility();
@@ -168,20 +158,16 @@ protected:
    uint32_t                mPersistentAttributesMask;
    uint32_t                mChromeFlags;
    nsString                mTitle;
    nsIntRect               mOpenerScreenRect; // the screen rect of the opener
 
    nsCOMArray<nsIWeakReference> mTargetableShells; // targetable shells only
 
    nsCOMPtr<nsITabParent> mPrimaryTabParent;
-private:
-   nsresult GetPrimaryTabParentSize(int32_t* aWidth, int32_t* aHeight);
-   nsresult GetPrimaryContentShellSize(int32_t* aWidth, int32_t* aHeight);
-   nsresult SetPrimaryTabParentSize(int32_t aWidth, int32_t aHeight);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXULWindow, NS_XULWINDOW_IMPL_CID)
 
 // nsContentShellInfo
 // Used to map shell IDs to nsIDocShellTreeItems.
 
 class nsContentShellInfo