Bug 1261842 - Factor out logic for creating windows for content processes from nsWindowWatcher::OpenWindowInternal. r=smaug
☠☠ backed out by ad32bf1994e9 ☠ ☠
authorMike Conley <mconley@mozilla.com>
Tue, 05 Jul 2016 12:00:07 -0400
changeset 330710 4cf843a05a68d55d1686d5cf347864563a623f97
parent 330709 cbdc0deb92bd5bcbae0be65c7bbd5ad020f7a153
child 330711 e91913cd64b8bebe80c661935adee644f24c6055
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1261842
milestone50.0a1
Bug 1261842 - Factor out logic for creating windows for content processes from nsWindowWatcher::OpenWindowInternal. r=smaug MozReview-Commit-ID: 1dhGthT8bmu
dom/base/nsGlobalWindow.cpp
dom/ipc/ContentParent.cpp
dom/workers/ServiceWorkerClients.cpp
embedding/components/windowwatcher/moz.build
embedding/components/windowwatcher/nsPIWindowWatcher.idl
embedding/components/windowwatcher/nsWindowWatcher.cpp
embedding/components/windowwatcher/nsWindowWatcher.h
--- 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, nullptr, argv,
+                                aDialog, aNavigate, 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, nullptr, aExtraArgument,
+                                aDialog, aNavigate, aExtraArgument,
                                 1.0f, 0, getter_AddRefs(domReturn));
 
     }
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // success!
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5316,23 +5316,16 @@ 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;
@@ -5418,51 +5411,32 @@ ContentParent::RecvCreateWindow(PBrowser
     return true;
   }
 
   nsCOMPtr<mozIDOMWindowProxy> window;
   TabParent::AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
 
   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)) {
+  nsCOMPtr<nsPIWindowWatcher> pwwatch =
+    do_GetService(NS_WINDOWWATCHER_CONTRACTID, aResult);
+
+  if (NS_WARN_IF(NS_FAILED(*aResult))) {
     return true;
   }
 
   nsCOMPtr<nsITabParent> newRemoteTab;
-  *aResult = xulBrowserWin->ForceInitialBrowserRemote(getter_AddRefs(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, features, aCalledFromJS,
+                                                aFullZoom, getter_AddRefs(newRemoteTab));
+  }
 
   if (NS_WARN_IF(NS_FAILED(*aResult))) {
     return true;
   }
 
   MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab);
 
   newTab->SwapFrameScriptsFrom(*aFrameScripts);
--- 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, nullptr, 1.0f, 0,
+                           false, false, true, 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/components/windowwatcher/moz.build
+++ b/embedding/components/windowwatcher/moz.build
@@ -40,8 +40,10 @@ 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,19 +49,16 @@ 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
@@ -72,21 +69,52 @@ 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 string 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,16 +59,19 @@
 #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;
 
@@ -363,17 +366,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, nullptr, argv,
+                            /* navigate = */ true, argv,
                             /* openerFullZoom = */ nullptr, aResult);
 }
 
 struct SizeSpec
 {
   SizeSpec()
     : mLeftSpecified(false)
     , mTopSpecified(false)
@@ -420,17 +423,16 @@ 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;
@@ -443,17 +445,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, aOpeningTab, argv,
+                            aNavigate, 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)
@@ -481,104 +483,233 @@ 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, "", true, 1.0f, aResult);
+}
+
+NS_IMETHODIMP
+nsWindowWatcher::OpenWindowWithTabParent(nsITabParent* aOpeningTabParent,
+                                         const char* 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;
+  }
+
+  // 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, "mozDisplayId", 0, nullptr);
+  windowCreator2->SetScreenId(retval);
+#endif
+
+  nsAutoCString features(aFeatures);
+  uint32_t chromeFlags = CalculateChromeFlagsForChild(features);
+
+  // 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;
+
+  bool cancel = false;
+  nsCOMPtr<nsIWebBrowserChrome> parentChrome(do_GetInterface(parentTreeOwner));
+  nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
+
+  nsresult rv =
+    windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags, contextFlags,
+                                        aOpeningTabParent, &cancel,
+                                        getter_AddRefs(newWindowChrome));
+
+  if (NS_SUCCEEDED(rv) && cancel) {
+    newWindowChrome = nullptr; // just in case
+    return NS_ERROR_ABORT;
+  }
+
+  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);
+
+  if (PL_strcasestr(features.get(), "width=") ||
+      PL_strcasestr(features.get(), "height=")) {
+    chromeTreeOwner->SetPersistence(false, false, false);
+  }
+
+  SizeSpec sizeSpec;
+  CalcSizeSpec(features, sizeSpec);
+  SizeOpenedDocShellItem(chromeTreeItem, 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 && !openedFromRemoteTab) {
+  if (aUrl) {
     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);
   }
 
-  // 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));
-  }
+  // 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) {
@@ -593,33 +724,39 @@ 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) && !openedFromRemoteTab;
+    hasChromeParent = doc && nsContentUtils::IsChromeDoc(doc);
   }
 
-  // Make sure we call CalculateChromeFlags() *before* we push the
+  bool isCallerChrome = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
+
+  // Make sure we calculate the chromeFlags *before* we push the
   // callee context onto the context stack so that
-  // CalculateChromeFlags() sees the actual caller when doing its
+  // the calculation sees the actual caller when doing its
   // security checks.
-  chromeFlags = CalculateChromeFlags(aParent, features, featuresSpecified,
-                                     aDialog, uriToLoadIsChrome,
-                                     hasChromeParent, aCalledFromJS,
-                                     openedFromRemoteTab);
+  if (isCallerChrome && XRE_IsParentProcess()) {
+    chromeFlags = CalculateChromeFlagsForParent(aParent, features,
+                                                aDialog, uriToLoadIsChrome,
+                                                hasChromeParent, aCalledFromJS);
+  } else {
+    chromeFlags = CalculateChromeFlagsForChild(features);
 
-  // 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);
+    // 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'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)) {
     windowIsModalContentDialog = true;
 
@@ -633,18 +770,16 @@ nsWindowWatcher::OpenWindowInternal(mozI
   }
 
   SizeSpec sizeSpec;
   CalcSizeSpec(features, 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;
@@ -832,29 +967,36 @@ nsWindowWatcher::OpenWindowInternal(mozI
 #ifdef MOZ_WIDGET_GONK
         int retval = WinHasOption(features, "mozDisplayId", 0, nullptr);
         windowCreator2->SetScreenId(retval);
 #endif
 
 
         bool cancel = false;
         rv = windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags,
-                                                 contextFlags, uriToLoad,
-                                                 aOpeningTab, &cancel,
-                                                 getter_AddRefs(newChrome));
+                                                 contextFlags, nullptr,
+                                                 &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) {
@@ -1536,120 +1678,51 @@ 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 && !openedFromContentScript) &&                 \
-      !(!openedFromContentScript && 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 && !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::CalculateChromeFlags(mozIDOMWindowProxy* aParent,
-                                      const nsACString& aFeatures,
-                                      bool aFeaturesSpecified,
-                                      bool aDialog,
-                                      bool aChromeURL,
-                                      bool aHasChromeParent,
-                                      bool aCalledFromJS,
-                                      bool aOpenedFromRemoteTab)
+nsWindowWatcher::CalculateChromeFlagsHelper(uint32_t aInitialFlags,
+                                            const nsACString& aFeatures,
+                                            bool& presenceFlag,
+                                            bool aDialog,
+                                            bool aHasChromeParent,
+                                            bool aChromeURL)
 {
-  const bool inContentProcess = XRE_IsContentProcess();
-  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;
-    }
-
-    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;
-    }
-  }
+  uint32_t chromeFlags = aInitialFlags;
 
   nsresult rv;
-
   nsCOMPtr<nsIPrefBranch> prefBranch;
   nsCOMPtr<nsIPrefService> prefs =
     do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, true);
+
+  NS_ENSURE_SUCCESS(rv, nsIWebBrowserChrome::CHROME_DEFAULT);
 
   rv = prefs->GetBranch("dom.disable_window_open_feature.",
                         getter_AddRefs(prefBranch));
-  NS_ENSURE_SUCCESS(rv, true);
+
+  NS_ENSURE_SUCCESS(rv, nsIWebBrowserChrome::CHROME_DEFAULT);
 
+  // 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);
@@ -1666,16 +1739,140 @@ nsWindowWatcher::CalculateChromeFlags(mo
   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
@@ -1719,26 +1916,21 @@ nsWindowWatcher::CalculateChromeFlags(mo
     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_QueryInterface(prefs);
+  nsCOMPtr<nsIPrefBranch> branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
+
   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) {
@@ -1750,37 +1942,18 @@ nsWindowWatcher::CalculateChromeFlags(mo
     }
   }
 
   /* missing
      chromeFlags->copy_history
    */
 
   // Check security state for use in determing window dimensions
-  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;
+  if (!aHasChromeParent) {
+    chromeFlags = EnsureFlagsSafeForContent(chromeFlags, aChromeURL);
   }
 
   // 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;
   }
--- a/embedding/components/windowwatcher/nsWindowWatcher.h
+++ b/embedding/components/windowwatcher/nsWindowWatcher.h
@@ -77,33 +77,33 @@ 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 CalculateChromeFlags(mozIDOMWindowProxy* aParent,
-                                       const nsACString& aFeatures,
-                                       bool aFeaturesSpecified,
-                                       bool aDialog,
-                                       bool aChromeURL,
-                                       bool aHasChromeParent,
-                                       bool aCalledFromJS,
-                                       bool aOpenedFromRemoteTab);
+  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,
                               int32_t aDefault, bool* aPresenceFlag);
   /* Compute the right SizeSpec based on aFeatures */
   static void CalcSizeSpec(const nsACString& aFeatures, SizeSpec& aResult);
   static nsresult ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
                                           nsPIDOMWindowOuter* aParent,
                                           bool aWindowIsNew,
                                           mozIDOMWindowProxy** aOpenedWindow);
@@ -112,16 +112,27 @@ protected:
                                      bool aIsCallerChrome,
                                      const SizeSpec& aSizeSpec,
                                      float* aOpenerFullZoom);
   static void GetWindowTreeItem(mozIDOMWindowProxy* aWindow,
                                 nsIDocShellTreeItem** aResult);
   static void GetWindowTreeOwner(nsPIDOMWindowOuter* aWindow,
                                  nsIDocShellTreeOwner** aResult);
 
+private:
+  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