moebius#187: DOM - nsIContentPolicy - context (document)

https://github.com/MoonchildProductions/moebius/pull/187
This commit is contained in:
janekptacijarabaci 2018-04-23 00:13:56 +02:00 • committed by Roy Tam
commit 7f09dee539
6 changed files with 120 additions and 55 deletions

View file

@ -9896,13 +9896,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
contentType = nsIContentPolicy::TYPE_DOCUMENT; contentType = nsIContentPolicy::TYPE_DOCUMENT;
} }
// If there's no targetDocShell, that means we are about to create a new window, // If there's no targetDocShell, that means we are about to create a new
// perform a content policy check before creating the window. // window (or aWindowTarget is empty). Perform a content policy check before
if (!targetDocShell) { // creating the window. Please note for all other docshell loads
nsCOMPtr<Element> requestingElement; // 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; nsISupports* requestingContext = nullptr;
if (contentType == nsIContentPolicy::TYPE_DOCUMENT) {
if (XRE_IsContentProcess()) { if (XRE_IsContentProcess()) {
// In e10s the child process doesn't have access to the element that // In e10s the child process doesn't have access to the element that
// contains the browsing context (because that element is in the chrome // contains the browsing context (because that element is in the chrome
@ -9912,25 +9916,10 @@ nsDocShell::InternalLoad(nsIURI* aURI,
// This is for loading non-e10s tabs and toplevel windows of various // This is for loading non-e10s tabs and toplevel windows of various
// sorts. // sorts.
// For the toplevel window cases, requestingElement will be null. // For the toplevel window cases, requestingElement will be null.
requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal(); nsCOMPtr<Element> requestingElement =
mScriptGlobal->AsOuter()->GetFrameElementInternal();
requestingContext = requestingElement; requestingContext = requestingElement;
} }
} else {
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 // Since Content Policy checks are performed within docShell as well as
// the ContentSecurityManager we need a reliable way to let certain // the ContentSecurityManager we need a reliable way to let certain
@ -10911,17 +10900,40 @@ nsDocShell::DoURILoad(nsIURI* aURI,
nsCOMPtr<nsINode> loadingNode; nsCOMPtr<nsINode> loadingNode;
nsCOMPtr<nsPIDOMWindowOuter> loadingWindow; nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
nsCOMPtr<nsIPrincipal> loadingPrincipal; nsCOMPtr<nsIPrincipal> loadingPrincipal;
nsCOMPtr<nsISupports> topLevelLoadingContext;
if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) { if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
loadingNode = nullptr; loadingNode = nullptr;
loadingPrincipal = nullptr; loadingPrincipal = nullptr;
loadingWindow = mScriptGlobal->AsOuter(); 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 { } else {
loadingWindow = nullptr; loadingWindow = nullptr;
loadingNode = mScriptGlobal->AsOuter()->GetFrameElementInternal(); loadingNode = mScriptGlobal->AsOuter()->GetFrameElementInternal();
if (loadingNode) { if (loadingNode) {
// If we have a loading node, then use that as our loadingPrincipal. // If we have a loading node, then use that as our loadingPrincipal.
loadingPrincipal = loadingNode->NodePrincipal(); 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 { } else {
// If this isn't a top-level load and mScriptGlobal's frame element is // 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 // null, then the element got removed from the DOM while we were trying
@ -10971,7 +10983,7 @@ nsDocShell::DoURILoad(nsIURI* aURI,
nsCOMPtr<nsILoadInfo> loadInfo = nsCOMPtr<nsILoadInfo> loadInfo =
(aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ? (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ?
new LoadInfo(loadingWindow, aTriggeringPrincipal, new LoadInfo(loadingWindow, aTriggeringPrincipal, topLevelLoadingContext,
securityFlags) : securityFlags) :
new LoadInfo(loadingPrincipal, aTriggeringPrincipal, loadingNode, new LoadInfo(loadingPrincipal, aTriggeringPrincipal, loadingNode,
securityFlags, aContentPolicyType); securityFlags, aContentPolicyType);

View file

@ -20,6 +20,7 @@
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
#include "nsIDOMNode.h" #include "nsIDOMNode.h"
#include "nsIDOMWindow.h" #include "nsIDOMWindow.h"
#include "nsITabChild.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsILoadContext.h" #include "nsILoadContext.h"
#include "nsCOMArray.h" #include "nsCOMArray.h"
@ -89,8 +90,9 @@ nsContentPolicy::CheckPolicy(CPMethod policyMethod,
{ {
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(requestingContext)); nsCOMPtr<nsIDOMNode> node(do_QueryInterface(requestingContext));
nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext)); nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext));
NS_ASSERTION(!requestingContext || node || window, nsCOMPtr<nsITabChild> tabChild(do_QueryInterface(requestingContext));
"Context should be a DOM node or a DOM window!"); NS_ASSERTION(!requestingContext || node || window || tabChild,
"Context should be a DOM node, DOM window or a tabChild!");
} }
#endif #endif

View file

@ -253,7 +253,7 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
nsContentPolicyType internalContentPolicyType = nsContentPolicyType internalContentPolicyType =
aLoadInfo->InternalContentPolicyType(); aLoadInfo->InternalContentPolicyType();
nsCString mimeTypeGuess; nsCString mimeTypeGuess;
nsCOMPtr<nsINode> requestingContext = nullptr; nsCOMPtr<nsISupports> requestingContext = nullptr;
#ifdef DEBUG #ifdef DEBUG
// Don't enforce TYPE_DOCUMENT assertions for loads // Don't enforce TYPE_DOCUMENT assertions for loads
@ -327,10 +327,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
case nsIContentPolicy::TYPE_XMLHTTPREQUEST: { case nsIContentPolicy::TYPE_XMLHTTPREQUEST: {
// alias nsIContentPolicy::TYPE_DATAREQUEST: // alias nsIContentPolicy::TYPE_DATAREQUEST:
requestingContext = aLoadInfo->LoadingNode(); requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext || #ifdef DEBUG
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, {
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"type_xml requires requestingContext of type Document"); "type_xml requires requestingContext of type Document");
}
#endif
// We're checking for the external TYPE_XMLHTTPREQUEST here in case // We're checking for the external TYPE_XMLHTTPREQUEST here in case
// an addon creates a request with that type. // an addon creates a request with that type.
if (internalContentPolicyType == if (internalContentPolicyType ==
@ -351,18 +354,26 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: { case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST: {
mimeTypeGuess = EmptyCString(); mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode(); requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext || #ifdef DEBUG
requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, {
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
"type_subrequest requires requestingContext of type Element"); "type_subrequest requires requestingContext of type Element");
}
#endif
break; break;
} }
case nsIContentPolicy::TYPE_DTD: { case nsIContentPolicy::TYPE_DTD: {
mimeTypeGuess = EmptyCString(); mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode(); requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext || #ifdef DEBUG
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, {
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"type_dtd requires requestingContext of type Document"); "type_dtd requires requestingContext of type Document");
}
#endif
break; break;
} }
@ -380,9 +391,13 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
mimeTypeGuess = EmptyCString(); mimeTypeGuess = EmptyCString();
} }
requestingContext = aLoadInfo->LoadingNode(); requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext || #ifdef DEBUG
requestingContext->NodeType() == nsIDOMNode::ELEMENT_NODE, {
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::ELEMENT_NODE,
"type_media requires requestingContext of type Element"); "type_media requires requestingContext of type Element");
}
#endif
break; break;
} }
@ -409,18 +424,26 @@ DoContentSecurityChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo)
case nsIContentPolicy::TYPE_XSLT: { case nsIContentPolicy::TYPE_XSLT: {
mimeTypeGuess = NS_LITERAL_CSTRING("application/xml"); mimeTypeGuess = NS_LITERAL_CSTRING("application/xml");
requestingContext = aLoadInfo->LoadingNode(); requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext || #ifdef DEBUG
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, {
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"type_xslt requires requestingContext of type Document"); "type_xslt requires requestingContext of type Document");
}
#endif
break; break;
} }
case nsIContentPolicy::TYPE_BEACON: { case nsIContentPolicy::TYPE_BEACON: {
mimeTypeGuess = EmptyCString(); mimeTypeGuess = EmptyCString();
requestingContext = aLoadInfo->LoadingNode(); requestingContext = aLoadInfo->LoadingNode();
MOZ_ASSERT(!requestingContext || #ifdef DEBUG
requestingContext->NodeType() == nsIDOMNode::DOCUMENT_NODE, {
nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext);
MOZ_ASSERT(!node || node->NodeType() == nsIDOMNode::DOCUMENT_NODE,
"type_beacon requires requestingContext of type Document"); "type_beacon requires requestingContext of type Document");
}
#endif
break; break;
} }

View file

@ -48,6 +48,7 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
aTriggeringPrincipal : mLoadingPrincipal.get()) aTriggeringPrincipal : mLoadingPrincipal.get())
, mPrincipalToInherit(nullptr) , mPrincipalToInherit(nullptr)
, mLoadingContext(do_GetWeakReference(aLoadingContext)) , mLoadingContext(do_GetWeakReference(aLoadingContext))
, mContextForTopLevelLoad(nullptr)
, mSecurityFlags(aSecurityFlags) , mSecurityFlags(aSecurityFlags)
, mInternalContentPolicyType(aContentPolicyType) , mInternalContentPolicyType(aContentPolicyType)
, mTainting(LoadTainting::Basic) , mTainting(LoadTainting::Basic)
@ -218,10 +219,12 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadingPrincipal,
*/ */
LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow, LoadInfo::LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aTriggeringPrincipal,
nsISupports* aContextForTopLevelLoad,
nsSecurityFlags aSecurityFlags) nsSecurityFlags aSecurityFlags)
: mLoadingPrincipal(nullptr) : mLoadingPrincipal(nullptr)
, mTriggeringPrincipal(aTriggeringPrincipal) , mTriggeringPrincipal(aTriggeringPrincipal)
, mPrincipalToInherit(nullptr) , mPrincipalToInherit(nullptr)
, mContextForTopLevelLoad(do_GetWeakReference(aContextForTopLevelLoad))
, mSecurityFlags(aSecurityFlags) , mSecurityFlags(aSecurityFlags)
, mInternalContentPolicyType(nsIContentPolicy::TYPE_DOCUMENT) , mInternalContentPolicyType(nsIContentPolicy::TYPE_DOCUMENT)
, mTainting(LoadTainting::Basic) , mTainting(LoadTainting::Basic)
@ -281,6 +284,7 @@ LoadInfo::LoadInfo(const LoadInfo& rhs)
, mTriggeringPrincipal(rhs.mTriggeringPrincipal) , mTriggeringPrincipal(rhs.mTriggeringPrincipal)
, mPrincipalToInherit(rhs.mPrincipalToInherit) , mPrincipalToInherit(rhs.mPrincipalToInherit)
, mLoadingContext(rhs.mLoadingContext) , mLoadingContext(rhs.mLoadingContext)
, mContextForTopLevelLoad(rhs.mContextForTopLevelLoad)
, mSecurityFlags(rhs.mSecurityFlags) , mSecurityFlags(rhs.mSecurityFlags)
, mInternalContentPolicyType(rhs.mInternalContentPolicyType) , mInternalContentPolicyType(rhs.mInternalContentPolicyType)
, mTainting(rhs.mTainting) , mTainting(rhs.mTainting)
@ -488,6 +492,17 @@ LoadInfo::LoadingNode()
return node; 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 NS_IMETHODIMP
LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult) LoadInfo::GetSecurityFlags(nsSecurityFlags* aResult)
{ {

View file

@ -59,10 +59,12 @@ public:
nsSecurityFlags aSecurityFlags, nsSecurityFlags aSecurityFlags,
nsContentPolicyType aContentPolicyType); nsContentPolicyType aContentPolicyType);
// Constructor used for TYPE_DOCUMENT loads which have no reasonable // Constructor used for TYPE_DOCUMENT loads which have a different
// loadingNode or loadingPrincipal // loadingContext than other loads. This ContextForTopLevelLoad is
// only used for content policy checks.
LoadInfo(nsPIDOMWindowOuter* aOuterWindow, LoadInfo(nsPIDOMWindowOuter* aOuterWindow,
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aTriggeringPrincipal,
nsISupports* aContextForTopLevelLoad,
nsSecurityFlags aSecurityFlags); nsSecurityFlags aSecurityFlags);
// create an exact copy of the loadinfo // create an exact copy of the loadinfo
@ -134,6 +136,7 @@ private:
nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
nsCOMPtr<nsIPrincipal> mPrincipalToInherit; nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
nsWeakPtr mLoadingContext; nsWeakPtr mLoadingContext;
nsWeakPtr mContextForTopLevelLoad;
nsSecurityFlags mSecurityFlags; nsSecurityFlags mSecurityFlags;
nsContentPolicyType mInternalContentPolicyType; nsContentPolicyType mInternalContentPolicyType;
LoadTainting mTainting; LoadTainting mTainting;

View file

@ -323,6 +323,16 @@ interface nsILoadInfo : nsISupports
[noscript, notxpcom, nostdcall, binaryname(LoadingNode)] [noscript, notxpcom, nostdcall, binaryname(LoadingNode)]
nsINode binaryLoadingNode(); 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. * The securityFlags of that channel.
*/ */