Bug 1267720 - Factor out logic for creating windows for content processes from OpenWindowInternal draft
authorMike Conley <mconley@mozilla.com>
Wed, 27 Apr 2016 16:19:37 -0400
changeset 363509 e9c4b41f05afe59ba95b658959065980b23bb843
parent 363508 46b192cdb154353127ea249bb03d90a013e76444
child 520055 4c9a721e1b9bd663c40eb0a70dd5f60cb0bc8edf
push id17222
push usermconley@mozilla.com
push dateWed, 04 May 2016 21:02:55 +0000
bugs1267720
milestone49.0a1
Bug 1267720 - Factor out logic for creating windows for content processes from OpenWindowInternal MozReview-Commit-ID: 1dhGthT8bmu
dom/ipc/ContentParent.cpp
embedding/components/windowwatcher/moz.build
embedding/components/windowwatcher/nsPIWindowWatcher.idl
embedding/components/windowwatcher/nsWindowWatcher.cpp
embedding/components/windowwatcher/nsWindowWatcher.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -5415,23 +5415,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;
@@ -5517,47 +5510,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, name, 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->OpenWindowForTablessContent(getter_AddRefs(newRemoteTab));
+  } else {
+    *aResult = pwwatch->OpenWindowForTabContent(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/embedding/components/windowwatcher/moz.build
+++ b/embedding/components/windowwatcher/moz.build
@@ -37,8 +37,10 @@ if CONFIG['MOZ_XUL']:
     ]
 
 FINAL_LIBRARY = 'xul'
 # For nsJSUtils
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
 ]
+
+include('/ipc/chromium/chromium-config.mozbuild')
--- a/embedding/components/windowwatcher/nsPIWindowWatcher.idl
+++ b/embedding/components/windowwatcher/nsPIWindowWatcher.idl
@@ -77,16 +77,47 @@ interface nsPIWindowWatcher : nsISupport
                                  in boolean aCalledFromScript,
                                  in boolean aDialog,
                                  in boolean aNavigate,
                                  in nsITabParent aOpeningTab,
                                  in nsISupports aArgs,
                                  [optional] in float aOpenerFullZoom);
 
   /**
+   * Used by the Service Worker Client.openWindow API. This allows notification
+   * handlers to open new top-level windows.
+   *
+   * @return the nsITabParent of the initial browser for the newly opened
+   *         window.
+   */
+  nsITabParent openWindowForTablessContent();
+
+  /**
+   * This should only be called if a content process has requested that
+   * a new window be opened.
+   *
+   * @param aOpeningTab
+   *        The nsITabParent that is requesting the new window be opened.
+   * @param aFeatures
+   *        Window features if called with window.open.
+   * @param aCalledFromJS
+   *        True if called via window.open.
+   * @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 openWindowForTabContent(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,17 @@
 #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"
 
 #ifdef USEWEAKREFS
 #include "nsIWeakReference.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
@@ -478,16 +479,253 @@ CheckUserContextCompatibility(nsIDocShel
 
   uint32_t principalUserContextId;
   nsresult rv = subjectPrincipal->GetUserContextId(&principalUserContextId);
   NS_ENSURE_SUCCESS(rv, false);
 
   return principalUserContextId == userContextId;
 }
 
+
+NS_IMETHODIMP
+nsWindowWatcher::OpenWindowForTablessContent(nsITabParent** aResult)
+{
+  MOZ_ASSERT(XRE_IsParentProcess());
+  MOZ_ASSERT(mWindowCreator);
+
+  if (!nsContentUtils::IsSafeToRunScript()) {
+    nsContentUtils::WarnScriptWasIgnored(nullptr);
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsPIDOMWindowOuter> 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 =
+    CalculateChromeFlagsForContent(EmptyCString(), true);
+
+  chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
+
+  bool cancel = false;
+  nsCOMPtr<nsIWebBrowserChrome> parentChrome(do_GetInterface(parentTreeOwner));
+  nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
+
+  nsresult rv =
+    windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags, contextFlags,
+                                        nullptr, &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<nsILoadContext> chromeContext = do_QueryInterface(chromeTreeItem);
+  if (NS_WARN_IF(!chromeContext)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  nsCOMPtr<nsIDocShellTreeOwner> chromeTreeOwner;
+  chromeTreeItem->GetTreeOwner(getter_AddRefs(chromeTreeOwner));
+  if (NS_WARN_IF(!chromeTreeOwner)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  bool isPrivateBrowsingWindow =
+    Preferences::GetBool("browser.privatebrowsing.autostart");
+
+  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);
+
+  SizeSpec sizeSpec;
+  CalcSizeSpec(EmptyCString().get(), sizeSpec);
+  float fullZoom = 1.0f;
+  SizeOpenedDocShellItem(chromeTreeItem, parentWindowOuter, false, sizeSpec,
+                         &fullZoom);
+
+  nsCOMPtr<nsITabParent> newTabParent;
+  chromeTreeOwner->GetPrimaryTabParent(getter_AddRefs(newTabParent));
+  if (NS_WARN_IF(!newTabParent)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  newTabParent.forget(aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsWindowWatcher::OpenWindowForTabContent(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(!aOpeningTabParent)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  if (NS_WARN_IF(!mWindowCreator)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // 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);
+
+  nsCOMPtr<nsPIDOMWindowOuter> parentWindowOuter =
+    openingTab->GetParentWindowOuter();
+
+  if (!parentWindowOuter) {
+    // We couldn't find a browser window for the opener, so either
+    // it's been 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));
+
+  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.get(), "mozDisplayId", 0, nullptr);
+  windowCreator2->SetScreenId(retval);
+#endif
+
+  nsAutoCString features(aFeatures);
+  uint32_t chromeFlags =
+    CalculateChromeFlagsForContent(features, aCalledFromJS);
+  // TODO: Always make remote yo
+  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;
+  }
+
+  if (PL_strcasestr(features.get(), "width=") ||
+      PL_strcasestr(features.get(), "height=")) {
+    chromeTreeOwner->SetPersistence(false, false, false);
+  }
+
+  nsCOMPtr<nsILoadContext> chromeContext = do_QueryInterface(chromeTreeItem);
+  if (NS_WARN_IF(!chromeContext)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  bool isPrivateBrowsingWindow =
+    Preferences::GetBool("browser.privatebrowsing.autostart");
+
+  // Otherwise, propagate the privacy status of the parent window, if
+  // available, to the child.
+  if (!isPrivateBrowsingWindow) {
+    nsCOMPtr<nsIDocShellTreeItem> parentItem;
+    GetWindowTreeItem(parentWindowOuter, getter_AddRefs(parentItem));
+    nsCOMPtr<nsILoadContext> parentContext = do_QueryInterface(parentItem);
+    if (parentContext) {
+      isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing();
+    }
+  }
+  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);
+
+  SizeSpec sizeSpec;
+  CalcSizeSpec(features.get(), 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,
@@ -827,19 +1065,18 @@ nsWindowWatcher::OpenWindowInternal(mozI
 #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));
+                                                 contextFlags, 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));
       }
@@ -1541,16 +1778,86 @@ nsWindowWatcher::URIfromURL(const char* 
   if (forceEnable && !(aDialog && !openedFromContentScript) &&                 \
       !(!openedFromContentScript && aHasChromeParent) && !aChromeURL) {                  \
     chromeFlags |= flag;                                                       \
   } else {                                                                     \
     chromeFlags |=                                                             \
       WinHasOption(aFeatures, feature, 0, &presenceFlag) ? flag : 0;           \
   }
 
+#define NS_CALCULATE_CHROME_FLAG_FOR_CONTENT(feature, flag)                    \
+  prefBranch->GetBoolPref(feature, &forceEnable);                              \
+  if (forceEnable) {                                                           \
+    chromeFlags |= flag;                                                       \
+  } else {                                                                     \
+    chromeFlags |=                                                             \
+      WinHasOption(aFeatures.BeginReading(), feature, 0, &presenceFlag) ? flag : 0;           \
+  }
+
+
+// static
+uint32_t
+nsWindowWatcher::CalculateChromeFlagsForContent(const nsACString& aFeatures,
+                                                bool aCalledFromJS)
+{
+  if (aFeatures.IsEmpty()) {
+    return nsIWebBrowserChrome::CHROME_ALL;
+  }
+
+  uint32_t chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
+
+  nsresult rv;
+  nsCOMPtr<nsIPrefBranch> prefBranch;
+  nsCOMPtr<nsIPrefService> prefs =
+    do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+  // TODO: Figure out error handling here...
+  NS_ENSURE_SUCCESS(rv, 0);
+
+  rv = prefs->GetBranch("dom.disable_window_open_feature.",
+                        getter_AddRefs(prefBranch));
+
+  NS_ENSURE_SUCCESS(rv, 0);
+
+  bool forceEnable = false;
+  bool presenceFlag = false;
+
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("titlebar",
+                               nsIWebBrowserChrome::CHROME_TITLEBAR);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("close",
+                               nsIWebBrowserChrome::CHROME_WINDOW_CLOSE);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("toolbar",
+                               nsIWebBrowserChrome::CHROME_TOOLBAR);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("location",
+                               nsIWebBrowserChrome::CHROME_LOCATIONBAR);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("personalbar",
+                               nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("status",
+                               nsIWebBrowserChrome::CHROME_STATUSBAR);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("menubar",
+                               nsIWebBrowserChrome::CHROME_MENUBAR);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("scrollbars",
+                               nsIWebBrowserChrome::CHROME_SCROLLBARS);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("resizable",
+                               nsIWebBrowserChrome::CHROME_WINDOW_RESIZE);
+  NS_CALCULATE_CHROME_FLAG_FOR_CONTENT("minimizable",
+                               nsIWebBrowserChrome::CHROME_WINDOW_MIN);
+
+  chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
+  chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
+
+  chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
+  chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
+  chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_POPUP;
+  chromeFlags &= ~(nsIWebBrowserChrome::CHROME_MODAL |
+                   nsIWebBrowserChrome::CHROME_OPENAS_CHROME);
+  chromeFlags &= ~nsIWebBrowserChrome::CHROME_DEPENDENT;
+
+  return chromeFlags;
+}
+
 /**
  * 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
--- a/embedding/components/windowwatcher/nsWindowWatcher.h
+++ b/embedding/components/windowwatcher/nsWindowWatcher.h
@@ -86,16 +86,19 @@ protected:
                               nsIArray* aArgv,
                               float* aOpenerFullZoom,
                               mozIDOMWindowProxy** aResult);
 
   static nsresult URIfromURL(const char* aURL,
                              mozIDOMWindowProxy* aParent,
                              nsIURI** aURI);
 
+  static uint32_t CalculateChromeFlagsForContent(const nsACString& aFeaturesStr,
+                                                 bool aCalledFromJS);
+
   static uint32_t CalculateChromeFlags(mozIDOMWindowProxy* aParent,
                                        const char* aFeatures,
                                        bool aFeaturesSpecified,
                                        bool aDialog,
                                        bool aChromeURL,
                                        bool aHasChromeParent,
                                        bool aCalledFromJS,
                                        bool aOpenedFromRemoteTab);