Bug 1113196 - Pass a sane set of parameters to loadinfo for top-level loads in e10s. r=sicking
authorBlake Kaplan <mrbkap@gmail.com>
Fri, 04 Mar 2016 08:54:07 -0800
changeset 286794 750b61b5d681dacc485e53201612b717b95a6d07
parent 286793 79ef5d05b4473d846eabd65aa491816618dd0401
child 286795 702b8da8e312f8a56ee5818b17bc18354dfce5d7
push id72914
push usermrbkap@mozilla.com
push dateFri, 04 Mar 2016 16:55:34 +0000
treeherdermozilla-inbound@750b61b5d681 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssicking
bugs1113196
milestone47.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 1113196 - Pass a sane set of parameters to loadinfo for top-level loads in e10s. r=sicking
docshell/base/nsDocShell.cpp
netwerk/base/LoadInfo.cpp
netwerk/base/LoadInfo.h
netwerk/base/nsNetUtil.cpp
netwerk/base/nsNetUtil.h
netwerk/protocol/viewsource/nsViewSourceChannel.cpp
netwerk/protocol/viewsource/nsViewSourceChannel.h
netwerk/protocol/viewsource/nsViewSourceHandler.cpp
netwerk/protocol/viewsource/nsViewSourceHandler.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -10565,21 +10565,49 @@ nsDocShell::DoURILoad(nsIURI* aURI,
     }
   }
 
   // open a channel for the url
   nsCOMPtr<nsIChannel> channel;
 
   bool isSrcdoc = !aSrcdoc.IsVoid();
 
+  // There are three cases we care about:
+  // * Null mScriptGlobal: shouldn't happen but does (see bug 1240246). In this
+  //   case, we create a loadingPrincipal as for a top-level load, but we leave
+  //   requestingNode and requestingWindow null.
+  // * Top-level load (GetFrameElementInternal returns null). In this case,
+  //   requestingNode is null, but requestingWindow is our mScriptGlobal.
+  //   TODO we want to pass null for loadingPrincipal in this case.
+  // * Subframe load: requestingWindow is null, but requestingNode is the frame
+  //   element for the load. loadingPrincipal is the NodePrincipal of the frame
+  //   element.
   nsCOMPtr<nsINode> requestingNode;
+  nsCOMPtr<nsPIDOMWindowOuter> requestingWindow;
+
+  nsCOMPtr<nsIPrincipal> loadingPrincipal;
   if (mScriptGlobal) {
     requestingNode = mScriptGlobal->AsOuter()->GetFrameElementInternal();
-    if (!requestingNode) {
-      requestingNode = mScriptGlobal->GetExtantDoc();
+    if (requestingNode) {
+      // If we have a requesting node, then use that as our loadingPrincipal.
+      loadingPrincipal = requestingNode->NodePrincipal();
+    } else {
+      MOZ_ASSERT(aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT);
+      requestingWindow = mScriptGlobal->AsOuter();
+    }
+  }
+
+  if (!loadingPrincipal) {
+    if (mItemType != typeChrome) {
+      nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+      ssm->GetDocShellCodebasePrincipal(aURI, this, getter_AddRefs(loadingPrincipal));
+    } else {
+      // This is a top-level chrome load, use a system principal for the
+      // loadingPrincipal.
+      loadingPrincipal = nsContentUtils::GetSystemPrincipal();
     }
   }
 
   bool isSandBoxed = mSandboxFlags & SANDBOXED_ORIGIN;
   // only inherit if we have a triggeringPrincipal
   bool inherit = false;
 
   nsCOMPtr<nsIPrincipal> triggeringPrincipal = do_QueryInterface(aOwner);
@@ -10600,29 +10628,29 @@ nsDocShell::DoURILoad(nsIURI* aURI,
   nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
   if (inherit) {
     securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
   }
   if (isSandBoxed) {
     securityFlags |= nsILoadInfo::SEC_SANDBOXED;
   }
 
+  nsCOMPtr<nsILoadInfo> loadInfo =
+    requestingWindow ?
+      new LoadInfo(requestingWindow, loadingPrincipal, triggeringPrincipal,
+                   securityFlags) :
+      new LoadInfo(loadingPrincipal, triggeringPrincipal, requestingNode,
+                   securityFlags, aContentPolicyType);
   if (!isSrcdoc) {
     rv = NS_NewChannelInternal(getter_AddRefs(channel),
                                aURI,
-                               requestingNode,
-                               requestingNode
-                                 ? requestingNode->NodePrincipal()
-                                 : triggeringPrincipal.get(),
-                                triggeringPrincipal,
-                                securityFlags,
-                                aContentPolicyType,
-                                nullptr,   // loadGroup
-                                static_cast<nsIInterfaceRequestor*>(this),
-                                loadFlags);
+                               loadInfo,
+                               nullptr,   // loadGroup
+                               static_cast<nsIInterfaceRequestor*>(this),
+                               loadFlags);
 
     if (NS_FAILED(rv)) {
       if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
         // This is a uri with a protocol scheme we don't know how
         // to handle.  Embedders might still be interested in
         // handling the load, though, so we fire a notification
         // before throwing the load away.
         bool abort = false;
@@ -10647,36 +10675,23 @@ nsDocShell::DoURILoad(nsIURI* aURI,
     bool isViewSource;
     aURI->SchemeIs("view-source", &isViewSource);
 
     if (isViewSource) {
       nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
       NS_ENSURE_TRUE(vsh, NS_ERROR_FAILURE);
 
       rv = vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc,
-                                 requestingNode,
-                                 requestingNode
-                                   ? requestingNode->NodePrincipal()
-                                   : triggeringPrincipal.get(),
-                                 triggeringPrincipal,
-                                 securityFlags,
-                                 aContentPolicyType,
-                                 getter_AddRefs(channel));
+                                 loadInfo, getter_AddRefs(channel));
     } else {
       rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
                                             aURI,
                                             aSrcdoc,
                                             NS_LITERAL_CSTRING("text/html"),
-                                            requestingNode,
-                                            requestingNode ?
-                                              requestingNode->NodePrincipal() :
-                                              triggeringPrincipal.get(),
-                                            triggeringPrincipal,
-                                            securityFlags,
-                                            aContentPolicyType,
+                                            loadInfo,
                                             true);
       NS_ENSURE_SUCCESS(rv, rv);
       nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
       MOZ_ASSERT(isc);
       isc->SetBaseURI(aBaseURI);
     }
   }
 
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -19,16 +19,24 @@
 #include "nsISupportsUtils.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 
 using namespace mozilla::dom;
 
 namespace mozilla {
 
+static void
+InheritOriginAttributes(nsIPrincipal* aLoadingPrincipal, NeckoOriginAttributes& aAttrs)
+{
+  const PrincipalOriginAttributes attrs =
+    BasePrincipal::Cast(aLoadingPrincipal)->OriginAttributesRef();
+  aAttrs.InheritFromDocToNecko(attrs);
+}
+
 LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
                    nsIPrincipal* aTriggeringPrincipal,
                    nsINode* aLoadingContext,
                    nsSecurityFlags aSecurityFlags,
                    nsContentPolicyType aContentPolicyType)
   : mLoadingPrincipal(aLoadingContext ?
                         aLoadingContext->NodePrincipal() : aLoadingPrincipal)
   , mTriggeringPrincipal(aTriggeringPrincipal ?
@@ -92,18 +100,56 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
     // we should do that for all requests. If it only forces preloads to be upgraded
     // then we should enforce upgrade insecure requests only for preloads.
     mUpgradeInsecureRequests =
       aLoadingContext->OwnerDoc()->GetUpgradeInsecureRequests(false) ||
       (nsContentUtils::IsPreloadType(mInternalContentPolicyType) &&
        aLoadingContext->OwnerDoc()->GetUpgradeInsecureRequests(true));
   }
 
-  const PrincipalOriginAttributes attrs = BasePrincipal::Cast(mLoadingPrincipal)->OriginAttributesRef();
-  mOriginAttributes.InheritFromDocToNecko(attrs);
+  InheritOriginAttributes(mLoadingPrincipal, mOriginAttributes);
+}
+
+LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
+                   nsIPrincipal* aLoadingPrincipal,
+                   nsIPrincipal* aTriggeringPrincipal,
+                   nsSecurityFlags aSecurityFlags)
+  : mLoadingPrincipal(aLoadingPrincipal)
+  , mTriggeringPrincipal(aTriggeringPrincipal)
+  , mSecurityFlags(aSecurityFlags)
+  , mInternalContentPolicyType(nsIContentPolicy::TYPE_DOCUMENT)
+  , mTainting(LoadTainting::Basic)
+  , mUpgradeInsecureRequests(false)
+  , mInnerWindowID(0)
+  , mOuterWindowID(0)
+  , mParentOuterWindowID(0)
+  , mEnforceSecurity(false)
+  , mInitialSecurityCheckDone(false)
+  , mIsThirdPartyContext(false) // NB: TYPE_DOCUMENT implies not third-party.
+  , mForcePreflight(false)
+  , mIsPreflight(false)
+{
+  // Top-level loads are never third-party
+  // Grab the information we can out of the window.
+  MOZ_ASSERT(aOuterWindow);
+
+  // if the load is sandboxed, we can not also inherit the principal
+  if (mSecurityFlags & nsILoadInfo::SEC_SANDBOXED) {
+    mSecurityFlags ^= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
+  }
+
+  // NB: Ignore the current inner window since we're navigating away from it.
+  mOuterWindowID = aOuterWindow->WindowID();
+
+  // TODO We can have a parent without a frame element in some cases dealing
+  // with the hidden window.
+  nsCOMPtr<nsPIDOMWindowOuter> parent = aOuterWindow->GetScriptableParent();
+  mParentOuterWindowID = parent ? parent->WindowID() : 0;
+
+  InheritOriginAttributes(mLoadingPrincipal, mOriginAttributes);
 }
 
 LoadInfo::LoadInfo(const LoadInfo& rhs)
   : mLoadingPrincipal(rhs.mLoadingPrincipal)
   , mTriggeringPrincipal(rhs.mTriggeringPrincipal)
   , mLoadingContext(rhs.mLoadingContext)
   , mSecurityFlags(rhs.mSecurityFlags)
   , mInternalContentPolicyType(rhs.mInternalContentPolicyType)
--- a/netwerk/base/LoadInfo.h
+++ b/netwerk/base/LoadInfo.h
@@ -49,16 +49,22 @@ public:
 
   // aLoadingPrincipal MUST NOT BE NULL.
   LoadInfo(nsIPrincipal* aLoadingPrincipal,
            nsIPrincipal* aTriggeringPrincipal,
            nsINode* aLoadingContext,
            nsSecurityFlags aSecurityFlags,
            nsContentPolicyType aContentPolicyType);
 
+  // Constructor used for TYPE_DOCUMENT loads with no reasonable loadingNode.
+  LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
+           nsIPrincipal* aLoadingPrincipal,
+           nsIPrincipal* aTriggeringPrincipal,
+           nsSecurityFlags aSecurityFlags);
+
   // create an exact copy of the loadinfo
   already_AddRefed<nsILoadInfo> Clone() const;
   // creates a copy of the loadinfo which is appropriate to use for a
   // separate request. I.e. not for a redirect or an inner channel, but
   // when a separate request is made with the same security properties.
   already_AddRefed<nsILoadInfo> CloneForNewRequest() const;
 
   void SetIsPreflight();
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -366,21 +366,17 @@ NS_NewInputStreamChannel(nsIChannel     
                                           aContentPolicyType);
 }
 
 nsresult
 NS_NewInputStreamChannelInternal(nsIChannel        **outChannel,
                                  nsIURI             *aUri,
                                  const nsAString    &aData,
                                  const nsACString   &aContentType,
-                                 nsINode            *aLoadingNode,
-                                 nsIPrincipal       *aLoadingPrincipal,
-                                 nsIPrincipal       *aTriggeringPrincipal,
-                                 nsSecurityFlags     aSecurityFlags,
-                                 nsContentPolicyType aContentPolicyType,
+                                 nsILoadInfo        *aLoadInfo,
                                  bool                aIsSrcdocChannel /* = false */)
 {
   nsresult rv;
   nsCOMPtr<nsIStringInputStream> stream;
   stream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
 #ifdef MOZILLA_INTERNAL_API
@@ -393,34 +389,49 @@ NS_NewInputStreamChannelInternal(nsIChan
 #endif
 
   nsCOMPtr<nsIChannel> channel;
   rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
                                         aUri,
                                         stream,
                                         aContentType,
                                         NS_LITERAL_CSTRING("UTF-8"),
-                                        aLoadingNode,
-                                        aLoadingPrincipal,
-                                        aTriggeringPrincipal,
-                                        aSecurityFlags,
-                                        aContentPolicyType);
+                                        aLoadInfo);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aIsSrcdocChannel) {
     nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(channel);
     NS_ENSURE_TRUE(inStrmChan, NS_ERROR_FAILURE);
     inStrmChan->SetSrcdocData(aData);
   }
   channel.forget(outChannel);
   return NS_OK;
 }
 
 nsresult
+NS_NewInputStreamChannelInternal(nsIChannel        **outChannel,
+                                 nsIURI             *aUri,
+                                 const nsAString    &aData,
+                                 const nsACString   &aContentType,
+                                 nsINode            *aLoadingNode,
+                                 nsIPrincipal       *aLoadingPrincipal,
+                                 nsIPrincipal       *aTriggeringPrincipal,
+                                 nsSecurityFlags     aSecurityFlags,
+                                 nsContentPolicyType aContentPolicyType,
+                                 bool                aIsSrcdocChannel /* = false */)
+{
+  nsCOMPtr<nsILoadInfo> loadInfo =
+      new mozilla::LoadInfo(aLoadingPrincipal, aTriggeringPrincipal,
+                            aLoadingNode, aSecurityFlags, aContentPolicyType);
+  return NS_NewInputStreamChannelInternal(outChannel, aUri, aData, aContentType,
+                                          loadInfo, aIsSrcdocChannel);
+}
+
+nsresult
 NS_NewInputStreamChannel(nsIChannel        **outChannel,
                          nsIURI             *aUri,
                          const nsAString    &aData,
                          const nsACString   &aContentType,
                          nsIPrincipal       *aLoadingPrincipal,
                          nsSecurityFlags     aSecurityFlags,
                          nsContentPolicyType aContentPolicyType,
                          bool                aIsSrcdocChannel /* = false */)
--- a/netwerk/base/nsNetUtil.h
+++ b/netwerk/base/nsNetUtil.h
@@ -312,16 +312,24 @@ nsresult NS_NewInputStreamChannelInterna
                                           const nsACString   &aContentType,
                                           nsINode            *aLoadingNode,
                                           nsIPrincipal       *aLoadingPrincipal,
                                           nsIPrincipal       *aTriggeringPrincipal,
                                           nsSecurityFlags     aSecurityFlags,
                                           nsContentPolicyType aContentPolicyType,
                                           bool                aIsSrcdocChannel = false);
 
+nsresult
+NS_NewInputStreamChannelInternal(nsIChannel        **outChannel,
+                                 nsIURI             *aUri,
+                                 const nsAString    &aData,
+                                 const nsACString   &aContentType,
+                                 nsILoadInfo        *aLoadInfo,
+                                 bool                aIsSrcdocChannel = false);
+
 nsresult NS_NewInputStreamChannel(nsIChannel        **outChannel,
                                   nsIURI             *aUri,
                                   const nsAString    &aData,
                                   const nsACString   &aContentType,
                                   nsIPrincipal       *aLoadingPrincipal,
                                   nsSecurityFlags     aSecurityFlags,
                                   nsContentPolicyType aContentPolicyType,
                                   bool                aIsSrcdocChannel = false);
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp
@@ -93,41 +93,33 @@ nsViewSourceChannel::Init(nsIURI* uri)
     
     return NS_OK;
 }
 
 nsresult
 nsViewSourceChannel::InitSrcdoc(nsIURI* aURI,
                                 nsIURI* aBaseURI,
                                 const nsAString &aSrcdoc,
-                                nsINode *aLoadingNode,
-                                nsIPrincipal *aLoadingPrincipal,
-                                nsIPrincipal *aTriggeringPrincipal,
-                                nsSecurityFlags aSecurityFlags,
-                                nsContentPolicyType aContentPolicyType)
+                                nsILoadInfo* aLoadInfo)
 {
     nsresult rv;
 
     nsCOMPtr<nsIURI> inStreamURI;
     // Need to strip view-source: from the URI.  Hardcoded to
     // about:srcdoc as this is the only permissible URI for srcdoc 
     // loads
     rv = NS_NewURI(getter_AddRefs(inStreamURI),
                    NS_LITERAL_STRING("about:srcdoc"));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = NS_NewInputStreamChannelInternal(getter_AddRefs(mChannel),
                                           inStreamURI,
                                           aSrcdoc,
                                           NS_LITERAL_CSTRING("text/html"),
-                                          aLoadingNode,
-                                          aLoadingPrincipal,
-                                          aTriggeringPrincipal,
-                                          aSecurityFlags,
-                                          aContentPolicyType,
+                                          aLoadInfo,
                                           true);
 
     NS_ENSURE_SUCCESS(rv, rv);
     mOriginalURI = aURI;
     mIsSrcdocChannel = true;
 
     mChannel->SetOriginalURI(mOriginalURI);
     mHttpChannel = do_QueryInterface(mChannel);
--- a/netwerk/protocol/viewsource/nsViewSourceChannel.h
+++ b/netwerk/protocol/viewsource/nsViewSourceChannel.h
@@ -48,21 +48,17 @@ public:
         : mIsDocument(false)
         , mOpened(false) {}
 
     nsresult Init(nsIURI* uri);
 
     nsresult InitSrcdoc(nsIURI* aURI,
                         nsIURI* aBaseURI,
                         const nsAString &aSrcdoc,
-                        nsINode *aLoadingNode,
-                        nsIPrincipal *aLoadingPrincipal,
-                        nsIPrincipal *aTriggeringPrincipal,
-                        nsSecurityFlags aSecurityFlags,
-                        nsContentPolicyType aContentPolicyType);
+                        nsILoadInfo* aLoadInfo);
 
 protected:
     ~nsViewSourceChannel() {}
 
     nsCOMPtr<nsIChannel>        mChannel;
     nsCOMPtr<nsIHttpChannel>    mHttpChannel;
     nsCOMPtr<nsIHttpChannelInternal>    mHttpChannelInternal;
     nsCOMPtr<nsICachingChannel> mCachingChannel;
--- a/netwerk/protocol/viewsource/nsViewSourceHandler.cpp
+++ b/netwerk/protocol/viewsource/nsViewSourceHandler.cpp
@@ -122,40 +122,28 @@ nsViewSourceHandler::NewChannel(nsIURI* 
 {
     return NewChannel2(uri, nullptr, result);
 }
 
 nsresult
 nsViewSourceHandler::NewSrcdocChannel(nsIURI *aURI,
                                       nsIURI *aBaseURI,
                                       const nsAString &aSrcdoc,
-                                      nsINode *aLoadingNode,
-                                      nsIPrincipal *aLoadingPrincipal,
-                                      nsIPrincipal *aTriggeringPrincipal,
-                                      nsSecurityFlags aSecurityFlags,
-                                      nsContentPolicyType aContentPolicyType,
+                                      nsILoadInfo* aLoadInfo,
                                       nsIChannel** outChannel)
 {
     NS_ENSURE_ARG_POINTER(aURI);
-    nsViewSourceChannel *channel = new nsViewSourceChannel();
-    if (!channel) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-    NS_ADDREF(channel);
+    RefPtr<nsViewSourceChannel> channel = new nsViewSourceChannel();
 
-    nsresult rv = channel->InitSrcdoc(aURI, aBaseURI, aSrcdoc,
-                                      aLoadingNode, aLoadingPrincipal,
-                                      aTriggeringPrincipal, aSecurityFlags,
-                                      aContentPolicyType);
+    nsresult rv = channel->InitSrcdoc(aURI, aBaseURI, aSrcdoc, aLoadInfo);
     if (NS_FAILED(rv)) {
-        NS_RELEASE(channel);
         return rv;
     }
 
-    *outChannel = static_cast<nsIViewSourceChannel*>(channel);
+    *outChannel = static_cast<nsIViewSourceChannel*>(channel.forget().take());
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsViewSourceHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
 {
     // don't override anything.  
     *_retval = false;
--- a/netwerk/protocol/viewsource/nsViewSourceHandler.h
+++ b/netwerk/protocol/viewsource/nsViewSourceHandler.h
@@ -5,37 +5,32 @@
 
 #ifndef nsViewSourceHandler_h___
 #define nsViewSourceHandler_h___
 
 #include "nsIProtocolHandler.h"
 #include "nsNetUtil.h"
 #include "mozilla/Attributes.h"
 
-class nsINode;
-class nsIPrincipal;
+class nsILoadInfo;
 
 class nsViewSourceHandler final : public nsIProtocolHandler
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIPROTOCOLHANDLER
 
     nsViewSourceHandler();
 
     // Creates a new nsViewSourceChannel to view the source of an about:srcdoc
     // URI with contents specified by srcdoc.
     nsresult NewSrcdocChannel(nsIURI *aURI,
                               nsIURI *aBaseURI,
                               const nsAString &aSrcdoc,
-                              nsINode *aLoadingNode,
-                              nsIPrincipal *aLoadingPrincipal,
-                              nsIPrincipal *aTriggeringPrincipal,
-                              nsSecurityFlags aSecurityFlags,
-                              nsContentPolicyType aContentPolicyType,
+                              nsILoadInfo *aLoadInfo,
                               nsIChannel** outChannel);
 
     static nsViewSourceHandler* GetInstance();
 
 private:
     ~nsViewSourceHandler();
 
     static nsViewSourceHandler* gInstance;