Bug 1021466 - Part 2: Make it possible to pass in an nsITabParent when opening windows, and then stash that nsITabParent in the newly created chrome docshell. r=smaug.
authorMike Conley <mconley@mozilla.com>
Thu, 05 Jun 2014 22:51:14 -0400
changeset 206435 ad9adc4900df4d6d257cfc3118d9889138b5ca1d
parent 206434 522ef2feb676d358e06e622700d330bd6fadc737
child 206436 779ef393fd2e1212159547605341d545a1e02d05
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1021466 - Part 2: Make it possible to pass in an nsITabParent when opening windows, and then stash that nsITabParent in the newly created chrome docshell. r=smaug.
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -11639,17 +11639,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(this, url.get(), name_ptr, options_ptr,
                                 /* aCalledFromScript = */ true,
-                                aDialog, aNavigate, argv,
+                                aDialog, aNavigate, nullptr, argv,
     } 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
@@ -11659,17 +11659,17 @@ nsGlobalWindow::OpenInternal(const nsASt
       Maybe<AutoNoJSAPI> nojsapi;
       if (!aContentModal) {
       rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
                                 /* aCalledFromScript = */ false,
-                                aDialog, aNavigate, aExtraArgument,
+                                aDialog, aNavigate, nullptr, aExtraArgument,
   // success!
--- a/embedding/base/nsIWindowCreator2.idl
+++ b/embedding/base/nsIWindowCreator2.idl
@@ -12,20 +12,21 @@
  * @see nsIWindowCreator
  * @see nsIWindowWatcher
  * @status
 #include "nsIWindowCreator.idl"
+interface nsITabParent;
 interface nsIURI;
 interface nsIWebBrowserChrome;
-[scriptable, uuid(f673ec81-a4b0-11d6-964b-eb5a2bf216fc)]
+[scriptable, uuid(e28f810b-9b49-4927-a4be-62a74fadfe21)]
 interface nsIWindowCreator2 : nsIWindowCreator {
    * Definitions for contextFlags
   // Likely that the window is an advertising popup. 
@@ -39,20 +40,23 @@ interface nsIWindowCreator2 : nsIWindowC
                     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);
--- a/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl
+++ b/embedding/components/windowwatcher/public/nsPIWindowWatcher.idl
@@ -10,18 +10,19 @@
 #include "nsISupports.idl"
 interface nsIDOMWindow;
 interface nsISimpleEnumerator;
 interface nsIWebBrowserChrome;
 interface nsIDocShellTreeItem;
 interface nsIArray;
+interface nsITabParent;
 interface nsPIWindowWatcher : nsISupports
   /** A window has been created. Add it to our list.
       @param aWindow the window to add
       @param aChrome the corresponding chrome window. The DOM window
                      and chrome will be mapped together, and the corresponding
                      chrome can be retrieved using the (not private)
@@ -46,31 +47,35 @@ 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
       @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
             window named aName.
       @note This method should try to set the default charset for the new
             window to the default charset of the document in the calling window
             (which is determined based on the JS stack and the value of
             aParent).  This is not guaranteed, however.
   nsIDOMWindow openWindow2(in nsIDOMWindow aParent, in string aUrl,
                            in string aName, in string aFeatures,
                            in boolean aCalledFromScript, in boolean aDialog,
-                           in boolean aNavigate, in nsISupports aArgs);
+                           in boolean aNavigate, in nsITabParent aOpeningTab,
+                           in nsISupports aArgs);
    * 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.
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
@@ -337,17 +337,17 @@ nsWindowWatcher::OpenWindow(nsIDOMWindow
   uint32_t argc = 0;
   if (argv) {
   bool dialog = (argc != 0);
   return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
                             /* calledFromJS = */ false, dialog,
-                            /* navigate = */ true, argv, _retval);
+                            /* navigate = */ true, nullptr, argv, _retval);
 struct SizeSpec {
   SizeSpec() :
@@ -389,16 +389,17 @@ struct SizeSpec {
 nsWindowWatcher::OpenWindow2(nsIDOMWindow *aParent,
                               const char *aUrl,
                               const char *aName,
                               const char *aFeatures,
                               bool aCalledFromScript,
                               bool aDialog,
                               bool aNavigate,
+                              nsITabParent *aOpeningTab,
                               nsISupports *aArguments,
                               nsIDOMWindow **_retval)
   nsCOMPtr<nsIArray> argv = ConvertArgsToArray(aArguments);
   uint32_t argc = 0;
   if (argv) {
@@ -409,27 +410,28 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindo
   // 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, _retval);
+                            aNavigate, aOpeningTab, argv, _retval);
 nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent,
                                     const char *aUrl,
                                     const char *aName,
                                     const char *aFeatures,
                                     bool aCalledFromJS,
                                     bool aDialog,
                                     bool aNavigate,
+                                    nsITabParent *aOpeningTab,
                                     nsIArray *argv,
                                     nsIDOMWindow **_retval)
   nsresult                        rv = NS_OK;
   bool                            nameSpecified,
                                   isNewToplevelWindow = false,
                                   windowIsNew = false,
@@ -693,17 +695,17 @@ nsWindowWatcher::OpenWindowInternal(nsID
         if (popupConditions)
           contextFlags |= nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT;
         bool cancel = false;
         rv = windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags,
                                                  contextFlags, uriToLoad,
-                                                 &cancel,
+                                                 aOpeningTab, &cancel,
         if (NS_SUCCEEDED(rv) && cancel) {
           newChrome = 0; // just in case
           rv = NS_ERROR_ABORT;
         rv = mWindowCreator->CreateChromeWindow(parentChrome, chromeFlags,
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.h
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.h
@@ -10,16 +10,17 @@
  {0xa21bfa01, 0xf349, 0x4394, {0xa8, 0x4c, 0x8d, 0xe5, 0xcf, 0x7, 0x37, 0xd0}}
 #include "nsCOMPtr.h"
 #include "mozilla/Mutex.h"
 #include "nsIWindowCreator.h" // for stupid compilers
 #include "nsIWindowWatcher.h"
 #include "nsIPromptFactory.h"
+#include "nsITabParent.h"
 #include "nsPIWindowWatcher.h"
 #include "nsTArray.h"
 #include "js/TypeDecls.h"
 class  nsIURI;
 class  nsIDocShellTreeItem;
 class  nsIDocShellTreeOwner;
 class nsPIDOMWindow;
@@ -72,16 +73,17 @@ protected:
   // (which means called from script) or called via OpenWindow.
   nsresult OpenWindowInternal(nsIDOMWindow *aParent,
                               const char *aUrl,
                               const char *aName,
                               const char *aFeatures,
                               bool aCalledFromJS,
                               bool aDialog,
                               bool aNavigate,
+                              nsITabParent *aOpeningTab,
                               nsIArray *argv,
                               nsIDOMWindow **_retval);
   static JSContext *GetJSContextFromWindow(nsIDOMWindow *aWindow);
   static nsresult   URIfromURL(const char *aURL,
                                nsIDOMWindow *aParent,
                                nsIURI **aURI);
--- a/toolkit/components/startup/nsAppStartup.cpp
+++ b/toolkit/components/startup/nsAppStartup.cpp
@@ -607,29 +607,30 @@ nsAppStartup::GetInterrupted(bool *aInte
 nsAppStartup::CreateChromeWindow(nsIWebBrowserChrome *aParent,
                                  uint32_t aChromeFlags,
                                  nsIWebBrowserChrome **_retval)
   bool cancel;
-  return CreateChromeWindow2(aParent, aChromeFlags, 0, 0, &cancel, _retval);
+  return CreateChromeWindow2(aParent, aChromeFlags, 0, 0, nullptr, &cancel, _retval);
 // nsAppStartup->nsIWindowCreator2
 nsAppStartup::CreateChromeWindow2(nsIWebBrowserChrome *aParent,
                                   uint32_t aChromeFlags,
                                   uint32_t aContextFlags,
                                   nsIURI *aURI,
+                                  nsITabParent *aOpeningTab,
                                   bool *aCancel,
                                   nsIWebBrowserChrome **_retval)
   *aCancel = false;
   *_retval = 0;
@@ -639,33 +640,34 @@ nsAppStartup::CreateChromeWindow2(nsIWeb
   nsCOMPtr<nsIXULWindow> newWindow;
   if (aParent) {
     nsCOMPtr<nsIXULWindow> xulParent(do_GetInterface(aParent));
     NS_ASSERTION(xulParent, "window created using non-XUL parent. that's unexpected, but may work.");
     if (xulParent)
-      xulParent->CreateNewWindow(aChromeFlags, getter_AddRefs(newWindow));
+      xulParent->CreateNewWindow(aChromeFlags, aOpeningTab, getter_AddRefs(newWindow));
     // And if it fails, don't try again without a parent. It could fail
     // intentionally (bug 115969).
   } else { // try using basic methods:
     /* You really shouldn't be making dependent windows without a parent.
       But unparented modal (and therefore dependent) windows happen
       in our codebase, so we allow it after some bellyaching: */
     if (aChromeFlags & nsIWebBrowserChrome::CHROME_DEPENDENT)
       NS_WARNING("dependent window created without a parent");
     nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
     if (!appShell)
       return NS_ERROR_FAILURE;
     appShell->CreateTopLevelWindow(0, 0, aChromeFlags,
+                                   aOpeningTab,
   // if anybody gave us anything to work with, use it
   if (newWindow) {
     nsCOMPtr<nsIInterfaceRequestor> thing(do_QueryInterface(newWindow));
     if (thing)
--- a/widget/tests/TestAppShellSteadyState.cpp
+++ b/widget/tests/TestAppShellSteadyState.cpp
@@ -402,17 +402,17 @@ Test4Internal(nsIAppShell* aAppShell)
   if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), "about:", nullptr))) {
     fail("Failed to create new uri");
     return false;
   uint32_t flags = nsIWebBrowserChrome::CHROME_DEFAULT;
   nsCOMPtr<nsIXULWindow> xulWindow;
-  if (NS_FAILED(appService->CreateTopLevelWindow(nullptr, uri, flags, 100, 100,
+  if (NS_FAILED(appService->CreateTopLevelWindow(nullptr, uri, flags, 100, 100, nullptr,
                                                  getter_AddRefs(xulWindow)))) {
     fail("Failed to create new window");
     return false;
   nsCOMPtr<nsIDOMWindow> window = do_GetInterface(xulWindow);
   if (!window) {
     fail("Can't get dom window!");
--- a/xpfe/appshell/public/nsIAppShellService.idl
+++ b/xpfe/appshell/public/nsIAppShellService.idl
@@ -5,24 +5,25 @@
 #include "nsISupports.idl"
 interface nsIXULWindow;
 interface nsIWebNavigation;
 interface nsIURI;
 interface nsIDOMWindow;
 interface nsIAppShell;
+interface nsITabParent;
 [ptr] native JSContext(JSContext);
 #include "js/TypeDecls.h"
-[scriptable, uuid(2fa2f813-c216-4efb-8a8c-de60108ce5e5)]
+[scriptable, uuid(41a2f0c6-3ca1-44f9-8efa-744a43aa399d)]
 interface nsIAppShellService : nsISupports
    * Create a window, which will be initially invisible.
    * @param aParent the parent window.  Can be null.
    * @param aUrl the contents of the new window.
    * @param aChromeMask chrome flags affecting the kind of OS border
    *                    given to the window. see nsIBrowserWindow for
@@ -30,24 +31,26 @@ interface nsIAppShellService : nsISuppor
    * @param aCallbacks interface providing C++ hooks for window initialization
    *                   before the window is made visible.  Can be null.
    *                   Deprecated.
    * @param aInitialWidth width, in pixels, of the window.  Width of window
    *                      at creation.  Can be overridden by the "width"
    *                      tag in the XUL.  Set to NS_SIZETOCONTENT to force
    *                      the window to wrap to its contents.
    * @param aInitialHeight like aInitialWidth, but subtly different.
-   * @param aResult the newly created window is returned here.
+   * @param aOpeningTab The TabParent that requested that this window be opened.
+   *                    Can be left null.
   const long SIZE_TO_CONTENT = -1;
   nsIXULWindow createTopLevelWindow(in nsIXULWindow aParent,
                                     in nsIURI aUrl, 
                                     in uint32_t aChromeMask,
                                     in long aInitialWidth,
-                                    in long aInitialHeight);
+                                    in long aInitialHeight,
+                                    in nsITabParent aOpeningTab);
    * This is the constructor for creating an invisible DocShell.
    * It is used to simulate DOM windows without an actual physical
    * representation.
    * @param aIsChrome Set true if you want to use it for chrome content.
   nsIWebNavigation createWindowlessBrowser([optional] in bool aIsChrome);
--- a/xpfe/appshell/public/nsIXULWindow.idl
+++ b/xpfe/appshell/public/nsIXULWindow.idl
@@ -11,18 +11,19 @@
  * When the window is destroyed, it will fire a "xul-window-destroyed"
  * notification through the global observer service.
 interface nsIDocShell;
 interface nsIDocShellTreeItem;
 interface nsIXULBrowserWindow;
+interface nsITabParent;
-[scriptable, uuid(CCF9E98A-E442-4061-9F74-94539DD9FE9E)]
+[scriptable, uuid(a68a40b9-f7df-47ff-a874-2af3df7eb888)]
 interface nsIXULWindow : nsISupports
    * The docshell owning the XUL for this window.
   readonly attribute nsIDocShell docShell;
@@ -103,19 +104,22 @@ interface nsIXULWindow : nsISupports
    * Begin assuming |chromeFlags| don't change hereafter, and assert
    * if they do change.  The state change is one-way and idempotent.
   void assumeChromeFlagsAreFrozen();
    * Create a new window.
    * @param aChromeFlags see nsIWebBrowserChrome
+   * @param aOpeningTab the TabParent that requested this new window be opened.
+   *                    Can be left null.
    * @return the newly minted window
-  nsIXULWindow createNewWindow(in int32_t aChromeFlags);
+  nsIXULWindow createNewWindow(in int32_t aChromeFlags,
+                               in nsITabParent aOpeningTab);
   attribute nsIXULBrowserWindow XULBrowserWindow;
    * 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.
--- a/xpfe/appshell/src/nsAppShellService.cpp
+++ b/xpfe/appshell/src/nsAppShellService.cpp
@@ -122,27 +122,27 @@ nsAppShellService::CreateHiddenWindowHel
   nsCOMPtr<nsIURI> url;
   rv = NS_NewURI(getter_AddRefs(url), hiddenWindowURL);
   nsRefPtr<nsWebShellWindow> newWindow;
   if (!aIsPrivate) {
     rv = JustCreateTopWindow(nullptr, url,
                              chromeMask, initialWidth, initialHeight,
-                             true, getter_AddRefs(newWindow));
+                             true, nullptr, getter_AddRefs(newWindow));
     NS_ENSURE_SUCCESS(rv, rv);
   } else {
     // Create the hidden private window
     chromeMask |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
     rv = JustCreateTopWindow(nullptr, url,
                              chromeMask, initialWidth, initialHeight,
-                             true, getter_AddRefs(newWindow));
+                             true, nullptr, getter_AddRefs(newWindow));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocShell> docShell;
     if (docShell) {
@@ -176,27 +176,28 @@ nsAppShellService::DestroyHiddenWindow()
  * Create a new top level window and display the given URL within it...
 nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
                                         nsIURI *aUrl, 
                                         uint32_t aChromeMask,
                                         int32_t aInitialWidth,
                                         int32_t aInitialHeight,
+                                        nsITabParent *aOpeningTab,
                                         nsIXULWindow **aResult)
   nsresult rv;
   nsWebShellWindow *newWindow = nullptr;
   rv = JustCreateTopWindow(aParent, aUrl,
                            aChromeMask, aInitialWidth, aInitialHeight,
-                           false, &newWindow);  // addrefs
+                           false, aOpeningTab, &newWindow);  // addrefs
   *aResult = newWindow; // transfer ref
   if (NS_SUCCEEDED(rv)) {
     // the addref resulting from this is the owning addref for this window
     nsCOMPtr<nsIXULWindow> parent;
     if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
@@ -477,21 +478,22 @@ CheckForFullscreenWindow()
  * Just do the window-making part of CreateTopLevelWindow
 nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
-                                       nsIURI *aUrl, 
+                                       nsIURI *aUrl,
                                        uint32_t aChromeMask,
                                        int32_t aInitialWidth,
                                        int32_t aInitialHeight,
                                        bool aIsHiddenWindow,
+                                       nsITabParent *aOpeningTab,
                                        nsWebShellWindow **aResult)
   *aResult = nullptr;
   nsCOMPtr<nsIXULWindow> parent;
   if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
     parent = aParent;
@@ -592,17 +594,17 @@ nsAppShellService::JustCreateTopWindow(n
     bool isRTL = false;
     reg->IsLocaleRTL(package, &isRTL);
     widgetInitData.mRTL = isRTL;
   nsresult rv = window->Initialize(parent, center ? aParent : nullptr,
                                    aUrl, aInitialWidth, aInitialHeight,
-                                   aIsHiddenWindow, widgetInitData);
+                                   aIsHiddenWindow, aOpeningTab, widgetInitData);
   // Enforce the Private Browsing autoStart pref first.
   bool isPrivateBrowsingWindow =
   if (aChromeMask & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW) {
     // Caller requested a private window
--- a/xpfe/appshell/src/nsAppShellService.h
+++ b/xpfe/appshell/src/nsAppShellService.h
@@ -8,16 +8,17 @@
 #include "nsIAppShellService.h"
 #include "nsIObserver.h"
 //Interfaces Needed
 #include "nsWebShellWindow.h"
 #include "nsStringFwd.h"
 #include "nsAutoPtr.h"
+#include "nsITabParent.h"
 #include "mozilla/Attributes.h"
 // {0099907D-123C-4853-A46A-43098B5FB68C}
 { 0x99907d, 0x123c, 0x4853, { 0xa4, 0x6a, 0x43, 0x9, 0x8b, 0x5f, 0xb6, 0x8c } }
 class nsAppShellService MOZ_FINAL : public nsIAppShellService,
                                     public nsIObserver
@@ -31,20 +32,21 @@ public:
   nsresult CreateHiddenWindowHelper(bool aIsPrivate);
   void EnsurePrivateHiddenWindow();
   nsresult JustCreateTopWindow(nsIXULWindow *aParent,
-                               nsIURI *aUrl, 
+                               nsIURI *aUrl,
                                uint32_t aChromeMask,
                                int32_t aInitialWidth, int32_t aInitialHeight,
                                bool aIsHiddenWindow,
+                               nsITabParent *aOpeningTab,
                                nsWebShellWindow **aResult);
   uint32_t CalculateWindowZLevel(nsIXULWindow *aParent, uint32_t aChromeMask);
   nsRefPtr<nsWebShellWindow>  mHiddenWindow;
   nsRefPtr<nsWebShellWindow>  mHiddenPrivateWindow;
   bool                        mXPCOMWillShutDown;
   bool                        mXPCOMShuttingDown;
   uint16_t                    mModalWindowCount;
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -106,16 +106,17 @@ NS_INTERFACE_MAP_BEGIN(nsWebShellWindow)
 nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent,
                                       nsIXULWindow* aOpener,
                                       nsIURI* aUrl,
                                       int32_t aInitialWidth,
                                       int32_t aInitialHeight,
                                       bool aIsHiddenWindow,
+                                      nsITabParent *aOpeningTab,
                                       nsWidgetInitData& widgetInitData)
   nsresult rv;
   nsCOMPtr<nsIWidget> parentWidget;
   mIsHiddenWindow = aIsHiddenWindow;
   int32_t initialX = 0, initialY = 0;
@@ -178,16 +179,18 @@ nsresult nsWebShellWindow::Initialize(ns
   // Match the default background color of content. Important on windows
   // since we no longer use content child widgets.
   // Create web shell
   mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
+  mDocShell->SetOpener(aOpeningTab);
   // Make sure to set the item type on the docshell _before_ calling
   // Create() so it knows what type it is.
   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
--- a/xpfe/appshell/src/nsWebShellWindow.h
+++ b/xpfe/appshell/src/nsWebShellWindow.h
@@ -7,16 +7,17 @@
 #define nsWebShellWindow_h__
 #include "mozilla/Mutex.h"
 #include "nsIWebProgressListener.h"
 #include "nsITimer.h"
 #include "nsCOMPtr.h"
 #include "nsXULWindow.h"
 #include "nsIWidgetListener.h"
+#include "nsITabParent.h"
 /* Forward declarations.... */
 class nsIURI;
 struct nsWidgetInitData;
 namespace mozilla {
 class WebShellWindowTimerCallback;
@@ -32,16 +33,17 @@ public:
   // nsISupports interface...
   // nsWebShellWindow methods...
   nsresult Initialize(nsIXULWindow * aParent, nsIXULWindow * aOpener,
                       nsIURI* aUrl,
                       int32_t aInitialWidth, int32_t aInitialHeight,
                       bool aIsHiddenWindow,
+                      nsITabParent *aOpeningTab,
                       nsWidgetInitData& widgetInitData);
   nsresult Toolbar();
   // nsIWebProgressListener
   // nsIBaseWindow
--- a/xpfe/appshell/src/nsXULWindow.cpp
+++ b/xpfe/appshell/src/nsXULWindow.cpp
@@ -1709,48 +1709,52 @@ NS_IMETHODIMP nsXULWindow::ExitModalLoop
   mContinueModalLoop = false;
   mModalStatus = aStatus;
   return NS_OK;
 // top-level function to create a new window
 NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags,
-                             nsIXULWindow **_retval)
+                                           nsITabParent *aOpeningTab,
+                                           nsIXULWindow **_retval)
   if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
-    return CreateNewChromeWindow(aChromeFlags, _retval);
-  return CreateNewContentWindow(aChromeFlags, _retval);
+    return CreateNewChromeWindow(aChromeFlags, aOpeningTab, _retval);
+  return CreateNewContentWindow(aChromeFlags, aOpeningTab, _retval);
 NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags,
+                                                 nsITabParent *aOpeningTab,
                                                  nsIXULWindow **_retval)
   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
   // Just do a normal create of a window and return.
   nsCOMPtr<nsIXULWindow> newWindow;
   appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags,
+                                 aOpeningTab,
   *_retval = newWindow;
   return NS_OK;
 NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
+                                                  nsITabParent *aOpeningTab,
                                                   nsIXULWindow **_retval)
   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
   // We need to create a new top level window and then enter a nested
   // loop. Eventually the new window will be told that it has loaded,
   // at which time we know it is safe to spin out of the nested loop
@@ -1773,16 +1777,17 @@ NS_IMETHODIMP nsXULWindow::CreateNewCont
   // to pass back. The subject principal needs to be system while we're creating
   // it to make things work right, so force a system caller. See bug 799348
   // comment 13 for a description of what happens when we don't.
   nsCOMPtr<nsIXULWindow> newWindow;
     AutoNoJSAPI nojsapi;
     appShell->CreateTopLevelWindow(this, uri,
                                    aChromeFlags, 615, 480,
+                                   aOpeningTab,
   // Specify that we want the window to remain locked until the chrome has loaded.
   nsXULWindow *xulWin = static_cast<nsXULWindow*>
@@ -1793,17 +1798,26 @@ NS_IMETHODIMP nsXULWindow::CreateNewCont
     AutoNoJSAPI nojsapi;
     nsIThread *thread = NS_GetCurrentThread();
     while (xulWin->IsLocked()) {
       if (!NS_ProcessNextEvent(thread))
-  NS_ENSURE_STATE(xulWin->mPrimaryContentShell);
+  // If aOpeningTab is not null, it means that we're creating a new window
+  // with a remote browser, which doesn't have a primary docshell. In that
+  // case, we check for the chrome window docshell and make sure that a new
+  // remote tab was opened and stashed in that docshell.
+  if (aOpeningTab) {
+    NS_ENSURE_STATE(xulWin->mDocShell);
+    NS_ENSURE_STATE(xulWin->mDocShell->GetOpenedRemote());
+  } else {
+    NS_ENSURE_STATE(xulWin->mPrimaryContentShell);
+  }
   *_retval = newWindow;
   return NS_OK;
 void nsXULWindow::EnableParent(bool aEnable)
--- a/xpfe/appshell/src/nsXULWindow.h
+++ b/xpfe/appshell/src/nsXULWindow.h
@@ -27,16 +27,17 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIXULWindow.h"
 #include "nsIPrompt.h"
 #include "nsIAuthPrompt.h"
 #include "nsIXULBrowserWindow.h"
 #include "nsIWeakReference.h"
 #include "nsIWidgetListener.h"
+#include "nsITabParent.h"
 namespace mozilla {
 namespace dom {
 class Element;
 // nsXULWindow
@@ -103,18 +104,18 @@ protected:
    // 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 SizeShellTo(nsIDocShellTreeItem* aShellItem, int32_t aCX, 
       int32_t aCY);
    NS_IMETHOD ExitModalLoop(nsresult aStatus);
-   NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsIXULWindow **_retval);
-   NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsIXULWindow **_retval);
+   NS_IMETHOD CreateNewChromeWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval);
+   NS_IMETHOD CreateNewContentWindow(int32_t aChromeFlags, nsITabParent* aOpeningTab, nsIXULWindow **_retval);
    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();