Bug 1420702 - Propagate referrer policy when creating window from pinned tab draft
authorThomas Nguyen <tnguyen@mozilla.com>
Thu, 30 Nov 2017 21:42:05 +0800
changeset 705764 5f743807bddbd44f9ab464054cf94afc21c24b19
parent 704807 cb9092a90f6ef501e6de8eb5fc6ce19e2717193f
child 705765 acc27f9939d9baabc65054ef32e36c1f90e60bc7
push id91569
push userbmo:tnguyen@mozilla.com
push dateThu, 30 Nov 2017 16:29:58 +0000
bugs1420702
milestone59.0a1
Bug 1420702 - Propagate referrer policy when creating window from pinned tab MozReview-Commit-ID: 1kMssKbAm1l
dom/base/nsOpenURIInFrameParams.cpp
dom/base/nsOpenURIInFrameParams.h
dom/interfaces/base/nsIBrowserDOMWindow.idl
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
dom/ipc/TabChild.cpp
toolkit/components/windowcreator/nsIWindowProvider.idl
toolkit/components/windowwatcher/nsWindowWatcher.cpp
xpfe/appshell/nsContentTreeOwner.cpp
--- a/dom/base/nsOpenURIInFrameParams.cpp
+++ b/dom/base/nsOpenURIInFrameParams.cpp
@@ -2,31 +2,33 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsOpenURIInFrameParams.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/dom/ToJSValue.h"
+#include "mozilla/net/ReferrerPolicy.h"
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsOpenURIInFrameParams)
   NS_INTERFACE_MAP_ENTRY(nsIOpenURIInFrameParams)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION(nsOpenURIInFrameParams, mOpenerBrowser)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsOpenURIInFrameParams)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsOpenURIInFrameParams)
 
 nsOpenURIInFrameParams::nsOpenURIInFrameParams(const mozilla::OriginAttributes& aOriginAttributes,
                                                nsIFrameLoaderOwner* aOpener)
   : mOpenerOriginAttributes(aOriginAttributes)
   , mOpenerBrowser(aOpener)
+  , mReferrerPolicy(mozilla::net::RP_Unset)
 {
 }
 
 nsOpenURIInFrameParams::~nsOpenURIInFrameParams() {
 }
 
 NS_IMETHODIMP
 nsOpenURIInFrameParams::GetReferrer(nsAString& aReferrer)
@@ -37,16 +39,31 @@ nsOpenURIInFrameParams::GetReferrer(nsAS
 
 NS_IMETHODIMP
 nsOpenURIInFrameParams::SetReferrer(const nsAString& aReferrer)
 {
   mReferrer = aReferrer;
   return NS_OK;
 }
 
+
+NS_IMETHODIMP
+nsOpenURIInFrameParams::GetReferrerPolicy(uint32_t* aReferrerPolicy)
+{
+  *aReferrerPolicy = mReferrerPolicy;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsOpenURIInFrameParams::SetReferrerPolicy(uint32_t aReferrerPolicy)
+{
+  mReferrerPolicy = aReferrerPolicy;
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsOpenURIInFrameParams::GetIsPrivate(bool* aIsPrivate)
 {
   NS_ENSURE_ARG_POINTER(aIsPrivate);
   *aIsPrivate = mOpenerOriginAttributes.mPrivateBrowsingId > 0;
   return NS_OK;
 }
 
--- a/dom/base/nsOpenURIInFrameParams.h
+++ b/dom/base/nsOpenURIInFrameParams.h
@@ -25,10 +25,11 @@ public:
                                   nsIFrameLoaderOwner* aOpener);
 
 private:
   ~nsOpenURIInFrameParams();
 
   mozilla::OriginAttributes mOpenerOriginAttributes;
   nsCOMPtr<nsIFrameLoaderOwner> mOpenerBrowser;
   nsString mReferrer;
+  uint32_t mReferrerPolicy;
   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
 };
--- a/dom/interfaces/base/nsIBrowserDOMWindow.idl
+++ b/dom/interfaces/base/nsIBrowserDOMWindow.idl
@@ -10,16 +10,17 @@ interface nsIDOMWindow;
 interface nsIURI;
 interface nsIFrameLoaderOwner;
 interface nsIPrincipal;
 
 [scriptable, uuid(e774db14-79ac-4156-a7a3-aa3fd0a22c10)]
 interface nsIOpenURIInFrameParams : nsISupports
 {
   attribute DOMString referrer;
+  attribute unsigned long referrerPolicy;
   readonly attribute boolean isPrivate;
   attribute nsIPrincipal triggeringPrincipal;
 
   // The browser or frame element in the parent process which holds the
   // opener window in the content process. May be null.
   readonly attribute nsIFrameLoaderOwner openerBrowser;
 
   [implicit_jscontext]
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -97,16 +97,17 @@
 #include "mozilla/Sandbox.h"
 #endif
 #endif
 
 #include "mozilla/Unused.h"
 
 #include "mozInlineSpellChecker.h"
 #include "nsDocShell.h"
+#include "nsIDocShellLoadInfo.h"
 #include "nsIConsoleListener.h"
 #include "nsIContentViewer.h"
 #include "nsICycleCollectorListener.h"
 #include "nsIIdlePeriod.h"
 #include "nsIDragService.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMemoryInfoDumper.h"
@@ -699,29 +700,32 @@ ContentChild::ProvideWindow(mozIDOMWindo
                             uint32_t aChromeFlags,
                             bool aCalledFromJS,
                             bool aPositionSpecified,
                             bool aSizeSpecified,
                             nsIURI* aURI,
                             const nsAString& aName,
                             const nsACString& aFeatures,
                             bool aForceNoOpener,
+                            nsIDocShellLoadInfo* aLoadInfo,
                             bool* aWindowIsNew,
                             mozIDOMWindowProxy** aReturn)
 {
   return ProvideWindowCommon(nullptr, aParent, false, aChromeFlags,
                              aCalledFromJS, aPositionSpecified,
                              aSizeSpecified, aURI, aName, aFeatures,
-                             aForceNoOpener, aWindowIsNew, aReturn);
+                             aForceNoOpener, aLoadInfo, aWindowIsNew, aReturn);
 }
 
 static nsresult
-GetWindowParamsFromParent(mozIDOMWindowProxy* aParent,
-                          nsACString& aBaseURIString, float* aFullZoom,
-                          nsIPrincipal** aTriggeringPrincipal)
+GetCreateWindowParams(mozIDOMWindowProxy* aParent,
+                      nsIDocShellLoadInfo* aLoadInfo,
+                      nsACString& aBaseURIString, float* aFullZoom,
+                      uint32_t* aReferrerPolicy,
+                      nsIPrincipal** aTriggeringPrincipal)
 {
   *aFullZoom = 1.0f;
   auto* opener = nsPIDOMWindowOuter::From(aParent);
   if (!opener) {
     nsCOMPtr<nsIPrincipal> nullPrincipal = NullPrincipal::Create();
     NS_ADDREF(*aTriggeringPrincipal = nullPrincipal);
     return NS_OK;
   }
@@ -731,16 +735,26 @@ GetWindowParamsFromParent(mozIDOMWindowP
   nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
   if (!baseURI) {
     NS_ERROR("nsIDocument didn't return a base URI");
     return NS_ERROR_FAILURE;
   }
 
   baseURI->GetSpec(aBaseURIString);
 
+  bool sendReferrer = true;
+  if (aLoadInfo) {
+    aLoadInfo->GetSendReferrer(&sendReferrer);
+    if (!sendReferrer) {
+      *aReferrerPolicy = mozilla::net::RP_No_Referrer;
+    } else {
+      aLoadInfo->GetReferrerPolicy(aReferrerPolicy);
+    }
+  }
+
   RefPtr<nsDocShell> openerDocShell =
     static_cast<nsDocShell*>(opener->GetDocShell());
   if (!openerDocShell) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIContentViewer> cv;
   nsresult rv = openerDocShell->GetContentViewer(getter_AddRefs(cv));
@@ -758,16 +772,17 @@ ContentChild::ProvideWindowCommon(TabChi
                                   uint32_t aChromeFlags,
                                   bool aCalledFromJS,
                                   bool aPositionSpecified,
                                   bool aSizeSpecified,
                                   nsIURI* aURI,
                                   const nsAString& aName,
                                   const nsACString& aFeatures,
                                   bool aForceNoOpener,
+                                  nsIDocShellLoadInfo* aLoadInfo,
                                   bool* aWindowIsNew,
                                   mozIDOMWindowProxy** aReturn)
 {
   *aReturn = nullptr;
 
   nsAutoPtr<IPCTabContext> ipcContext;
   TabId openerTabId = TabId(0);
   nsAutoCString features(aFeatures);
@@ -803,35 +818,38 @@ ContentChild::ProvideWindowCommon(TabChi
   }
 
   // If we're in a content process and we have noopener set, there's no reason
   // to load in our process, so let's load it elsewhere!
   if (loadInDifferentProcess) {
     nsAutoCString baseURIString;
     float fullZoom;
     nsCOMPtr<nsIPrincipal> triggeringPrincipal;
-    rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom,
-                                   getter_AddRefs(triggeringPrincipal));
+    uint32_t referrerPolicy = mozilla::net::RP_Unset;
+    rv = GetCreateWindowParams(aParent, aLoadInfo, baseURIString, &fullZoom,
+                               &referrerPolicy,
+                               getter_AddRefs(triggeringPrincipal));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     OptionalURIParams uriToLoad;
     SerializeURI(aURI, uriToLoad);
     Unused << SendCreateWindowInDifferentProcess(aTabOpener,
                                                  aChromeFlags,
                                                  aCalledFromJS,
                                                  aPositionSpecified,
                                                  aSizeSpecified,
                                                  uriToLoad,
                                                  features,
                                                  baseURIString,
                                                  fullZoom,
                                                  name,
-                                                 Principal(triggeringPrincipal));
+                                                 Principal(triggeringPrincipal),
+                                                 referrerPolicy);
 
     // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned
     // the window open as far as it is concerned.
     return NS_ERROR_ABORT;
   }
 
   if (aTabOpener) {
     PopupIPCTabContext context;
@@ -1012,33 +1030,35 @@ ContentChild::ProvideWindowCommon(TabChi
     newChild->SendBrowserFrameOpenWindow(aTabOpener, renderFrame,
                                          NS_ConvertUTF8toUTF16(url),
                                          name, NS_ConvertUTF8toUTF16(features),
                                          Move(resolve), Move(reject));
   } else {
     nsAutoCString baseURIString;
     float fullZoom;
     nsCOMPtr<nsIPrincipal> triggeringPrincipal;
-    rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom,
-                                   getter_AddRefs(triggeringPrincipal));
+    uint32_t referrerPolicy = mozilla::net::RP_Unset;
+    rv = GetCreateWindowParams(aParent, aLoadInfo, baseURIString, &fullZoom,
+                               &referrerPolicy,
+                               getter_AddRefs(triggeringPrincipal));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     OptionalURIParams uriToLoad;
     if (aURI) {
       SerializeURI(aURI, uriToLoad);
     } else {
       uriToLoad = mozilla::void_t();
     }
 
     SendCreateWindow(aTabOpener, newChild, renderFrame,
                      aChromeFlags, aCalledFromJS, aPositionSpecified,
                      aSizeSpecified, uriToLoad, features, baseURIString,
-                     fullZoom, Principal(triggeringPrincipal),
+                     fullZoom, Principal(triggeringPrincipal), referrerPolicy,
                      Move(resolve), Move(reject));
   }
 
   // =======================
   // Begin Nested Event Loop
   // =======================
 
   // We have to wait for a response from either SendCreateWindow or
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -29,16 +29,17 @@
 
 struct ChromePackage;
 class nsIObserver;
 struct SubstitutionMapping;
 struct OverrideMapping;
 class nsIDomainPolicy;
 class nsIURIClassifierCallback;
 struct LookAndFeelInt;
+class nsIDocShellLoadInfo;
 
 namespace mozilla {
 class RemoteSpellcheckEngineChild;
 class ChildProfilerController;
 
 using mozilla::loader::PScriptCacheChild;
 
 #if !defined(XP_WIN)
@@ -108,16 +109,17 @@ public:
                       uint32_t aChromeFlags,
                       bool aCalledFromJS,
                       bool aPositionSpecified,
                       bool aSizeSpecified,
                       nsIURI* aURI,
                       const nsAString& aName,
                       const nsACString& aFeatures,
                       bool aForceNoOpener,
+                      nsIDocShellLoadInfo* aLoadInfo,
                       bool* aWindowIsNew,
                       mozIDOMWindowProxy** aReturn);
 
   bool Init(MessageLoop* aIOLoop,
             base::ProcessId aParentPid,
             IPC::Channel* aChannel,
             uint64_t aChildID,
             bool aIsForBrowser);
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -4482,16 +4482,17 @@ ContentParent::CommonCreateWindow(PBrows
                                   const nsCString& aBaseURI,
                                   const float& aFullZoom,
                                   uint64_t aNextTabParentId,
                                   const nsString& aName,
                                   nsresult& aResult,
                                   nsCOMPtr<nsITabParent>& aNewTabParent,
                                   bool* aWindowIsNew,
                                   nsIPrincipal* aTriggeringPrincipal,
+                                  uint32_t aReferrerPolicy,
                                   bool aLoadURI)
 
 {
   // The content process should never be in charge of computing whether or
   // not a window should be private or remote - the parent will do that.
   const uint32_t badFlags = nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW |
                             nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW |
                             nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME |
@@ -4564,16 +4565,17 @@ ContentParent::CommonCreateWindow(PBrows
 
     nsCOMPtr<nsIFrameLoaderOwner> opener = do_QueryInterface(frame);
 
     nsCOMPtr<nsIOpenURIInFrameParams> params =
       new nsOpenURIInFrameParams(openerOriginAttributes, opener);
     params->SetReferrer(NS_ConvertUTF8toUTF16(aBaseURI));
     MOZ_ASSERT(aTriggeringPrincipal, "need a valid triggeringPrincipal");
     params->SetTriggeringPrincipal(aTriggeringPrincipal);
+    params->SetReferrerPolicy(aReferrerPolicy);
 
     nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
     if (aLoadURI) {
       aResult = browserDOMWin->OpenURIInFrame(aURIToLoad,
                                               params, openLocation,
                                               nsIBrowserDOMWindow::OPEN_NEW,
                                               aNextTabParentId, aName,
                                               getter_AddRefs(frameLoaderOwner));
@@ -4658,16 +4660,17 @@ ContentParent::RecvCreateWindow(PBrowser
                                 const bool& aCalledFromJS,
                                 const bool& aPositionSpecified,
                                 const bool& aSizeSpecified,
                                 const OptionalURIParams& aURIToLoad,
                                 const nsCString& aFeatures,
                                 const nsCString& aBaseURI,
                                 const float& aFullZoom,
                                 const IPC::Principal& aTriggeringPrincipal,
+                                const uint32_t& aReferrerPolicy,
                                 CreateWindowResolver&& aResolve)
 {
   nsresult rv = NS_OK;
   CreatedWindowInfo cwi;
 
   // We always expect to open a new window here. If we don't, it's an error.
   cwi.windowOpened() = true;
   cwi.layersId() = 0;
@@ -4705,17 +4708,18 @@ ContentParent::RecvCreateWindow(PBrowser
 
   nsCOMPtr<nsITabParent> newRemoteTab;
   mozilla::ipc::IPCResult ipcResult =
     CommonCreateWindow(aThisTab, /* aSetOpener = */ true, aChromeFlags,
                        aCalledFromJS, aPositionSpecified, aSizeSpecified,
                        uriToLoad, aFeatures, aBaseURI, aFullZoom,
                        nextTabParentId, VoidString(), rv,
                        newRemoteTab, &cwi.windowOpened(),
-                       aTriggeringPrincipal, /* aLoadUri = */ false);
+                       aTriggeringPrincipal, aReferrerPolicy,
+                       /* aLoadUri = */ false);
   if (!ipcResult) {
     return ipcResult;
   }
 
   if (NS_WARN_IF(NS_FAILED(rv)) || !newRemoteTab) {
     return IPC_OK();
   }
 
@@ -4749,29 +4753,30 @@ ContentParent::RecvCreateWindowInDiffere
   const bool& aCalledFromJS,
   const bool& aPositionSpecified,
   const bool& aSizeSpecified,
   const OptionalURIParams& aURIToLoad,
   const nsCString& aFeatures,
   const nsCString& aBaseURI,
   const float& aFullZoom,
   const nsString& aName,
-  const IPC::Principal& aTriggeringPrincipal)
+  const IPC::Principal& aTriggeringPrincipal,
+  const uint32_t& aReferrerPolicy)
 {
   nsCOMPtr<nsITabParent> newRemoteTab;
   bool windowIsNew;
   nsCOMPtr<nsIURI> uriToLoad = DeserializeURI(aURIToLoad);
   nsresult rv;
   mozilla::ipc::IPCResult ipcResult =
     CommonCreateWindow(aThisTab, /* aSetOpener = */ false, aChromeFlags,
                        aCalledFromJS, aPositionSpecified, aSizeSpecified,
                        uriToLoad, aFeatures, aBaseURI, aFullZoom,
                        /* aNextTabParentId = */ 0, aName, rv,
                        newRemoteTab, &windowIsNew, aTriggeringPrincipal,
-                       /* aLoadUri = */ true);
+                       aReferrerPolicy, /* aLoadUri = */ true);
   if (!ipcResult) {
     return ipcResult;
   }
 
   if (NS_FAILED(rv)) {
     NS_WARNING("Call to CommonCreateWindow failed.");
   }
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -535,30 +535,32 @@ public:
                    const bool& aCalledFromJS,
                    const bool& aPositionSpecified,
                    const bool& aSizeSpecified,
                    const OptionalURIParams& aURIToLoad,
                    const nsCString& aFeatures,
                    const nsCString& aBaseURI,
                    const float& aFullZoom,
                    const IPC::Principal& aTriggeringPrincipal,
+                   const uint32_t& aReferrerPolicy,
                    CreateWindowResolver&& aResolve) override;
 
   virtual mozilla::ipc::IPCResult RecvCreateWindowInDifferentProcess(
     PBrowserParent* aThisTab,
     const uint32_t& aChromeFlags,
     const bool& aCalledFromJS,
     const bool& aPositionSpecified,
     const bool& aSizeSpecified,
     const OptionalURIParams& aURIToLoad,
     const nsCString& aFeatures,
     const nsCString& aBaseURI,
     const float& aFullZoom,
     const nsString& aName,
-    const IPC::Principal& aTriggeringPrincipal) override;
+    const IPC::Principal& aTriggeringPrincipal,
+    const uint32_t& aReferrerPolicy) override;
 
   static bool AllocateLayerTreeId(TabParent* aTabParent, uint64_t* aId);
 
   static void
   BroadcastBlobURLRegistration(const nsACString& aURI,
                                BlobImpl* aBlobImpl,
                                nsIPrincipal* aPrincipal,
                                ContentParent* aIgnoreThisCP = nullptr);
@@ -712,16 +714,17 @@ private:
                      const nsCString& aBaseURI,
                      const float& aFullZoom,
                      uint64_t aNextTabParentId,
                      const nsString& aName,
                      nsresult& aResult,
                      nsCOMPtr<nsITabParent>& aNewTabParent,
                      bool* aWindowIsNew,
                      nsIPrincipal* aTriggeringPrincipal,
+                     uint32_t aReferrerPolicy,
                      bool aLoadUri);
 
   FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
 
   explicit ContentParent(int32_t aPluginID)
     : ContentParent(nullptr, EmptyString(), aPluginID)
   {}
   ContentParent(ContentParent* aOpener,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -1008,31 +1008,33 @@ parent:
                        uint32_t aChromeFlags,
                        bool aCalledFromJS,
                        bool aPositionSpecified,
                        bool aSizeSpecified,
                        OptionalURIParams aURIToLoad,
                        nsCString aFeatures,
                        nsCString aBaseURI,
                        float aFullZoom,
-                       Principal aTriggeringPrincipal)
+                       Principal aTriggeringPrincipal,
+                       uint32_t aReferrerPolicy)
         returns (CreatedWindowInfo window);
 
     async CreateWindowInDifferentProcess(
       PBrowser aThisTab,
       uint32_t aChromeFlags,
       bool aCalledFromJS,
       bool aPositionSpecified,
       bool aSizeSpecified,
       OptionalURIParams aURIToLoad,
       nsCString aFeatures,
       nsCString aBaseURI,
       float aFullZoom,
       nsString aName,
-      Principal aTriggeringPrincipal);
+      Principal aTriggeringPrincipal,
+      uint32_t aReferrerPolicy);
 
     sync GetAndroidSystemInfo()
         returns (AndroidSystemInfo info);
 
     /**
      * Tells the parent to ungrab the pointer on the default display.
      *
      * This is for GTK platforms where we have to ensure the pointer ungrab happens in the
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -121,16 +121,17 @@
 #include "nsISHistory.h"
 #include "nsQueryObject.h"
 #include "GroupedSHistory.h"
 #include "nsIHttpChannel.h"
 #include "mozilla/dom/DocGroup.h"
 #include "nsString.h"
 #include "nsISupportsPrimitives.h"
 #include "mozilla/Telemetry.h"
+#include "nsIDocShellLoadInfo.h"
 
 #ifdef XP_WIN
 #include "mozilla/plugins/PluginWidgetChild.h"
 #endif
 
 #ifdef NS_PRINTING
 #include "nsIPrintSession.h"
 #include "nsIPrintSettings.h"
@@ -1019,17 +1020,18 @@ TabChild::GetInterface(const nsIID & aII
 
 NS_IMETHODIMP
 TabChild::ProvideWindow(mozIDOMWindowProxy* aParent,
                         uint32_t aChromeFlags,
                         bool aCalledFromJS,
                         bool aPositionSpecified, bool aSizeSpecified,
                         nsIURI* aURI, const nsAString& aName,
                         const nsACString& aFeatures, bool aForceNoOpener,
-                        bool* aWindowIsNew, mozIDOMWindowProxy** aReturn)
+                        nsIDocShellLoadInfo* aLoadInfo, bool* aWindowIsNew,
+                        mozIDOMWindowProxy** aReturn)
 {
     *aReturn = nullptr;
 
     // If aParent is inside an <iframe mozbrowser> and this isn't a request to
     // open a modal-type window, we're going to create a new <iframe mozbrowser>
     // and return its window here.
     nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
     bool iframeMoz = (docshell && docshell->GetIsInMozBrowser() &&
@@ -1062,16 +1064,17 @@ TabChild::ProvideWindow(mozIDOMWindowPro
                                    aChromeFlags,
                                    aCalledFromJS,
                                    aPositionSpecified,
                                    aSizeSpecified,
                                    aURI,
                                    aName,
                                    aFeatures,
                                    aForceNoOpener,
+                                   aLoadInfo,
                                    aWindowIsNew,
                                    aReturn);
 }
 
 void
 TabChild::DestroyWindow()
 {
     if (mCoalescedMouseEventFlusher) {
--- a/toolkit/components/windowcreator/nsIWindowProvider.idl
+++ b/toolkit/components/windowcreator/nsIWindowProvider.idl
@@ -10,16 +10,17 @@
  * a new tab, an existing window, etc) instead of just having a real new
  * toplevel window open.
  */
 
 #include "nsISupports.idl"
 
 interface mozIDOMWindowProxy;
 interface nsIURI;
+interface nsIDocShellLoadInfo;
 
 /**
  * The nsIWindowProvider interface exists so that the window watcher's default
  * behavior of opening a new window can be easly modified.  When the window
  * watcher needs to open a new window, it will first check with the
  * nsIWindowProvider it gets from the parent window.  If there is no provider
  * or the provider does not provide a window, the window watcher will proceed
  * to actually open a new window.
@@ -66,16 +67,18 @@ interface nsIWindowProvider : nsISupport
    *        is provided solely to help the nsIWindowProvider implementation
    *        make decisions.
    *
    * @param aFeatures The feature string for the window being opened.  This may
    *        be empty.  The nsIWindowProvider implementation is allowed to apply
    *        the feature string to the window it returns in any way it sees fit.
    *        See the nsIWindowWatcher interface for details on feature strings.
    *
+   * @param aLoadInfo Specify setup information of the load in the new window
+   *
    * @param aWindowIsNew [out] Whether the window being returned was just
    *        created by the window provider implementation.  This can be used by
    *        callers to keep track of which windows were opened by the user as
    *        opposed to being opened programmatically.  This should be set to
    *        false if the window being returned existed before the
    *        provideWindow() call.  The value of this out parameter is
    *        meaningless if provideWindow() returns null.
 
@@ -94,10 +97,11 @@ interface nsIWindowProvider : nsISupport
                                    in unsigned long aChromeFlags,
                                    in boolean aCalledFromJS,
                                    in boolean aPositionSpecified,
                                    in boolean aSizeSpecified,
                                    in nsIURI aURI,
                                    in AString aName,
                                    in AUTF8String aFeatures,
                                    in boolean aForceNoOpener,
+                                   in nsIDocShellLoadInfo aLoadInfo,
                                    out boolean aWindowIsNew);
 };
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
@@ -848,17 +848,18 @@ nsWindowWatcher::OpenWindowInternal(mozI
       }
 
       if (provider) {
         nsCOMPtr<mozIDOMWindowProxy> newWindow;
         rv = provider->ProvideWindow(aParent, chromeFlags, aCalledFromJS,
                                      sizeSpec.PositionSpecified(),
                                      sizeSpec.SizeSpecified(),
                                      uriToLoad, name, features, aForceNoOpener,
-                                     &windowIsNew, getter_AddRefs(newWindow));
+                                     aLoadInfo, &windowIsNew,
+                                     getter_AddRefs(newWindow));
 
         if (NS_SUCCEEDED(rv)) {
           GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem));
           if (windowIsNew && newDocShellItem) {
             // Make sure to stop any loads happening in this window that the
             // window provider might have started.  Otherwise if our caller
             // manipulates the window it just opened and then the load
             // completes their stuff will get blown away.
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -32,16 +32,17 @@
 #include "nsIWebNavigation.h"
 #include "nsDocShellCID.h"
 #include "nsIExternalURLHandlerService.h"
 #include "nsIMIMEInfo.h"
 #include "nsIWidget.h"
 #include "nsWindowWatcher.h"
 #include "NullPrincipal.h"
 #include "mozilla/BrowserElementParent.h"
+#include "nsIDocShellLoadInfo.h"
 
 #include "nsIDOMDocument.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #if defined(XP_MACOSX)
 #include "nsThreadUtils.h"
 #endif
@@ -820,16 +821,17 @@ nsContentTreeOwner::ProvideWindow(mozIDO
                                   uint32_t aChromeFlags,
                                   bool aCalledFromJS,
                                   bool aPositionSpecified,
                                   bool aSizeSpecified,
                                   nsIURI* aURI,
                                   const nsAString& aName,
                                   const nsACString& aFeatures,
                                   bool aForceNoOpener,
+                                  nsIDocShellLoadInfo* aLoadInfo,
                                   bool* aWindowIsNew,
                                   mozIDOMWindowProxy** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aParent);
 
   auto* parent = nsPIDOMWindowOuter::From(aParent);
 
   *aReturn = nullptr;