diff options
-rw-r--r-- | docshell/base/nsDocShell.cpp | 74 | ||||
-rw-r--r-- | dom/base/nsContentPolicy.cpp | 6 | ||||
-rw-r--r-- | dom/security/nsContentSecurityManager.cpp | 63 | ||||
-rw-r--r-- | netwerk/base/LoadInfo.cpp | 15 | ||||
-rw-r--r-- | netwerk/base/LoadInfo.h | 7 | ||||
-rw-r--r-- | netwerk/base/nsILoadInfo.idl | 10 |
6 files changed, 120 insertions, 55 deletions
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index b1fcc5c23..bd2a8a433 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -9896,40 +9896,29 @@ nsDocShell::InternalLoad(nsIURI* aURI, contentType = nsIContentPolicy::TYPE_DOCUMENT; } - // If there's no targetDocShell, that means we are about to create a new window, - // perform a content policy check before creating the window. - if (!targetDocShell) { - nsCOMPtr<Element> requestingElement; + // If there's no targetDocShell, that means we are about to create a new + // window (or aWindowTarget is empty). Perform a content policy check before + // creating the window. Please note for all other docshell loads + // content policy checks are performed within the contentSecurityManager + // when the channel is about to be openend. + if (!targetDocShell && !aWindowTarget.IsEmpty()) { + MOZ_ASSERT(contentType == nsIContentPolicy::TYPE_DOCUMENT, + "opening a new window requires type to be TYPE_DOCUMENT"); + nsISupports* requestingContext = nullptr; - if (contentType == nsIContentPolicy::TYPE_DOCUMENT) { - if (XRE_IsContentProcess()) { - // In e10s the child process doesn't have access to the element that - // contains the browsing context (because that element is in the chrome - // process). So we just pass mScriptGlobal. - requestingContext = ToSupports(mScriptGlobal); - } else { - // This is for loading non-e10s tabs and toplevel windows of various - // sorts. - // For the toplevel window cases, requestingElement will be null. - requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal(); - requestingContext = requestingElement; - } + if (XRE_IsContentProcess()) { + // In e10s the child process doesn't have access to the element that + // contains the browsing context (because that element is in the chrome + // process). So we just pass mScriptGlobal. + requestingContext = ToSupports(mScriptGlobal); } else { - requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal(); + // This is for loading non-e10s tabs and toplevel windows of various + // sorts. + // For the toplevel window cases, requestingElement will be null. + nsCOMPtr<Element> requestingElement = + mScriptGlobal->AsOuter()->GetFrameElementInternal(); requestingContext = requestingElement; - -#ifdef DEBUG - if (requestingElement) { - // Get the docshell type for requestingElement. - nsCOMPtr<nsIDocument> requestingDoc = requestingElement->OwnerDoc(); - nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell(); - - // requestingElement docshell type = current docshell type. - MOZ_ASSERT(mItemType == elementDocShell->ItemType(), - "subframes should have the same docshell type as their parent"); - } -#endif } // Since Content Policy checks are performed within docShell as well as @@ -10911,17 +10900,40 @@ nsDocShell::DoURILoad(nsIURI* aURI, nsCOMPtr<nsINode> loadingNode; nsCOMPtr<nsPIDOMWindowOuter> loadingWindow; nsCOMPtr<nsIPrincipal> loadingPrincipal; + nsCOMPtr<nsISupports> topLevelLoadingContext; if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) { loadingNode = nullptr; loadingPrincipal = nullptr; loadingWindow = mScriptGlobal->AsOuter(); + if (XRE_IsContentProcess()) { + // In e10s the child process doesn't have access to the element that + // contains the browsing context (because that element is in the chrome + // process). + nsCOMPtr<nsITabChild> tabChild = GetTabChild(); + topLevelLoadingContext = ToSupports(tabChild); + } else { + // This is for loading non-e10s tabs and toplevel windows of various + // sorts. + // For the toplevel window cases, requestingElement will be null. + nsCOMPtr<Element> requestingElement = + loadingWindow->GetFrameElementInternal(); + topLevelLoadingContext = requestingElement; + } } else { loadingWindow = nullptr; loadingNode = mScriptGlobal->AsOuter()->GetFrameElementInternal(); if (loadingNode) { // If we have a loading node, then use that as our loadingPrincipal. loadingPrincipal = loadingNode->NodePrincipal(); +#ifdef DEBUG + // Get the docshell type for requestingElement. + nsCOMPtr<nsIDocument> requestingDoc = loadingNode->OwnerDoc(); + nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell(); + // requestingElement docshell type = current docshell type. + MOZ_ASSERT(mItemType == elementDocShell->ItemType(), + "subframes should have the same docshell type as their parent"); +#endif } else { // If this isn't a top-level load and mScriptGlobal's frame element is // null, then the element got removed from the DOM while we were trying @@ -10971,7 +10983,7 @@ nsDocShell::DoURILoad(nsIURI* aURI, nsCOMPtr<nsILoadInfo> loadInfo = (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ? - new LoadInfo(loadingWindow, aTriggeringPrincipal, + new LoadInfo(loadingWindow, aTriggeringPrincipal, topLevelLoadingContext, securityFlags) : new LoadInfo(loadingPrincipal, aTriggeringPrincipal, loadingNode, securityFlags, aContentPolicyType); diff --git a/dom/base/nsContentPolicy.cpp b/dom/base/nsContentPolicy.cpp index 337debcea..5511b9086 100644 --- a/dom/base/nsContentPolicy.cpp +++ b/dom/base/nsContentPolicy.cpp @@ -20,6 +20,7 @@ #include "nsIDOMElement.h" #include "nsIDOMNode.h" #include "nsIDOMWindow.h" +#include "nsITabChild.h" #include "nsIContent.h" #include "nsILoadContext.h" #include "nsCOMArray.h" @@ -89,8 +90,9 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod, { nsCOMPtr<nsIDOMNode> node(do_QueryInterface(requestingContext)); nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext)); - NS_ASSERTION(!requestingContext || node || window, - "Context should be a DOM node or a DOM window!"); + nsCOMPtr<nsITabChild> tabChild(do_QueryInterface(requestingContext)); + NS_ASSERTION(!requestingContext || node || window || tabChild, + "Context should be a DOM node, DOM window or a tabChild!"); } #endif diff --git a/dom/security/nsContentSecurityManager.cpp b/dom/security/nsContentSecurityManager.cpp index 9329c558a..0cc4933fe 100644 --- a/dom/security/nsContentSecurityManager.cpp +++ b/dom/security/nsContentSecurityManager.cpp @@ -253,7 +253,7 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo) nsContentPolicyType internalContentPolicyType = aLoadInfo->InternalContentPolicyType(); nsCString mimeTypeGuess; - nsCOMPtr<nsINode> requestingContext = nullptr; + nsCOMPtr<nsISupports> requestingContext = nullptr; #ifdef DEBUG // Don't enforce TYPE_DOCUMENT assertions for loads @@ -327,10 +327,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo) case nsIContentPolicy::TYPE_XMLHTTPREQUEST: { // alias nsIContentPolicy::TYPE_DATAREQUEST: requestingContext = aLoadInfo->LoadingNode(); - MOZ_ASSERT(!requestingContext || - requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, - "type_xml requires requestingContext of type Document"); - +#ifdef DEBUG + { + nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext); + MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE, + "type_xml requires requestingContext of type Document"); + } +#endif // We're checking for the external TYPE_XMLHTTPREQUEST here in case // an addon creates a request with that type. if (internalContentPolicyType == @@ -351,18 +354,26 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo) case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); - MOZ_ASSERT(!requestingContext || - requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, - "type_subrequest requires requestingContext of type Element"); +#ifdef DEBUG + { + nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext); + MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE, + "type_subrequest requires requestingContext of type Element"); + } +#endif break; } case nsIContentPolicy::TYPE_DTD: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); - MOZ_ASSERT(!requestingContext || - requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, - "type_dtd requires requestingContext of type Document"); +#ifdef DEBUG + { + nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext); + MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE, + "type_dtd requires requestingContext of type Document"); + } +#endif break; } @@ -380,9 +391,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo) mimeTypeGuess = EmptyCString(); } requestingContext = aLoadInfo->LoadingNode(); - MOZ_ASSERT(!requestingContext || - requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, - "type_media requires requestingContext of type Element"); +#ifdef DEBUG + { + nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext); + MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE, + "type_media requires requestingContext of type Element"); + } +#endif break; } @@ -409,18 +424,26 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo) case nsIContentPolicy::TYPE_XSLT: { mimeTypeGuess = NS_LITERAL_CSTRING("application/xml"); requestingContext = aLoadInfo->LoadingNode(); - MOZ_ASSERT(!requestingContext || - requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, - "type_xslt requires requestingContext of type Document"); +#ifdef DEBUG + { + nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext); + MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE, + "type_xslt requires requestingContext of type Document"); + } +#endif break; } case nsIContentPolicy::TYPE_BEACON: { mimeTypeGuess = EmptyCString(); requestingContext = aLoadInfo->LoadingNode(); - MOZ_ASSERT(!requestingContext || - requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, - "type_beacon requires requestingContext of type Document"); +#ifdef DEBUG + { + nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext); + MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE, + "type_beacon requires requestingContext of type Document"); + } +#endif break; } diff --git a/netwerk/base/LoadInfo.cpp b/netwerk/base/LoadInfo.cpp index 9923f6d30..ede825b8f 100644 --- a/netwerk/base/LoadInfo.cpp +++ b/netwerk/base/LoadInfo.cpp @@ -48,6 +48,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, aTriggeringPrincipal : mLoadingPrincipal.get()) , mPrincipalToInherit(nullptr) , mLoadingContext(do_GetWeakReference(aLoadingContext)) + , mContextForTopLevelLoad(nullptr) , mSecurityFlags(aSecurityFlags) , mInternalContentPolicyType(aContentPolicyType) , mTainting(LoadTainting::Basic) @@ -218,10 +219,12 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal, */ LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, nsIPrincipal* aTriggeringPrincipal, + nsISupports* aContextForTopLevelLoad, nsSecurityFlags aSecurityFlags) : mLoadingPrincipal(nullptr) , mTriggeringPrincipal(aTriggeringPrincipal) , mPrincipalToInherit(nullptr) + , mContextForTopLevelLoad(do_GetWeakReference(aContextForTopLevelLoad)) , mSecurityFlags(aSecurityFlags) , mInternalContentPolicyType(nsIContentPolicy::TYPE_DOCUMENT) , mTainting(LoadTainting::Basic) @@ -281,6 +284,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs) , mTriggeringPrincipal(rhs.mTriggeringPrincipal) , mPrincipalToInherit(rhs.mPrincipalToInherit) , mLoadingContext(rhs.mLoadingContext) + , mContextForTopLevelLoad(rhs.mContextForTopLevelLoad) , mSecurityFlags(rhs.mSecurityFlags) , mInternalContentPolicyType(rhs.mInternalContentPolicyType) , mTainting(rhs.mTainting) @@ -488,6 +492,17 @@ LoadInfo::LoadingNode() return node; } +nsISupports* +LoadInfo::ContextForTopLevelLoad() +{ + // Most likely you want to query LoadingNode() instead of + // ContextForTopLevelLoad() if this assertion fires. + MOZ_ASSERT(mInternalContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT, + "should only query this context for top level document loads"); + nsCOMPtr<nsISupports> context = do_QueryReferent(mContextForTopLevelLoad); + return context; +} + NS_IMETHODIMP LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult) { diff --git a/netwerk/base/LoadInfo.h b/netwerk/base/LoadInfo.h index 86cfddc68..0ae6061b3 100644 --- a/netwerk/base/LoadInfo.h +++ b/netwerk/base/LoadInfo.h @@ -59,10 +59,12 @@ public: nsSecurityFlags aSecurityFlags, nsContentPolicyType aContentPolicyType); - // Constructor used for TYPE_DOCUMENT loads which have no reasonable - // loadingNode or loadingPrincipal + // Constructor used for TYPE_DOCUMENT loads which have a different + // loadingContext than other loads. This ContextForTopLevelLoad is + // only used for content policy checks. LoadInfo(nsPIDOMWindowOuter* aOuterWindow, nsIPrincipal* aTriggeringPrincipal, + nsISupports* aContextForTopLevelLoad, nsSecurityFlags aSecurityFlags); // create an exact copy of the loadinfo @@ -134,6 +136,7 @@ private: nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; nsCOMPtr<nsIPrincipal> mPrincipalToInherit; nsWeakPtr mLoadingContext; + nsWeakPtr mContextForTopLevelLoad; nsSecurityFlags mSecurityFlags; nsContentPolicyType mInternalContentPolicyType; LoadTainting mTainting; diff --git a/netwerk/base/nsILoadInfo.idl b/netwerk/base/nsILoadInfo.idl index 5b35736e5..4ec29b972 100644 --- a/netwerk/base/nsILoadInfo.idl +++ b/netwerk/base/nsILoadInfo.idl @@ -324,6 +324,16 @@ interface nsILoadInfo : nsISupports nsINode binaryLoadingNode(); /** + * A C++ friendly version of the loadingContext for toplevel loads. + * Most likely you want to query the ownerDocument or LoadingNode + * and not this context only available for TYPE_DOCUMENT loads. + * Please note that except for loads of TYPE_DOCUMENT, this + * ContextForTopLevelLoad will always return null. + */ + [noscript, notxpcom, nostdcall, binaryname(ContextForTopLevelLoad)] + nsISupports binaryContextForTopLevelLoad(); + + /** * The securityFlags of that channel. */ readonly attribute nsSecurityFlags securityFlags; |