From 4514600c1adae976781be422bf393161f1ed0f7b Mon Sep 17 00:00:00 2001 From: John Schoenick Date: Tue, 19 Aug 2014 14:49:38 -0700 Subject: [PATCH] Bug 1055750 - Part 3 - Track image vs imageset request load type through ImageLoadingContent::LoadImage r=bz,tanvi --- content/base/public/nsIContentPolicy.idl | 7 +- .../base/public/nsIImageLoadingContent.idl | 5 +- content/base/src/nsContentUtils.cpp | 3 +- content/base/src/nsGenConImageContent.cpp | 2 +- content/base/src/nsImageLoadingContent.cpp | 103 +++++++++++++----- content/base/src/nsImageLoadingContent.h | 54 +++++++-- content/html/content/src/HTMLImageElement.cpp | 21 ++-- content/html/content/src/HTMLInputElement.cpp | 6 +- content/svg/content/src/SVGFEImageElement.cpp | 2 +- content/svg/content/src/SVGImageElement.cpp | 2 +- dom/webidl/HTMLImageElement.webidl | 2 +- embedding/browser/nsContextMenuInfo.cpp | 5 +- image/public/imgILoader.idl | 12 +- image/src/imgLoader.cpp | 37 +++++-- image/src/imgLoader.h | 7 +- layout/generic/nsImageFrame.cpp | 4 +- widget/cocoa/OSXNotificationCenter.mm | 3 +- widget/cocoa/nsMenuItemIconX.mm | 4 +- 18 files changed, 204 insertions(+), 75 deletions(-) diff --git a/content/base/public/nsIContentPolicy.idl b/content/base/public/nsIContentPolicy.idl index 9fe0b885ad15..d25e621c9a44 100644 --- a/content/base/public/nsIContentPolicy.idl +++ b/content/base/public/nsIContentPolicy.idl @@ -24,9 +24,14 @@ typedef unsigned long nsContentPolicyType; * by launching a dialog to prompt the user for something). */ -[scriptable,uuid(d8210e91-1970-4230-88ef-74b6fdc418cf)] +[scriptable,uuid(94513f07-d559-480e-8879-6249852365ea)] interface nsIContentPolicy : nsISupports { + /** + * Indicates a unset or bogus policy type. + */ + const nsContentPolicyType TYPE_INVALID = 0; + /** * Gecko/Firefox developers: Do not use TYPE_OTHER under any circumstances. * diff --git a/content/base/public/nsIImageLoadingContent.idl b/content/base/public/nsIImageLoadingContent.idl index 001b47e19e5b..3c3594054e16 100644 --- a/content/base/public/nsIImageLoadingContent.idl +++ b/content/base/public/nsIImageLoadingContent.idl @@ -37,7 +37,7 @@ interface nsIFrame; * interface to mirror this interface when changing it. */ -[scriptable, builtinclass, uuid(256a5283-ebb5-4430-8e15-5ada92156ef7)] +[scriptable, builtinclass, uuid(ce098f6c-baca-4178-a9aa-266e8bfe509b)] interface nsIImageLoadingContent : imgINotificationObserver { /** @@ -149,9 +149,10 @@ interface nsIImageLoadingContent : imgINotificationObserver /** * forceReload forces reloading of the image pointed to by currentURI * + * @param aNotify [optional] request should notify, defaults to true * @throws NS_ERROR_NOT_AVAILABLE if there is no current URI to reload */ - void forceReload(); + [optional_argc] void forceReload([optional] in boolean aNotify /* = true */); /** * Enables/disables image state forcing. When |aForce| is PR_TRUE, we force diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 427ddd97e956..a034e81efef4 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -3020,7 +3020,8 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument, aObserver, /* imgINotificationObserver */ aLoadingDocument, /* uniquification key */ aLoadFlags, /* load flags */ - nullptr, /* cache key */ + nullptr, /* cache key */ + aContentPolicyType, /* content policy type */ initiatorType, /* the load initiator */ aRequest); } diff --git a/content/base/src/nsGenConImageContent.cpp b/content/base/src/nsGenConImageContent.cpp index 22cacb6c3d25..4ecf26709fde 100644 --- a/content/base/src/nsGenConImageContent.cpp +++ b/content/base/src/nsGenConImageContent.cpp @@ -35,7 +35,7 @@ public: nsresult Init(imgRequestProxy* aImageRequest) { // No need to notify, since we have no frame. - return UseAsPrimaryRequest(aImageRequest, false); + return UseAsPrimaryRequest(aImageRequest, false, eImageLoadType_Normal); } // nsIContent overrides diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp index f23c392e6204..e48c451f465b 100644 --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -522,6 +522,19 @@ nsImageLoadingContent::FrameDestroyed(nsIFrame* aFrame) } } +/* static */ +nsContentPolicyType +nsImageLoadingContent::PolicyTypeForLoad(ImageLoadType aImageLoadType) +{ + if (aImageLoadType == eImageLoadType_Imageset) { + return nsIContentPolicy::TYPE_IMAGESET; + } + + MOZ_ASSERT(aImageLoadType == eImageLoadType_Normal, + "Unknown ImageLoadType type in PolicyTypeForLoad"); + return nsIContentPolicy::TYPE_IMAGE; +} + int32_t nsImageLoadingContent::GetRequestType(imgIRequest* aRequest, ErrorResult& aError) @@ -600,7 +613,7 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel, // Do the load. nsCOMPtr listener; - nsRefPtr& req = PrepareNextRequest(); + nsRefPtr& req = PrepareNextRequest(eImageLoadType_Normal); nsresult rv = nsContentUtils::GetImgLoaderForChannel(aChannel)-> LoadImageWithChannel(aChannel, this, doc, getter_AddRefs(listener), @@ -632,7 +645,8 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel, } void -nsImageLoadingContent::ForceReload(ErrorResult& aError) +nsImageLoadingContent::ForceReload(const mozilla::dom::Optional& aNotify, + mozilla::ErrorResult& aError) { nsCOMPtr currentURI; GetCurrentURI(getter_AddRefs(currentURI)); @@ -641,16 +655,32 @@ nsImageLoadingContent::ForceReload(ErrorResult& aError) return; } - nsresult rv = LoadImage(currentURI, true, true, nullptr, nsIRequest::VALIDATE_ALWAYS); + // defaults to true + bool notify = !aNotify.WasPassed() || aNotify.Value(); + + // We keep this flag around along with the old URI even for failed requests + // without a live request object + ImageLoadType loadType = \ + (mCurrentRequestFlags & REQUEST_IS_IMAGESET) ? eImageLoadType_Imageset + : eImageLoadType_Normal; + nsresult rv = LoadImage(currentURI, true, notify, loadType, nullptr, + nsIRequest::VALIDATE_ALWAYS); if (NS_FAILED(rv)) { aError.Throw(rv); } } -NS_IMETHODIMP nsImageLoadingContent::ForceReload() +NS_IMETHODIMP +nsImageLoadingContent::ForceReload(bool aNotify /* = true */, + uint8_t aArgc) { + mozilla::dom::Optional notify; + if (aArgc >= 1) { + notify.Construct() = aNotify; + } + ErrorResult result; - ForceReload(result); + ForceReload(notify, result); return result.ErrorCode(); } @@ -735,7 +765,8 @@ nsImageLoadingContent::GetVisibleCount() nsresult nsImageLoadingContent::LoadImage(const nsAString& aNewURI, bool aForce, - bool aNotify) + bool aNotify, + ImageLoadType aImageLoadType) { // First, get a document (needed for security checks and the like) nsIDocument* doc = GetOurOwnerDoc(); @@ -758,9 +789,9 @@ nsImageLoadingContent::LoadImage(const nsAString& aNewURI, // Loading an embedded img from the same URI as the document URI will not work // as a resource cannot recursively embed itself. Attempting to do so generally - // results in having to pre-emptively close down an in-flight HTTP transaction + // results in having to pre-emptively close down an in-flight HTTP transaction // and then incurring the significant cost of establishing a new TCP channel. - // This is generally triggered from + // This is generally triggered from // In light of that, just skip loading it.. // Do make sure to drop our existing image, if any CancelImageRequests(aNotify); @@ -769,13 +800,14 @@ nsImageLoadingContent::LoadImage(const nsAString& aNewURI, NS_TryToSetImmutable(imageURI); - return LoadImage(imageURI, aForce, aNotify, doc); + return LoadImage(imageURI, aForce, aNotify, aImageLoadType, doc); } nsresult nsImageLoadingContent::LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify, + ImageLoadType aImageLoadType, nsIDocument* aDocument, nsLoadFlags aLoadFlags) { @@ -829,11 +861,14 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI, // Are we blocked? int16_t cpDecision = nsIContentPolicy::REJECT_REQUEST; + nsContentPolicyType policyType = PolicyTypeForLoad(aImageLoadType); + nsContentUtils::CanLoadImage(aNewURI, static_cast(this), aDocument, aDocument->NodePrincipal(), - &cpDecision); + &cpDecision, + policyType); if (!NS_CP_ACCEPTED(cpDecision)) { FireEvent(NS_LITERAL_STRING("error")); SetBlockedRequest(aNewURI, cpDecision); @@ -849,7 +884,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI, } // Not blocked. Do the load. - nsRefPtr& req = PrepareNextRequest(); + nsRefPtr& req = PrepareNextRequest(aImageLoadType); nsCOMPtr content = do_QueryInterface(static_cast(this)); nsresult rv; @@ -858,7 +893,8 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI, aDocument->GetDocumentURI(), this, loadFlags, content->LocalName(), - getter_AddRefs(req)); + getter_AddRefs(req), + policyType); if (NS_SUCCEEDED(rv)) { TrackImage(req); @@ -982,14 +1018,14 @@ nsImageLoadingContent::UpdateImageState(bool aNotify) // XXX - This machinery should be removed after bug 521604. return; } - + nsCOMPtr thisContent = do_QueryInterface(static_cast(this)); if (!thisContent) { return; } mLoading = mBroken = mUserDisabled = mSuppressed = false; - + // If we were blocked by server-based content policy, we claim to be // suppressed. If we were blocked by type-based content policy, we claim to // be user-disabled. Otherwise, claim to be broken. @@ -1024,7 +1060,8 @@ nsImageLoadingContent::CancelImageRequests(bool aNotify) nsresult nsImageLoadingContent::UseAsPrimaryRequest(imgRequestProxy* aRequest, - bool aNotify) + bool aNotify, + ImageLoadType aImageLoadType) { // Our state will change. Watch it. AutoStateChanger changer(this, aNotify); @@ -1034,7 +1071,7 @@ nsImageLoadingContent::UseAsPrimaryRequest(imgRequestProxy* aRequest, ClearCurrentRequest(NS_BINDING_ABORTED, REQUEST_DISCARD); // Clone the request we were given. - nsRefPtr& req = PrepareNextRequest(); + nsRefPtr& req = PrepareNextRequest(aImageLoadType); nsresult rv = aRequest->Clone(this, getter_AddRefs(req)); if (NS_SUCCEEDED(rv)) { TrackImage(req); @@ -1125,15 +1162,15 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType) } nsRefPtr& -nsImageLoadingContent::PrepareNextRequest() +nsImageLoadingContent::PrepareNextRequest(ImageLoadType aImageLoadType) { // If we don't have a usable current request, get rid of any half-baked // request that might be sitting there and make this one current. if (!HaveSize(mCurrentRequest)) - return PrepareCurrentRequest(); + return PrepareCurrentRequest(aImageLoadType); // Otherwise, make it pending. - return PreparePendingRequest(); + return PreparePendingRequest(aImageLoadType); } void @@ -1155,16 +1192,19 @@ nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision) if (!HaveSize(mCurrentRequest)) { mImageBlockingStatus = aContentDecision; + uint32_t keepFlags = mCurrentRequestFlags & REQUEST_IS_IMAGESET; ClearCurrentRequest(NS_ERROR_IMAGE_BLOCKED, REQUEST_DISCARD); - // We still want to remember what URI we were despite not having an actual - // request. + // We still want to remember what URI we were and if it was an imageset, + // despite not having an actual request. These are both cleared as part of + // ClearCurrentRequest() before a new request is started. mCurrentURI = aURI; + mCurrentRequestFlags = keepFlags; } } nsRefPtr& -nsImageLoadingContent::PrepareCurrentRequest() +nsImageLoadingContent::PrepareCurrentRequest(ImageLoadType aImageLoadType) { // Blocked images go through SetBlockedRequest, which is a separate path. For // everything else, we're unblocked. @@ -1177,12 +1217,16 @@ nsImageLoadingContent::PrepareCurrentRequest() mCurrentRequestFlags |= REQUEST_NEEDS_ANIMATION_RESET; } + if (aImageLoadType == eImageLoadType_Imageset) { + mCurrentRequestFlags |= REQUEST_IS_IMAGESET; + } + // Return a reference. return mCurrentRequest; } nsRefPtr& -nsImageLoadingContent::PreparePendingRequest() +nsImageLoadingContent::PreparePendingRequest(ImageLoadType aImageLoadType) { // Get rid of anything that was there previously. ClearPendingRequest(NS_ERROR_IMAGE_SRC_CHANGED, REQUEST_DISCARD); @@ -1191,6 +1235,10 @@ nsImageLoadingContent::PreparePendingRequest() mPendingRequestFlags |= REQUEST_NEEDS_ANIMATION_RESET; } + if (aImageLoadType == eImageLoadType_Imageset) { + mPendingRequestFlags |= REQUEST_IS_IMAGESET; + } + // Return a reference. return mPendingRequest; } @@ -1233,7 +1281,11 @@ nsImageLoadingContent::MakePendingRequestCurrent() // to go to 0 and the image to be discarded! ImageRequestAutoLock autoLock(mCurrentRequest); - PrepareCurrentRequest() = mPendingRequest; + ImageLoadType loadType = \ + (mPendingRequestFlags & REQUEST_IS_IMAGESET) ? eImageLoadType_Imageset + : eImageLoadType_Normal; + + PrepareCurrentRequest(loadType) = mPendingRequest; mPendingRequest = nullptr; mCurrentRequestFlags = mPendingRequestFlags; mPendingRequestFlags = 0; @@ -1246,8 +1298,9 @@ nsImageLoadingContent::ClearCurrentRequest(nsresult aReason, { if (!mCurrentRequest) { // Even if we didn't have a current request, we might have been keeping - // a URI as a placeholder for a failed load. Clear that now. + // a URI and flags as a placeholder for a failed load. Clear that now. mCurrentURI = nullptr; + mCurrentRequestFlags = 0; return; } NS_ABORT_IF_FALSE(!mCurrentURI, diff --git a/content/base/src/nsImageLoadingContent.h b/content/base/src/nsImageLoadingContent.h index b4e546627d0d..067e52d2c97a 100644 --- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -22,6 +22,8 @@ #include "nsIRequest.h" #include "mozilla/ErrorResult.h" #include "nsAutoPtr.h" +#include "nsIContentPolicy.h" +#include "mozilla/dom/BindingDeclarations.h" class nsIURI; class nsIDocument; @@ -63,28 +65,46 @@ public: int32_t GetRequestType(imgIRequest* aRequest, mozilla::ErrorResult& aError); already_AddRefed GetCurrentURI(mozilla::ErrorResult& aError); + void ForceReload(const mozilla::dom::Optional& aNotify, + mozilla::ErrorResult& aError); + + // XPCOM [optional] syntax helper + nsresult ForceReload(bool aNotify = true) { + return ForceReload(aNotify, 1); + } + + /** + * Used to initialize content with a previously opened channel. Assumes + * eImageLoadType_Normal + */ already_AddRefed LoadImageWithChannel(nsIChannel* aChannel, mozilla::ErrorResult& aError); - void ForceReload(mozilla::ErrorResult& aError); - - protected: + enum ImageLoadType { + // Most normal image loads + eImageLoadType_Normal, + // From a or context. Affects type given to content + // policy. + eImageLoadType_Imageset + }; + /** * 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. + * into this superclass. * * @param aNewURI the URI spec to be loaded (may be a relative URI) * @param aForce If true, make sure to load the URI. If false, only * load if the URI is different from the currently loaded URI. * @param aNotify If true, nsIDocumentObserver state change notifications * will be sent as needed. + * @param aImageLoadType The ImageLoadType for this request */ nsresult LoadImage(const nsAString& aNewURI, bool aForce, - bool aNotify); + bool aNotify, ImageLoadType aImageLoadType); /** * ImageState is called by subclasses that are computing their content state. @@ -108,13 +128,14 @@ protected: * load if the URI is different from the currently loaded URI. * @param aNotify If true, nsIDocumentObserver state change notifications * will be sent as needed. + * @param aImageLoadType The ImageLoadType for this request * @param aDocument Optional parameter giving the document this node is in. * This is purely a performance optimization. * @param aLoadFlags Optional parameter specifying load flags to use for * the image load */ nsresult LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify, - nsIDocument* aDocument = nullptr, + ImageLoadType aImageLoadType, nsIDocument* aDocument = nullptr, nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL); /** @@ -158,7 +179,8 @@ protected: * effectively be called instead of LoadImage or LoadImageWithChannel. * If aNotify is true, this method will notify on state changes. */ - nsresult UseAsPrimaryRequest(imgRequestProxy* aRequest, bool aNotify); + nsresult UseAsPrimaryRequest(imgRequestProxy* aRequest, bool aNotify, + ImageLoadType aImageLoadType); /** * Derived classes of nsImageLoadingContent MUST call @@ -191,6 +213,9 @@ protected: void OnUnlockedDraw(); nsresult OnImageIsAnimated(imgIRequest *aRequest); + // The nsContentPolicyType we would use for this ImageLoadType + static nsContentPolicyType PolicyTypeForLoad(ImageLoadType aImageLoadType); + private: /** * Struct used to manage the image observers. @@ -260,8 +285,10 @@ protected: * a _usable_ current request (one with SIZE_AVAILABLE), this request is * "pending" until it becomes usable. Otherwise, this becomes the current * request. + * + * @param aImageLoadType The ImageLoadType for this request */ - nsRefPtr& PrepareNextRequest(); + nsRefPtr& PrepareNextRequest(ImageLoadType aImageLoadType); /** * Called when we would normally call PrepareNextRequest(), but the request was @@ -275,9 +302,11 @@ protected: * to get rid of one of the requests, you should call * Clear*Request(NS_BINDING_ABORTED) instead, since it passes a more appropriate * aReason than Prepare*Request() does (NS_ERROR_IMAGE_SRC_CHANGED). + * + * @param aImageLoadType The ImageLoadType for this request */ - nsRefPtr& PrepareCurrentRequest(); - nsRefPtr& PreparePendingRequest(); + nsRefPtr& PrepareCurrentRequest(ImageLoadType aImageLoadType); + nsRefPtr& PreparePendingRequest(ImageLoadType aImageLoadType); /** * Switch our pending request to be our current request. @@ -339,7 +368,10 @@ protected: // Set if the request is blocking onload. REQUEST_BLOCKS_ONLOAD = 0x00000002U, // Set if the request is currently tracked with the document. - REQUEST_IS_TRACKED = 0x00000004U + REQUEST_IS_TRACKED = 0x00000004U, + // Set if this is an imageset request, such as from or + // + REQUEST_IS_IMAGESET = 0x00000008U }; // If the image was blocked or if there was an error loading, it's nice to diff --git a/content/html/content/src/HTMLImageElement.cpp b/content/html/content/src/HTMLImageElement.cpp index 42ba380b2873..4971208e15c7 100644 --- a/content/html/content/src/HTMLImageElement.cpp +++ b/content/html/content/src/HTMLImageElement.cpp @@ -434,13 +434,9 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, QueueImageLoadTask(); } else { // Bug 1076583 - We still use the older synchronous algorithm in - // non-responsive mode. We want aForce == true in this LoadImage - // call, because we want to force a new load of the image with - // the new cross origin policy. - nsCOMPtr currentURI; - if (NS_SUCCEEDED(GetCurrentURI(getter_AddRefs(currentURI))) && currentURI) { - LoadImage(currentURI, true, aNotify); - } + // non-responsive mode. Force a new load of the image with the + // new cross origin policy. + ForceReload(aNotify); } } @@ -551,7 +547,7 @@ HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, // the state gets in Element's attr-setting happen around this // LoadImage call, we could start passing false instead of aNotify // here. - LoadImage(aValue, true, aNotify); + LoadImage(aValue, true, aNotify, eImageLoadType_Normal); mNewRequestsWillNeedAnimationReset = false; } @@ -909,14 +905,19 @@ HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify) if (mResponsiveSelector) { nsCOMPtr url = mResponsiveSelector->GetSelectedImageURL(); - rv = LoadImage(url, aForce, aNotify); + rv = LoadImage(url, aForce, aNotify, eImageLoadType_Imageset); } else { nsAutoString src; if (!GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { CancelImageRequests(aNotify); rv = NS_OK; } else { - rv = LoadImage(src, aForce, aNotify); + // If we have a srcset attribute or are in a element, + // we always use the Imageset load type, even if we parsed no + // valid responsive sources from either, per spec. + rv = LoadImage(src, aForce, aNotify, + HaveSrcsetOrInPicture() ? eImageLoadType_Imageset + : eImageLoadType_Normal); } } diff --git a/content/html/content/src/HTMLInputElement.cpp b/content/html/content/src/HTMLInputElement.cpp index 78334e62c79e..3c951552f52c 100644 --- a/content/html/content/src/HTMLInputElement.cpp +++ b/content/html/content/src/HTMLInputElement.cpp @@ -1314,7 +1314,7 @@ HTMLInputElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName, } else if (aNotify && aName == nsGkAtoms::src && mType == NS_FORM_INPUT_IMAGE) { if (aValue) { - LoadImage(aValue->String(), true, aNotify); + LoadImage(aValue->String(), true, aNotify, eImageLoadType_Normal); } else { // Null value means the attr got unset; drop the image CancelImageRequests(aNotify); @@ -1393,7 +1393,7 @@ HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, // whether we have an image to load; nsAutoString src; if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) { - LoadImage(src, false, aNotify); + LoadImage(src, false, aNotify, eImageLoadType_Normal); } } } @@ -4393,7 +4393,7 @@ HTMLInputElement::MaybeLoadImage() nsAutoString uri; if (mType == NS_FORM_INPUT_IMAGE && GetAttr(kNameSpaceID_None, nsGkAtoms::src, uri) && - (NS_FAILED(LoadImage(uri, false, true)) || + (NS_FAILED(LoadImage(uri, false, true, eImageLoadType_Normal)) || !LoadingEnabled())) { CancelImageRequests(true); } diff --git a/content/svg/content/src/SVGFEImageElement.cpp b/content/svg/content/src/SVGFEImageElement.cpp index e28f5a1ebf16..5855d76c9293 100644 --- a/content/svg/content/src/SVGFEImageElement.cpp +++ b/content/svg/content/src/SVGFEImageElement.cpp @@ -85,7 +85,7 @@ SVGFEImageElement::LoadSVGImage(bool aForce, bool aNotify) } } - return LoadImage(href, aForce, aNotify); + return LoadImage(href, aForce, aNotify, eImageLoadType_Normal); } //---------------------------------------------------------------------- diff --git a/content/svg/content/src/SVGImageElement.cpp b/content/svg/content/src/SVGImageElement.cpp index cb55b043e210..863e96f234fd 100644 --- a/content/svg/content/src/SVGImageElement.cpp +++ b/content/svg/content/src/SVGImageElement.cpp @@ -127,7 +127,7 @@ SVGImageElement::LoadSVGImage(bool aForce, bool aNotify) if (baseURI && !href.IsEmpty()) NS_MakeAbsoluteURI(href, href, baseURI); - return LoadImage(href, aForce, aNotify); + return LoadImage(href, aForce, aNotify, eImageLoadType_Normal); } //---------------------------------------------------------------------- diff --git a/dom/webidl/HTMLImageElement.webidl b/dom/webidl/HTMLImageElement.webidl index 70185675d456..c22c6bf1ad47 100644 --- a/dom/webidl/HTMLImageElement.webidl +++ b/dom/webidl/HTMLImageElement.webidl @@ -103,7 +103,7 @@ interface MozImageLoadingContent { [ChromeOnly,Throws] nsIStreamListener? loadImageWithChannel(MozChannel aChannel); [ChromeOnly,Throws] - void forceReload(); + void forceReload(optional boolean aNotify); [ChromeOnly] void forceImageState(boolean aForce, unsigned long long aState); }; diff --git a/embedding/browser/nsContextMenuInfo.cpp b/embedding/browser/nsContextMenuInfo.cpp index 0b4733071c0b..3b54f1cfff01 100644 --- a/embedding/browser/nsContextMenuInfo.cpp +++ b/embedding/browser/nsContextMenuInfo.cpp @@ -275,7 +275,7 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgRe // bail for the parent node of the root element or null argument if (!domElement) break; - + nsCOMPtr computedStyle; window->GetComputedStyle(domElement, EmptyString(), getter_AddRefs(computedStyle)); @@ -296,7 +296,8 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgRe return il->LoadImage(bgUri, nullptr, nullptr, principal, nullptr, nullptr, nullptr, nsIRequest::LOAD_NORMAL, - nullptr, EmptyString(), aRequest); + nullptr, nsIContentPolicy::TYPE_IMAGE, + EmptyString(), aRequest); } } diff --git a/image/public/imgILoader.idl b/image/public/imgILoader.idl index 491eda22ae63..a2de1073a818 100644 --- a/image/public/imgILoader.idl +++ b/image/public/imgILoader.idl @@ -18,6 +18,7 @@ interface nsIURI; interface nsISimpleEnumerator; #include "nsIRequest.idl" // for nsLoadFlags +#include "nsIContentPolicy.idl" // for nsContentPolicyType /** * imgILoader interface @@ -26,7 +27,7 @@ interface nsISimpleEnumerator; * @version 0.3 * @see imagelib2 */ -[scriptable, builtinclass, uuid(046d5fa6-ac59-489d-b51e-0ffe57e8df59)] +[scriptable, builtinclass, uuid(42ef3b0a-cd82-454b-b4c4-f3470014a68b)] interface imgILoader : nsISupports { // Extra flags to pass to loadImage if you want a load to use CORS @@ -46,6 +47,9 @@ interface imgILoader : nsISupports * @param aLoadFlags Load flags for the request * @param aCacheKey cache key to use for a load if the original * image came from a request that had post data + * @param aContentPolicyType [optional] the nsContentPolicyType to + * use for this load. Defaults to + * nsIContentPolicy::TYPE_IMAGE * libpr0n does NOT keep a strong ref to the observer; this prevents @@ -61,13 +65,15 @@ interface imgILoader : nsISupports in imgINotificationObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, - in nsISupports cacheKey); + in nsISupports cacheKey, + [optional] + in nsContentPolicyType aContentPolicyType); /** * Start the load and decode of an image. * @param aChannel the channel to load the image from. This must * already be opened before ths method is called, and there - * must have been no OnDataAvailable calls for it yet. + * must have been no OnDataAvailable calls for it yet. * @param aObserver the observer (may be null) * @param cx some random data * @param aListener [out] diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp index 063cf53cfb5b..338a00201362 100644 --- a/image/src/imgLoader.cpp +++ b/image/src/imgLoader.cpp @@ -635,6 +635,7 @@ static nsresult NewImageChannel(nsIChannel **aResult, nsILoadGroup *aLoadGroup, const nsCString& aAcceptHeader, nsLoadFlags aLoadFlags, + nsContentPolicyType aPolicyType, nsIPrincipal *aLoadingPrincipal, nsISupports *aRequestingContext) { @@ -680,6 +681,7 @@ static nsresult NewImageChannel(nsIChannel **aResult, if (inherit) { securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL; } + // Note we are calling NS_NewChannelInternal() here with a node and a principal. // This is for things like background images that are specified by user // stylesheets, where the document is being styled, but the principal is that @@ -689,7 +691,7 @@ static nsresult NewImageChannel(nsIChannel **aResult, requestingNode, requestingPrincipal, securityFlags, - nsIContentPolicy::TYPE_IMAGE, + aPolicyType, nullptr, // loadGroup callbacks, aLoadFlags); @@ -1442,6 +1444,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, imgINotificationObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, + nsContentPolicyType aLoadPolicyType, imgRequestProxy **aProxyRequest, nsIPrincipal* aLoadingPrincipal, int32_t aCORSMode) @@ -1490,6 +1493,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, aLoadGroup, mAcceptHeader, aLoadFlags, + aLoadPolicyType, aLoadingPrincipal, aCX); if (NS_FAILED(rv)) { @@ -1567,6 +1571,7 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry, imgINotificationObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, + nsContentPolicyType aLoadPolicyType, bool aCanMakeNewChannel, imgRequestProxy **aProxyRequest, nsIPrincipal* aLoadingPrincipal, @@ -1678,8 +1683,9 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry, return ValidateRequestWithNewChannel(request, aURI, aInitialDocumentURI, aReferrerURI, aLoadGroup, aObserver, - aCX, aLoadFlags, aProxyRequest, - aLoadingPrincipal, aCORSMode); + aCX, aLoadFlags, aLoadPolicyType, + aProxyRequest, aLoadingPrincipal, + aCORSMode); } return !validateRequest; @@ -1853,8 +1859,13 @@ NS_IMETHODIMP imgLoader::LoadImageXPCOM(nsIURI *aURI, nsISupports *aCX, nsLoadFlags aLoadFlags, nsISupports *aCacheKey, + nsContentPolicyType aContentPolicyType, imgIRequest **_retval) { + // Optional parameter, so defaults to 0 (== TYPE_INVALID) + if (!aContentPolicyType) { + aContentPolicyType = nsIContentPolicy::TYPE_IMAGE; + } imgRequestProxy *proxy; nsresult result = LoadImage(aURI, aInitialDocumentURI, @@ -1865,6 +1876,7 @@ NS_IMETHODIMP imgLoader::LoadImageXPCOM(nsIURI *aURI, aCX, aLoadFlags, aCacheKey, + aContentPolicyType, EmptyString(), &proxy); *_retval = proxy; @@ -1889,10 +1901,11 @@ nsresult imgLoader::LoadImage(nsIURI *aURI, nsISupports *aCX, nsLoadFlags aLoadFlags, nsISupports *aCacheKey, + nsContentPolicyType aContentPolicyType, const nsAString& initiatorType, imgRequestProxy **_retval) { - VerifyCacheSizes(); + VerifyCacheSizes(); NS_ASSERTION(aURI, "imgLoader::LoadImage -- NULL URI pointer"); @@ -1967,8 +1980,9 @@ nsresult imgLoader::LoadImage(nsIURI *aURI, if (cache.Get(spec, getter_AddRefs(entry)) && entry) { if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI, - aLoadGroup, aObserver, aCX, requestFlags, true, - _retval, aLoadingPrincipal, corsmode)) { + aLoadGroup, aObserver, aCX, requestFlags, + aContentPolicyType, true, _retval, + aLoadingPrincipal, corsmode)) { request = entry->GetRequest(); // If this entry has no proxies, its request has no reference to the entry. @@ -2010,6 +2024,7 @@ nsresult imgLoader::LoadImage(nsIURI *aURI, aLoadGroup, mAcceptHeader, requestFlags, + aContentPolicyType, aLoadingPrincipal, aCX); if (NS_FAILED(rv)) @@ -2192,9 +2207,13 @@ nsresult imgLoader::LoadImageWithChannel(nsIChannel *channel, imgINotificationOb // // XXX -- should this be changed? it's pretty much verbatim from the old // code, but seems nonsensical. - if (ValidateEntry(entry, uri, nullptr, nullptr, nullptr, aObserver, aCX, - requestFlags, false, nullptr, nullptr, - imgIRequest::CORS_NONE)) { + // + // Since aCanMakeNewChannel == false, we don't need to pass content policy + // type/principal/etc + if (ValidateEntry(entry, uri, nullptr, nullptr, nullptr, + aObserver, aCX, requestFlags, + nsIContentPolicy::TYPE_INVALID, false, nullptr, + nullptr, imgIRequest::CORS_NONE)) { request = entry->GetRequest(); } else { nsCOMPtr cacheChan(do_QueryInterface(channel)); diff --git a/image/src/imgLoader.h b/image/src/imgLoader.h index 620457651086..fedbc56d7cb2 100644 --- a/image/src/imgLoader.h +++ b/image/src/imgLoader.h @@ -257,8 +257,10 @@ public: nsISupports *aCX, nsLoadFlags aLoadFlags, nsISupports *aCacheKey, + nsContentPolicyType aContentPolicyType, const nsAString& initiatorType, imgRequestProxy **_retval); + nsresult LoadImageWithChannel(nsIChannel *channel, imgINotificationObserver *aObserver, nsISupports *aCX, @@ -336,7 +338,9 @@ private: // methods nsIURI *aInitialDocumentURI, nsIURI *aReferrerURI, nsILoadGroup *aLoadGroup, imgINotificationObserver *aObserver, nsISupports *aCX, - nsLoadFlags aLoadFlags, bool aCanMakeNewChannel, + nsLoadFlags aLoadFlags, + nsContentPolicyType aContentPolicyType, + bool aCanMakeNewChannel, imgRequestProxy **aProxyRequest, nsIPrincipal* aLoadingPrincipal, int32_t aCORSMode); @@ -347,6 +351,7 @@ private: // methods nsILoadGroup *aLoadGroup, imgINotificationObserver *aObserver, nsISupports *aCX, nsLoadFlags aLoadFlags, + nsContentPolicyType aContentPolicyType, imgRequestProxy **aProxyRequest, nsIPrincipal* aLoadingPrincipal, int32_t aCORSMode); diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 2d273ef89047..c09191a101fc 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1938,7 +1938,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec, nsCOMPtr realURI; SpecToURI(aSpec, sIOService, getter_AddRefs(realURI)); - + nsRefPtr il = nsContentUtils::GetImgLoaderForDocument(aPresContext->Document()); @@ -1947,6 +1947,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec, // For icon loads, we don't need to merge with the loadgroup flags nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL; + nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_IMAGE; return il->LoadImage(realURI, /* icon URI */ nullptr, /* initial document URI; this is only @@ -1959,6 +1960,7 @@ nsImageFrame::LoadIcon(const nsAString& aSpec, nullptr, /* Not associated with any particular document */ loadFlags, nullptr, + contentPolicyType, EmptyString(), aRequest); } diff --git a/widget/cocoa/OSXNotificationCenter.mm b/widget/cocoa/OSXNotificationCenter.mm index 943658e96f42..6ba09e5b3f45 100644 --- a/widget/cocoa/OSXNotificationCenter.mm +++ b/widget/cocoa/OSXNotificationCenter.mm @@ -14,6 +14,7 @@ #include "nsString.h" #include "nsCOMPtr.h" #include "nsIObserver.h" +#include "nsIContentPolicy.h" #include "imgRequestProxy.h" using namespace mozilla; @@ -244,7 +245,7 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const if (imageUri) { nsresult rv = il->LoadImage(imageUri, nullptr, nullptr, aPrincipal, nullptr, this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, - EmptyString(), + nsIContentPolicy::TYPE_IMAGE, EmptyString(), getter_AddRefs(osxni->mIconRequest)); if (NS_SUCCEEDED(rv)) { // Set a timer for six seconds. If we don't have an icon by the time this diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm index 1150d9fc7986..f6a0f03c1f72 100644 --- a/widget/cocoa/nsMenuItemIconX.mm +++ b/widget/cocoa/nsMenuItemIconX.mm @@ -40,6 +40,7 @@ #include "imgIContainer.h" #include "nsCocoaUtils.h" #include "nsContentUtils.h" +#include "nsIContentPolicy.h" using mozilla::gfx::SourceSurface; using mozilla::RefPtr; @@ -307,7 +308,8 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI) nsresult rv = loader->LoadImage(aIconURI, nullptr, nullptr, nullptr, loadGroup, this, nullptr, nsIRequest::LOAD_NORMAL, nullptr, - EmptyString(), getter_AddRefs(mIconRequest)); + nsIContentPolicy::TYPE_IMAGE, EmptyString(), + getter_AddRefs(mIconRequest)); if (NS_FAILED(rv)) return rv; // We need to request the icon be decoded (bug 573583, bug 705516).