Bug 1373780 - Part 3: add isImgSet argument. r=jdm

Per mixed-content-blocked spec, [1], <img srcset> and <picture> should
be blocked. However we still fetch <img srcset> and <picture> 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 <picture> or <img srcset>, 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.
This commit is contained in:
Yoshi Huang 2017-08-21 18:24:40 +08:00
Родитель e63d45332e
Коммит df6bad1c1e
5 изменённых файлов: 32 добавлений и 15 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -9765,19 +9765,23 @@ already_AddRefed<nsIURI>
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 <picture> element and found a URI from a source previous to
// this image, use it.
sourceURL = mPreloadPictureFoundSource;
isImgSet = true;
} else {
// Otherwise try to use this <img> as a source
HTMLImageElement::SelectSourceForTagWithAttrs(this, false, aSrcAttr,
aSrcsetAttr, aSizesAttr,
NullString(), NullString(),
sourceURL);
isImgSet = !aSrcsetAttr.IsEmpty();
}
// Empty sources are not loaded by <img> (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 <img> tags in
// this this <picture> share the same <sources> (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<imgRequestProxy> 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

Просмотреть файл

@ -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,

Просмотреть файл

@ -2403,21 +2403,27 @@ public:
* nesting and possible sources, which are used to inform URL selection
* responsive <picture> or <img srcset> images. Unset attributes are expected
* to be marked void.
* If this image is for <picture> or <img srcset>, aIsImgSet will be set to
* true, false otherwise.
*/
virtual already_AddRefed<nsIURI>
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 <picture> or <img srcset> 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

Просмотреть файл

@ -995,8 +995,9 @@ nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
const nsAString& aImageReferrerPolicy)
{
nsCOMPtr<nsIURI> baseURI = BaseURIForPreload();
bool isImgSet = false;
nsCOMPtr<nsIURI> 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);
}
}