From df6bad1c1e111ffc4ae57433362b3487ff6c7bb4 Mon Sep 17 00:00:00 2001 From: Yoshi Huang Date: Mon, 21 Aug 2017 18:24:40 +0800 Subject: [PATCH] Bug 1373780 - Part 3: add isImgSet argument. r=jdm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per mixed-content-blocked spec, [1], and should be blocked. However we still fetch and in image preload, because they are fetched with contentPolicyType TYPE_INTERNAL_IMAGE_PRELOAD and won't be rejected by nsMixedContentBlocker.cpp. So I updated the image preloading code, and use the type TYPE_IMAGESET if the image request is for or , otherwise for normal image load we still use TYPE_INTERNAL_IMAGE_PRELOAD. [1]: https://w3c.github.io/webappsec-mixed-content/#should-block-fetch 4. Return allowed if one or more of the following conditions are met: request’s type is "image", and initiator is not "imageset". 5. Return blocked. --- dom/base/nsContentUtils.cpp | 9 +++------ dom/base/nsDocument.cpp | 16 +++++++++++++--- dom/base/nsDocument.h | 7 +++++-- dom/base/nsIDocument.h | 10 ++++++++-- parser/html/nsHtml5TreeOpExecutor.cpp | 5 +++-- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index fef14b76477e..63629536bd68 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -8921,12 +8921,9 @@ nsContentUtils::GetWindowRoot(nsIDocument* aDoc) bool nsContentUtils::IsPreloadType(nsContentPolicyType aType) { - if (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || - aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD || - aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD) { - return true; - } - return false; + return (aType == nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD || + aType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD || + aType == nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD); } nsresult diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 7b8563d31b6c..03f954eb271e 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -9765,19 +9765,23 @@ already_AddRefed nsDocument::ResolvePreloadImage(nsIURI *aBaseURI, const nsAString& aSrcAttr, const nsAString& aSrcsetAttr, - const nsAString& aSizesAttr) + const nsAString& aSizesAttr, + bool *aIsImgSet) { nsString sourceURL; + bool isImgSet; if (mPreloadPictureDepth == 1 && !mPreloadPictureFoundSource.IsVoid()) { // We're in a element and found a URI from a source previous to // this image, use it. sourceURL = mPreloadPictureFoundSource; + isImgSet = true; } else { // Otherwise try to use this as a source HTMLImageElement::SelectSourceForTagWithAttrs(this, false, aSrcAttr, aSrcsetAttr, aSizesAttr, NullString(), NullString(), sourceURL); + isImgSet = !aSrcsetAttr.IsEmpty(); } // Empty sources are not loaded by (i.e. not resolved to the baseURI) @@ -9795,6 +9799,8 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI, return nullptr; } + *aIsImgSet = isImgSet; + // We don't clear mPreloadPictureFoundSource because subsequent tags in // this this share the same (though this is not valid per // spec) @@ -9803,7 +9809,7 @@ nsDocument::ResolvePreloadImage(nsIURI *aBaseURI, void nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, - ReferrerPolicy aReferrerPolicy) + ReferrerPolicy aReferrerPolicy, bool aIsImgSet) { // Early exit if the img is already present in the img-cache // which indicates that the "real" load has already started and @@ -9827,6 +9833,10 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, MOZ_CRASH("Unknown CORS mode!"); } + nsContentPolicyType policyType = + aIsImgSet ? nsIContentPolicy::TYPE_IMAGESET : + nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD; + // Image not in cache - trigger preload RefPtr request; nsresult rv = @@ -9840,7 +9850,7 @@ nsDocument::MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, loadFlags, NS_LITERAL_STRING("img"), getter_AddRefs(request), - nsIContentPolicy::TYPE_INTERNAL_IMAGE_PRELOAD); + policyType); // Pin image-reference to avoid evicting it from the img-cache before // the "real" load occurs. Unpinned in DispatchContentLoadedEvents and diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 2ebb658e1ee6..c6ea3d64dca2 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -823,11 +823,14 @@ public: ResolvePreloadImage(nsIURI *aBaseURI, const nsAString& aSrcAttr, const nsAString& aSrcsetAttr, - const nsAString& aSizesAttr) override; + const nsAString& aSizesAttr, + bool *aIsImgSet) override; virtual void MaybePreLoadImage(nsIURI* uri, const nsAString &aCrossOriginAttr, - ReferrerPolicy aReferrerPolicy) override; + ReferrerPolicy aReferrerPolicy, + bool aIsImgSet) override; + virtual void ForgetImagePreload(nsIURI* aURI) override; virtual void MaybePreconnect(nsIURI* uri, diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 3814049b0ce8..e834f5785cad 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -2403,21 +2403,27 @@ public: * nesting and possible sources, which are used to inform URL selection * responsive or images. Unset attributes are expected * to be marked void. + * If this image is for or , aIsImgSet will be set to + * true, false otherwise. */ virtual already_AddRefed ResolvePreloadImage(nsIURI *aBaseURI, const nsAString& aSrcAttr, const nsAString& aSrcsetAttr, - const nsAString& aSizesAttr) = 0; + const nsAString& aSizesAttr, + bool *aIsImgSet) = 0; /** * Called by nsParser to preload images. Can be removed and code moved * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the * parser-module is linked with gklayout-module. aCrossOriginAttr should * be a void string if the attr is not present. + * aIsImgSet is the value got from calling ResolvePreloadImage, it is true + * when this image is for loading or images. */ virtual void MaybePreLoadImage(nsIURI* uri, const nsAString& aCrossOriginAttr, - ReferrerPolicyEnum aReferrerPolicy) = 0; + ReferrerPolicyEnum aReferrerPolicy, + bool aIsImgSet) = 0; /** * Called by images to forget an image preload when they start doing diff --git a/parser/html/nsHtml5TreeOpExecutor.cpp b/parser/html/nsHtml5TreeOpExecutor.cpp index 2e1b0780813e..aa50ea5b80f9 100644 --- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -995,8 +995,9 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL, const nsAString& aImageReferrerPolicy) { nsCOMPtr baseURI = BaseURIForPreload(); + bool isImgSet = false; nsCOMPtr uri = mDocument->ResolvePreloadImage(baseURI, aURL, aSrcset, - aSizes); + aSizes, &isImgSet); if (uri && ShouldPreloadURI(uri)) { // use document wide referrer policy mozilla::net::ReferrerPolicy referrerPolicy = mSpeculationReferrerPolicy; @@ -1006,7 +1007,7 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL, referrerPolicy = imageReferrerPolicy; } - mDocument->MaybePreLoadImage(uri, aCrossOrigin, referrerPolicy); + mDocument->MaybePreLoadImage(uri, aCrossOrigin, referrerPolicy, isImgSet); } }