Bug 696301 part 3. Propagate the CORS mode to the script loader correctly; make sure the CORS mode of script preloads matches the actual load. r=sicking

This commit is contained in:
Boris Zbarsky 2012-03-10 10:13:52 -06:00
parent 7b4e2a3a45
commit 333a19ad97
8 changed files with 102 additions and 22 deletions

View File

@ -47,6 +47,7 @@
#include "nsIParser.h"
#include "nsContentCreatorFunctions.h"
#include "nsIDOMHTMLScriptElement.h"
#include "mozilla/CORSMode.h"
#define NS_ISCRIPTELEMENT_IID \
{ 0x24ab3ff2, 0xd75e, 0x4be4, \
@ -258,6 +259,15 @@ public:
return block;
}
/**
* Get the CORS mode of the script element
*/
virtual mozilla::CORSMode GetCORSMode() const
{
/* Default to no CORS */
return mozilla::CORS_NONE;
}
protected:
/**
* Processes the script if it's in the document-tree and links to or

View File

@ -6269,6 +6269,16 @@ nsGenericElement::StringToCORSMode(const nsAString& aValue)
return CORSMode(val.GetEnumValue());
}
/* static */ CORSMode
nsGenericElement::AttrValueToCORSMode(const nsAttrValue* aValue)
{
if (!aValue) {
return CORS_NONE;
}
return CORSMode(aValue->GetEnumValue());
}
#define EVENT(name_, id_, type_, struct_) \
NS_IMETHODIMP nsINode::GetOn##name_(JSContext *cx, jsval *vp) { \
nsEventListenerManager *elm = GetListenerManager(false); \

View File

@ -654,6 +654,12 @@ public:
*/
static mozilla::CORSMode StringToCORSMode(const nsAString& aValue);
/**
* Return the CORS mode for a given nsAttrValue (which may be null,
* but if not should have been parsed via ParseCORSValue).
*/
static mozilla::CORSMode AttrValueToCORSMode(const nsAttrValue* aValue);
protected:
/*
* Named-bools for use with SetAttrAndNotify to make call sites easier to

View File

@ -74,13 +74,16 @@
#include "nsChannelPolicy.h"
#include "nsCRT.h"
#include "nsContentCreatorFunctions.h"
#include "nsGenericElement.h"
#include "mozilla/FunctionTimer.h"
#include "mozilla/CORSMode.h"
#ifdef PR_LOGGING
static PRLogModuleInfo* gCspPRLog;
#endif
using namespace mozilla;
using namespace mozilla::dom;
//////////////////////////////////////////////////////////////
@ -90,11 +93,14 @@ using namespace mozilla::dom;
class nsScriptLoadRequest : public nsISupports {
public:
nsScriptLoadRequest(nsIScriptElement* aElement,
PRUint32 aVersion)
PRUint32 aVersion,
CORSMode aCORSMode)
: mElement(aElement),
mLoading(true),
mIsInline(true),
mJSVersion(aVersion), mLineNo(1)
mJSVersion(aVersion),
mLineNo(1),
mCORSMode(aCORSMode)
{
}
@ -122,6 +128,7 @@ public:
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mOriginPrincipal;
PRInt32 mLineNo;
const CORSMode mCORSMode;
};
// The nsScriptLoadRequest is passed as the context to necko, and thus
@ -551,6 +558,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
if (!scriptURI) {
return false;
}
CORSMode ourCORSMode = aElement->GetCORSMode();
nsTArray<PreloadInfo>::index_type i =
mPreloads.IndexOf(scriptURI.get(), 0, PreloadURIComparator());
if (i != nsTArray<PreloadInfo>::NoIndex) {
@ -565,7 +573,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
// the charset we have now.
nsAutoString elementCharset;
aElement->GetScriptCharset(elementCharset);
if (elementCharset.Equals(preloadCharset)) {
if (elementCharset.Equals(preloadCharset) &&
ourCORSMode == request->mCORSMode) {
rv = CheckContentPolicy(mDocument, aElement, request->mURI, type);
NS_ENSURE_SUCCESS(rv, false);
} else {
@ -576,7 +585,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
if (!request) {
// no usable preload
request = new nsScriptLoadRequest(aElement, version);
request = new nsScriptLoadRequest(aElement, version, ourCORSMode);
request->mURI = scriptURI;
request->mIsInline = false;
request->mLoading = true;
@ -697,7 +706,8 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
}
}
request = new nsScriptLoadRequest(aElement, version);
// Inline scripts ignore ther CORS mode and are always CORS_NONE
request = new nsScriptLoadRequest(aElement, version, CORS_NONE);
request->mJSVersion = version;
request->mLoading = false;
request->mIsInline = true;
@ -1333,7 +1343,9 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset,
return;
}
nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(nsnull, 0);
nsRefPtr<nsScriptLoadRequest> request =
new nsScriptLoadRequest(nsnull, 0,
nsGenericElement::StringToCORSMode(aCrossOrigin));
request->mURI = aURI;
request->mIsInline = false;
request->mLoading = true;

View File

@ -663,12 +663,5 @@ nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const
CORSMode
nsHTMLImageElement::GetCORSMode()
{
const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossorigin);
if (value) {
NS_ASSERTION(value->Type() == nsAttrValue::eEnum,
"Why is this not an enum value?");
return CORSMode(value->GetEnumValue());
}
return CORS_NONE;
return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
}

View File

@ -951,14 +951,7 @@ nsresult nsHTMLMediaElement::LoadResource()
}
// Set the media element's CORS mode only when loading a resource
// By default, it's CORS_NONE
mCORSMode = CORS_NONE;
const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossorigin);
if (value) {
NS_ASSERTION(value->Type() == nsAttrValue::eEnum,
"Why is this not an enum value?");
mCORSMode = CORSMode(value->GetEnumValue());
}
mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
nsHTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc);
if (other) {

View File

@ -57,6 +57,7 @@
#include "nsTArray.h"
#include "nsDOMJSUtils.h"
using namespace mozilla;
using namespace mozilla::dom;
class nsHTMLScriptElement : public nsGenericHTMLElement,
@ -108,11 +109,16 @@ public:
virtual void GetScriptText(nsAString& text);
virtual void GetScriptCharset(nsAString& charset);
virtual void FreezeUriAsyncDefer();
virtual CORSMode GetCORSMode() const;
// nsIContent
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers);
virtual bool ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
@ -178,6 +184,22 @@ nsHTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
return NS_OK;
}
bool
nsHTMLScriptElement::ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::crossorigin) {
ParseCORSValue(aValue, aResult);
return true;
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}
nsresult
nsHTMLScriptElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
{
@ -311,6 +333,12 @@ nsHTMLScriptElement::FreezeUriAsyncDefer()
mFrozen = true;
}
CORSMode
nsHTMLScriptElement::GetCORSMode() const
{
return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
}
bool
nsHTMLScriptElement::HasScriptContent()
{

View File

@ -86,6 +86,7 @@ public:
virtual void GetScriptText(nsAString& text);
virtual void GetScriptCharset(nsAString& charset);
virtual void FreezeUriAsyncDefer();
virtual CORSMode GetCORSMode() const;
// nsScriptElement
virtual bool HasScriptContent();
@ -96,6 +97,10 @@ public:
bool aCompileEventHandlers);
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
const nsAttrValue* aValue, bool aNotify);
virtual bool ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
@ -288,3 +293,26 @@ nsSVGScriptElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
return nsSVGScriptElementBase::AfterSetAttr(aNamespaceID, aName,
aValue, aNotify);
}
bool
nsSVGScriptElement::ParseAttribute(PRInt32 aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None &&
aAttribute == nsGkAtoms::crossorigin) {
ParseCORSValue(aValue, aResult);
return true;
}
return nsSVGScriptElementBase::ParseAttribute(aNamespaceID, aAttribute,
aValue, aResult);
}
CORSMode
nsSVGScriptElement::GetCORSMode() const
{
return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
}