# HG changeset patch # Parent 6017b2bb77e28406772175f33ba8628329e83c3c diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -251,16 +251,17 @@ GK_ATOM(control, "control") #ifdef MOZ_MEDIA GK_ATOM(controls, "controls") #endif GK_ATOM(coords, "coords") GK_ATOM(copy, "copy") GK_ATOM(copyOf, "copy-of") GK_ATOM(count, "count") GK_ATOM(crop, "crop") +GK_ATOM(crossOrigin, "crossOrigin") GK_ATOM(curpos, "curpos") GK_ATOM(current, "current") GK_ATOM(currentloop, "currentloop") GK_ATOM(cycler, "cycler") GK_ATOM(data, "data") GK_ATOM(datalist, "datalist") GK_ATOM(dataType, "data-type") GK_ATOM(dateTime, "date-time") diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -714,23 +714,31 @@ nsImageLoadingContent::LoadImage(nsIURI* nsContentUtils::CanLoadImage(aNewURI, this, aDocument, aDocument->NodePrincipal(), &cpDecision); if (!NS_CP_ACCEPTED(cpDecision)) { FireEvent(NS_LITERAL_STRING("error")); SetBlockedRequest(aNewURI, cpDecision); return NS_OK; } + nsLoadFlags loadFlags = aLoadFlags; + PRInt32 corsmode = GetCORSMode(); + if (corsmode == nsImageLoadingContent::CORS_ANONYMOUS) { + loadFlags |= imgILoader::LOAD_CORS_ANONYMOUS; + } else if (corsmode == nsImageLoadingContent::CORS_USE_CREDENTIALS) { + loadFlags |= imgILoader::LOAD_CORS_USE_CREDENTIALS; + } + // Not blocked. Do the load. nsCOMPtr& req = PrepareNextRequest(); nsresult rv; rv = nsContentUtils::LoadImage(aNewURI, aDocument, aDocument->NodePrincipal(), aDocument->GetDocumentURI(), - this, aLoadFlags, + this, loadFlags, getter_AddRefs(req)); if (NS_SUCCEEDED(rv)) { TrackImage(req); } else { // If we don't have a current URI, we might as well store this URI so people // know what we tried (and failed) to load. if (!mCurrentRequest) mCurrentURI = aNewURI; @@ -1081,8 +1089,13 @@ nsImageLoadingContent::CreateStaticImage aDest->mStateChangerDepth = mStateChangerDepth; aDest->mIsImageStateForced = mIsImageStateForced; aDest->mLoading = mLoading; aDest->mBroken = mBroken; aDest->mUserDisabled = mUserDisabled; aDest->mSuppressed = mSuppressed; } +nsImageLoadingContent::CORSMode +nsImageLoadingContent::GetCORSMode() +{ + return CORS_NONE; +} diff --git a/content/base/src/nsImageLoadingContent.h b/content/base/src/nsImageLoadingContent.h --- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -64,16 +64,35 @@ class nsImageLoadingContent : public nsI public: nsImageLoadingContent(); virtual ~nsImageLoadingContent(); NS_DECL_IMGICONTAINEROBSERVER NS_DECL_IMGIDECODEROBSERVER NS_DECL_NSIIMAGELOADINGCONTENT + enum CORSMode { + /** + * The default of not using CORS to validate cross-origin loads. + */ + CORS_NONE, + + /** + * Validate cross-site loads using CORS, but do not send any credentials + * (cookies, HTTP auth logins, etc) along with the request. + */ + CORS_ANONYMOUS, + + /** + * Validate cross-site loads using CORS, and send credentials such as cookies + * and HTTP auth logins along with the request. + */ + CORS_USE_CREDENTIALS + }; + protected: /** * LoadImage is called by subclasses when the appropriate * attributes (eg 'src' for tags) change. The string passed * in is the new uri string; this consolidates the code for getting * the charset, constructing URI objects, and any other incidentals * into this superclass. * @@ -154,16 +173,22 @@ protected: void ClearBrokenState() { mBroken = PR_FALSE; } PRBool LoadingEnabled() { return mLoadingEnabled; } // Sets blocking state only if the desired state is different from the // current one. See the comment for mBlockingOnload for more information. void SetBlockingOnload(PRBool aBlocking); + /** + * Returns the CORS mode that will be used for all future image loads. The + * default implementation returns CORS_NONE unconditionally. + */ + virtual CORSMode GetCORSMode(); + private: /** * Struct used to manage the image observers. */ struct ImageObserver { ImageObserver(imgIDecoderObserver* aObserver) : mObserver(aObserver), mNext(nsnull) diff --git a/content/html/content/src/nsHTMLImageElement.cpp b/content/html/content/src/nsHTMLImageElement.cpp --- a/content/html/content/src/nsHTMLImageElement.cpp +++ b/content/html/content/src/nsHTMLImageElement.cpp @@ -103,16 +103,19 @@ public: NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::) // nsIDOMHTMLImageElement NS_DECL_NSIDOMHTMLIMAGEELEMENT // override from nsGenericHTMLElement NS_IMETHOD GetDraggable(PRBool* aDraggable); + // override from nsImageLoadingContent + nsImageLoadingContent::CORSMode GetCORSMode(); + // nsIJSNativeInitializer NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext, JSObject* aObj, PRUint32 argc, jsval* argv); // nsIContent virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute, const nsAString& aValue, @@ -220,16 +223,27 @@ NS_IMPL_STRING_ATTR(nsHTMLImageElement, NS_IMPL_INT_ATTR(nsHTMLImageElement, Hspace, hspace) NS_IMPL_BOOL_ATTR(nsHTMLImageElement, IsMap, ismap) NS_IMPL_URI_ATTR(nsHTMLImageElement, LongDesc, longdesc) NS_IMPL_STRING_ATTR(nsHTMLImageElement, Lowsrc, lowsrc) NS_IMPL_URI_ATTR(nsHTMLImageElement, Src, src) NS_IMPL_STRING_ATTR(nsHTMLImageElement, UseMap, usemap) NS_IMPL_INT_ATTR(nsHTMLImageElement, Vspace, vspace) +static const nsAttrValue::EnumTable kCrossOriginTable[] = { + { "", nsImageLoadingContent::CORS_NONE }, + { "anonymous", nsImageLoadingContent::CORS_ANONYMOUS }, + { "use-credentials", nsImageLoadingContent::CORS_USE_CREDENTIALS }, + { 0 } +}; +// Default crossOrigin mode is CORS_NONE. +static const nsAttrValue::EnumTable* kCrossOriginDefault = &kCrossOriginTable[0]; + +NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(nsHTMLImageElement, CrossOrigin, crossOrigin, kCrossOriginDefault->tag) + NS_IMETHODIMP nsHTMLImageElement::GetDraggable(PRBool* aDraggable) { // images may be dragged unless the draggable attribute is false *aDraggable = !AttrValueIs(kNameSpaceID_None, nsGkAtoms::draggable, nsGkAtoms::_false, eIgnoreCase); return NS_OK; } @@ -331,16 +345,19 @@ nsHTMLImageElement::ParseAttribute(PRInt nsIAtom* aAttribute, const nsAString& aValue, nsAttrValue& aResult) { if (aNamespaceID == kNameSpaceID_None) { if (aAttribute == nsGkAtoms::align) { return ParseAlignValue(aValue, aResult); } + if (aAttribute == nsGkAtoms::crossOrigin) { + return aResult.ParseEnumValue(aValue, kCrossOriginTable, PR_FALSE); + } if (ParseImageAttribute(aAttribute, aValue, aResult)) { return PR_TRUE; } } return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue, aResult); } @@ -620,8 +637,21 @@ nsHTMLImageElement::GetNaturalWidth(PRIn nsresult nsHTMLImageElement::CopyInnerTo(nsGenericElement* aDest) const { if (aDest->GetOwnerDoc()->IsStaticDocument()) { CreateStaticImageClone(static_cast(aDest)); } return nsGenericHTMLElement::CopyInnerTo(aDest); } + +nsImageLoadingContent::CORSMode +nsHTMLImageElement::GetCORSMode() +{ + nsImageLoadingContent::CORSMode ret = nsImageLoadingContent::CORS_NONE; + + const nsAttrValue* value = GetParsedAttr(nsGkAtoms::crossOrigin); + if (value && value->Type() == nsAttrValue::eEnum) { + ret = (nsImageLoadingContent::CORSMode) value->GetEnumValue(); + } + + return ret; +} diff --git a/dom/interfaces/html/nsIDOMHTMLImageElement.idl b/dom/interfaces/html/nsIDOMHTMLImageElement.idl --- a/dom/interfaces/html/nsIDOMHTMLImageElement.idl +++ b/dom/interfaces/html/nsIDOMHTMLImageElement.idl @@ -45,21 +45,22 @@ * * This interface is trying to follow the DOM Level 2 HTML specification: * http://www.w3.org/TR/DOM-Level-2-HTML/ * * with changes from the work-in-progress WHATWG HTML specification: * http://www.whatwg.org/specs/web-apps/current-work/ */ -[scriptable, uuid(cf8a8744-ec3b-474e-8f2b-8def3da2344a)] +[scriptable, uuid(ce760602-0528-493d-966d-65d4ee52347d)] interface nsIDOMHTMLImageElement : nsIDOMHTMLElement { attribute DOMString alt; attribute DOMString src; + attribute DOMString crossOrigin; attribute DOMString useMap; attribute boolean isMap; attribute long width; attribute long height; readonly attribute long naturalWidth; readonly attribute long naturalHeight; readonly attribute boolean complete; diff --git a/toolkit/system/gnome/nsAlertsIconListener.cpp b/toolkit/system/gnome/nsAlertsIconListener.cpp --- a/toolkit/system/gnome/nsAlertsIconListener.cpp +++ b/toolkit/system/gnome/nsAlertsIconListener.cpp @@ -257,17 +257,17 @@ nsAlertsIconListener::StartRequest(const NS_NewURI(getter_AddRefs(imageUri), aImageUrl); if (!imageUri) return ShowAlert(NULL); nsCOMPtr il(do_GetService("@mozilla.org/image/loader;1")); if (!il) return ShowAlert(NULL); - return il->LoadImage(imageUri, nsnull, nsnull, nsnull, this, + return il->LoadImage(imageUri, nsnull, nsnull, nsnull, nsnull, this, nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull, nsnull, getter_AddRefs(mIconRequest)); } void nsAlertsIconListener::SendCallback() { if (mAlertListener)