Bug 1639195 - Part 1: Make BrowserChild::RecvLoadURL() to use the correct triggering princpal. r=ckerschb,mattwoodrow
authorTim Huang <tihuang@mozilla.com>
Tue, 19 May 2020 20:22:34 +0000
changeset 530950 5cf6e62ea26befe090114c51306f69a7fbb56a14
parent 530949 8b594c96ab8e8e10e224169cd95ebb57d18ccf0e
child 530951 55ff7a761ebbc488561e2b4b9e4061a540d7e55d
push id37434
push userabutkovits@mozilla.com
push dateWed, 20 May 2020 10:05:10 +0000
treeherdermozilla-central@005ef1c25992 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersckerschb, mattwoodrow
bugs1639195
milestone78.0a1
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 1639195 - Part 1: Make BrowserChild::RecvLoadURL() to use the correct triggering princpal. r=ckerschb,mattwoodrow This patch makes the triggering princpal to be propagated to the BrowserChild when calling LoadURL in nsFrameLoader. And use it as the triggering principal for loading instead of the system principal. Differential Revision: https://phabricator.services.mozilla.com/D75965
dom/base/nsFrameLoader.cpp
dom/ipc/BrowserBridgeHost.cpp
dom/ipc/BrowserBridgeHost.h
dom/ipc/BrowserBridgeParent.cpp
dom/ipc/BrowserBridgeParent.h
dom/ipc/BrowserChild.cpp
dom/ipc/BrowserChild.h
dom/ipc/BrowserHost.cpp
dom/ipc/BrowserHost.h
dom/ipc/BrowserParent.cpp
dom/ipc/BrowserParent.h
dom/ipc/PBrowser.ipdl
dom/ipc/PBrowserBridge.ipdl
dom/ipc/RemoteBrowser.h
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -571,17 +571,25 @@ nsresult nsFrameLoader::ReallyStartLoadi
       NS_WARNING("Couldn't create child process for iframe.");
       return NS_ERROR_FAILURE;
     }
 
     if (mPendingSwitchID) {
       mRemoteBrowser->ResumeLoad(mPendingSwitchID);
       mPendingSwitchID = 0;
     } else {
-      mRemoteBrowser->LoadURL(mURIToLoad);
+      // The triggering principal could be null if the frame is loaded other
+      // than the src attribute, for example, the frame is sandboxed. In the
+      // case we use the principal of the owner content, which is needed to
+      // prevent XSS attaches on documents loaded in subframes.
+      if (mTriggeringPrincipal) {
+        mRemoteBrowser->LoadURL(mURIToLoad, mTriggeringPrincipal);
+      } else {
+        mRemoteBrowser->LoadURL(mURIToLoad, mOwnerContent->NodePrincipal());
+      }
     }
 
     if (!mRemoteBrowserShown) {
       // This can fail if it's too early to show the frame, we will retry later.
       Unused << ShowRemoteFrame(ScreenIntSize(0, 0));
     }
 
     return NS_OK;
--- a/dom/ipc/BrowserBridgeHost.cpp
+++ b/dom/ipc/BrowserBridgeHost.cpp
@@ -32,20 +32,24 @@ mozilla::layers::LayersId BrowserBridgeH
 BrowsingContext* BrowserBridgeHost::GetBrowsingContext() const {
   return mBridge->GetBrowsingContext();
 }
 
 nsILoadContext* BrowserBridgeHost::GetLoadContext() const {
   return mBridge->GetLoadContext();
 }
 
-void BrowserBridgeHost::LoadURL(nsIURI* aURI) {
+void BrowserBridgeHost::LoadURL(nsIURI* aURI,
+                                nsIPrincipal* aTriggeringPrincipal) {
+  MOZ_ASSERT(aURI);
+  MOZ_ASSERT(aTriggeringPrincipal);
+
   nsAutoCString spec;
   aURI->GetSpec(spec);
-  Unused << mBridge->SendLoadURL(spec);
+  Unused << mBridge->SendLoadURL(spec, aTriggeringPrincipal);
 }
 
 void BrowserBridgeHost::ResumeLoad(uint64_t aPendingSwitchId) {
   Unused << mBridge->SendResumeLoad(aPendingSwitchId);
 }
 
 void BrowserBridgeHost::DestroyStart() { DestroyComplete(); }
 
--- a/dom/ipc/BrowserBridgeHost.h
+++ b/dom/ipc/BrowserBridgeHost.h
@@ -38,17 +38,17 @@ class BrowserBridgeHost : public RemoteB
   BrowserHost* AsBrowserHost() override { return nullptr; }
   BrowserBridgeHost* AsBrowserBridgeHost() override { return this; }
 
   TabId GetTabId() const override;
   LayersId GetLayersId() const override;
   BrowsingContext* GetBrowsingContext() const override;
   nsILoadContext* GetLoadContext() const override;
 
-  void LoadURL(nsIURI* aURI) override;
+  void LoadURL(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal) override;
   void ResumeLoad(uint64_t aPendingSwitchId) override;
   void DestroyStart() override;
   void DestroyComplete() override;
 
   bool Show(const OwnerShowInfo&) override;
   void UpdateDimensions(const nsIntRect& aRect,
                         const ScreenIntSize& aSize) override;
 
--- a/dom/ipc/BrowserBridgeParent.cpp
+++ b/dom/ipc/BrowserBridgeParent.cpp
@@ -139,18 +139,20 @@ IPCResult BrowserBridgeParent::RecvShow(
 }
 
 IPCResult BrowserBridgeParent::RecvScrollbarPreferenceChanged(
     ScrollbarPreference aPref) {
   Unused << mBrowserParent->SendScrollbarPreferenceChanged(aPref);
   return IPC_OK();
 }
 
-IPCResult BrowserBridgeParent::RecvLoadURL(const nsCString& aUrl) {
-  Unused << mBrowserParent->SendLoadURL(aUrl, mBrowserParent->GetShowInfo());
+IPCResult BrowserBridgeParent::RecvLoadURL(const nsCString& aUrl,
+                                           nsIPrincipal* aTriggeringPrincipal) {
+  Unused << mBrowserParent->SendLoadURL(aUrl, aTriggeringPrincipal,
+                                        mBrowserParent->GetShowInfo());
   return IPC_OK();
 }
 
 IPCResult BrowserBridgeParent::RecvResumeLoad(uint64_t aPendingSwitchID) {
   mBrowserParent->ResumeLoad(aPendingSwitchID);
   return IPC_OK();
 }
 
--- a/dom/ipc/BrowserBridgeParent.h
+++ b/dom/ipc/BrowserBridgeParent.h
@@ -58,17 +58,18 @@ class BrowserBridgeParent : public PBrow
   // Tear down this BrowserBridgeParent.
   void Destroy();
 
  protected:
   friend class PBrowserBridgeParent;
 
   mozilla::ipc::IPCResult RecvShow(const OwnerShowInfo&);
   mozilla::ipc::IPCResult RecvScrollbarPreferenceChanged(ScrollbarPreference);
-  mozilla::ipc::IPCResult RecvLoadURL(const nsCString& aUrl);
+  mozilla::ipc::IPCResult RecvLoadURL(const nsCString& aUrl,
+                                      nsIPrincipal* aTriggeringPrincipal);
   mozilla::ipc::IPCResult RecvResumeLoad(uint64_t aPendingSwitchID);
   mozilla::ipc::IPCResult RecvUpdateDimensions(const nsIntRect& aRect,
                                                const ScreenIntSize& aSize);
   mozilla::ipc::IPCResult RecvUpdateEffects(const EffectsInfo& aEffects);
   mozilla::ipc::IPCResult RecvRenderLayers(const bool& aEnabled,
                                            const LayersObserverEpoch& aEpoch);
 
   mozilla::ipc::IPCResult RecvNavigateByKey(const bool& aForward,
--- a/dom/ipc/BrowserChild.cpp
+++ b/dom/ipc/BrowserChild.cpp
@@ -994,29 +994,30 @@ mozilla::ipc::IPCResult BrowserChild::Re
     WillChangeProcessResolver&& aResolve) {
   if (mWebBrowser) {
     mWebBrowser->SetWillChangeProcess();
   }
   aResolve(true);
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult BrowserChild::RecvLoadURL(const nsCString& aURI,
-                                                  const ParentShowInfo& aInfo) {
+mozilla::ipc::IPCResult BrowserChild::RecvLoadURL(
+    const nsCString& aURI, nsIPrincipal* aTriggeringPrincipal,
+    const ParentShowInfo& aInfo) {
   if (!mDidLoadURLInit) {
     mDidLoadURLInit = true;
     if (!InitBrowserChildMessageManager()) {
       return IPC_FAIL_NO_REASON(this);
     }
 
     ApplyParentShowInfo(aInfo);
   }
 
   LoadURIOptions loadURIOptions;
-  loadURIOptions.mTriggeringPrincipal = nsContentUtils::GetSystemPrincipal();
+  loadURIOptions.mTriggeringPrincipal = aTriggeringPrincipal;
   loadURIOptions.mLoadFlags =
       nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
       nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
 
   nsIWebNavigation* webNav = WebNavigation();
   nsresult rv = webNav->LoadURI(NS_ConvertUTF8toUTF16(aURI), loadURIOptions);
   if (NS_FAILED(rv)) {
     NS_WARNING(
--- a/dom/ipc/BrowserChild.h
+++ b/dom/ipc/BrowserChild.h
@@ -249,16 +249,17 @@ class BrowserChild final : public nsMess
   virtual nsresult DoSendAsyncMessage(const nsAString& aMessage,
                                       StructuredCloneData& aData) override;
 
   bool DoUpdateZoomConstraints(const uint32_t& aPresShellId,
                                const ViewID& aViewId,
                                const Maybe<ZoomConstraints>& aConstraints);
 
   mozilla::ipc::IPCResult RecvLoadURL(const nsCString& aURI,
+                                      nsIPrincipal* aTriggeringPrincipal,
                                       const ParentShowInfo&);
 
   mozilla::ipc::IPCResult RecvResumeLoad(const uint64_t& aPendingSwitchID,
                                          const ParentShowInfo&);
 
   MOZ_CAN_RUN_SCRIPT_BOUNDARY
   mozilla::ipc::IPCResult RecvShow(const ParentShowInfo&, const OwnerShowInfo&);
 
--- a/dom/ipc/BrowserHost.cpp
+++ b/dom/ipc/BrowserHost.cpp
@@ -51,17 +51,22 @@ nsILoadContext* BrowserHost::GetLoadCont
   RefPtr<nsILoadContext> loadContext = mRoot->GetLoadContext();
   return loadContext;
 }
 
 a11y::DocAccessibleParent* BrowserHost::GetTopLevelDocAccessible() const {
   return mRoot->GetTopLevelDocAccessible();
 }
 
-void BrowserHost::LoadURL(nsIURI* aURI) { mRoot->LoadURL(aURI); }
+void BrowserHost::LoadURL(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal) {
+  MOZ_ASSERT(aURI);
+  MOZ_ASSERT(aTriggeringPrincipal);
+
+  mRoot->LoadURL(aURI, aTriggeringPrincipal);
+}
 
 void BrowserHost::ResumeLoad(uint64_t aPendingSwitchId) {
   mRoot->ResumeLoad(aPendingSwitchId);
 }
 
 void BrowserHost::DestroyStart() { mRoot->Destroy(); }
 
 void BrowserHost::DestroyComplete() {
--- a/dom/ipc/BrowserHost.h
+++ b/dom/ipc/BrowserHost.h
@@ -75,17 +75,17 @@ class BrowserHost : public RemoteBrowser
   template <typename Callback>
   void VisitAll(Callback aCallback) {
     if (!mRoot) {
       return;
     }
     mRoot->VisitAll(aCallback);
   }
 
-  void LoadURL(nsIURI* aURI) override;
+  void LoadURL(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal) override;
   void ResumeLoad(uint64_t aPendingSwitchId) override;
   void DestroyStart() override;
   void DestroyComplete() override;
 
   bool Show(const OwnerShowInfo&) override;
   void UpdateDimensions(const nsIntRect& aRect,
                         const ScreenIntSize& aSize) override;
 
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -865,34 +865,35 @@ bool BrowserParent::SendLoadRemoteScript
         FrameScriptInfo(aURL, aRunInGlobalScope));
     return true;
   }
 
   MOZ_ASSERT(mDelayedFrameScripts.IsEmpty());
   return PBrowserParent::SendLoadRemoteScript(aURL, aRunInGlobalScope);
 }
 
-void BrowserParent::LoadURL(nsIURI* aURI) {
+void BrowserParent::LoadURL(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal) {
   MOZ_ASSERT(aURI);
+  MOZ_ASSERT(aTriggeringPrincipal);
 
   if (mIsDestroyed) {
     return;
   }
 
   nsCString spec;
   aURI->GetSpec(spec);
 
   if (mCreatingWindow) {
     // Don't send the message if the child wants to load its own URL.
     MOZ_ASSERT(mDelayedURL.IsEmpty());
     mDelayedURL = spec;
     return;
   }
 
-  Unused << SendLoadURL(spec, GetShowInfo());
+  Unused << SendLoadURL(spec, aTriggeringPrincipal, GetShowInfo());
 }
 
 void BrowserParent::ResumeLoad(uint64_t aPendingSwitchID) {
   MOZ_ASSERT(aPendingSwitchID != 0);
 
   if (NS_WARN_IF(mIsDestroyed)) {
     return;
   }
--- a/dom/ipc/BrowserParent.h
+++ b/dom/ipc/BrowserParent.h
@@ -485,17 +485,17 @@ class BrowserParent final : public PBrow
   mozilla::ipc::IPCResult RecvIsWindowSupportingProtectedMedia(
       const uint64_t& aOuterWindowID,
       IsWindowSupportingProtectedMediaResolver&& aResolve);
 
   mozilla::ipc::IPCResult RecvIsWindowSupportingWebVR(
       const uint64_t& aOuterWindowID,
       IsWindowSupportingWebVRResolver&& aResolve);
 
-  void LoadURL(nsIURI* aURI);
+  void LoadURL(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal);
 
   void ResumeLoad(uint64_t aPendingSwitchID);
 
   void InitRendering();
   bool AttachLayerManager();
   void MaybeShowFrame();
 
   bool Show(const OwnerShowInfo&);
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -707,17 +707,19 @@ child:
 
     async InitRendering(TextureFactoryIdentifier textureFactoryIdentifier,
                         LayersId layersId,
                         CompositorOptions compositorOptions,
                         bool layersConnected);
 
     async CompositorOptionsChanged(CompositorOptions newOptions);
 
-    async LoadURL(nsCString uri, ParentShowInfo info);
+    async LoadURL(nsCString uri,
+                  nsIPrincipal triggeringPrincipal,
+                  ParentShowInfo info);
 
     async ResumeLoad(uint64_t pendingSwitchID, ParentShowInfo info);
 
     async UpdateDimensions(DimensionInfo dimensions) compressall;
 
     async SizeModeChanged(nsSizeMode sizeMode);
 
     async ChildToParentMatrix(MaybeMatrix4x4 aMatrix,
--- a/dom/ipc/PBrowserBridge.ipdl
+++ b/dom/ipc/PBrowserBridge.ipdl
@@ -71,17 +71,17 @@ child:
 
   async AddBlockedNodeByClassifier();
 
 parent:
   // Destroy the remote web browser due to the nsFrameLoader going away.
   async __delete__();
 
   // DocShell messaging.
-  async LoadURL(nsCString aSpec);
+  async LoadURL(nsCString aSpec, nsIPrincipal aTriggeringPrincipal);
   async ResumeLoad(uint64_t aPendingSwitchID);
 
   // Out of process rendering.
   async Show(OwnerShowInfo info);
   async ScrollbarPreferenceChanged(ScrollbarPreference pref);
   async UpdateDimensions(nsIntRect rect, ScreenIntSize size) compressall;
   async RenderLayers(bool aEnabled, LayersObserverEpoch aEpoch);
 
--- a/dom/ipc/RemoteBrowser.h
+++ b/dom/ipc/RemoteBrowser.h
@@ -7,16 +7,17 @@
 #ifndef mozilla_dom_ipc_RemoteBrowser_h
 #define mozilla_dom_ipc_RemoteBrowser_h
 
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/ipc/IdType.h"
 #include "mozilla/dom/EffectsInfo.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "nsILoadContext.h"
+#include "nsIPrincipal.h"
 #include "nsISupports.h"
 #include "nsISupportsImpl.h"
 #include "nsIURI.h"
 #include "nsRect.h"
 #include "Units.h"
 
 namespace mozilla {
 
@@ -49,17 +50,17 @@ class RemoteBrowser : public nsISupports
   // Try to cast this RemoteBrowser to a BrowserBridgeHost, may return null
   virtual BrowserBridgeHost* AsBrowserBridgeHost() = 0;
 
   virtual TabId GetTabId() const = 0;
   virtual LayersId GetLayersId() const = 0;
   virtual BrowsingContext* GetBrowsingContext() const = 0;
   virtual nsILoadContext* GetLoadContext() const = 0;
 
-  virtual void LoadURL(nsIURI* aURI) = 0;
+  virtual void LoadURL(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal) = 0;
   virtual void ResumeLoad(uint64_t aPendingSwitchId) = 0;
   virtual void DestroyStart() = 0;
   virtual void DestroyComplete() = 0;
 
   virtual bool Show(const OwnerShowInfo&) = 0;
   virtual void UpdateDimensions(const nsIntRect& aRect,
                                 const ScreenIntSize& aSize) = 0;