mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-21 17:59:34 +00:00
Bug 1618295 - Make imgRequestProxy implement and use PreloaderBase to support the preload as speculative load feature; r=tnikkel,smaug,mayhemer
Depends on D72083 Differential Revision: https://phabricator.services.mozilla.com/D69860
This commit is contained in:
parent
ae65cbe96e
commit
3f250fba44
@ -11310,16 +11310,9 @@ already_AddRefed<nsIURI> Document::ResolvePreloadImage(
|
||||
return uri.forget();
|
||||
}
|
||||
|
||||
void Document::MaybePreLoadImage(nsIURI* uri, const nsAString& aCrossOriginAttr,
|
||||
enum 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
|
||||
// that we shouldn't preload it.
|
||||
if (nsContentUtils::IsImageInCache(uri, this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
void Document::PreLoadImage(nsIURI* aUri, const nsAString& aCrossOriginAttr,
|
||||
ReferrerPolicyEnum aReferrerPolicy, bool aIsImgSet,
|
||||
bool aLinkPreload) {
|
||||
nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL |
|
||||
nsContentUtils::CORSModeToLoadImageFlags(
|
||||
Element::StringToCORSMode(aCrossOriginAttr));
|
||||
@ -11331,21 +11324,50 @@ void Document::MaybePreLoadImage(nsIURI* uri, const nsAString& aCrossOriginAttr,
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo =
|
||||
ReferrerInfo::CreateFromDocumentAndPolicyOverride(this, aReferrerPolicy);
|
||||
|
||||
// Image not in cache - trigger preload
|
||||
RefPtr<imgRequestProxy> request;
|
||||
nsresult rv = nsContentUtils::LoadImage(
|
||||
uri, static_cast<nsINode*>(this), this, NodePrincipal(), 0, referrerInfo,
|
||||
nullptr, // no observer
|
||||
loadFlags, NS_LITERAL_STRING("img"), getter_AddRefs(request), policyType);
|
||||
aUri, static_cast<nsINode*>(this), this, NodePrincipal(), 0, referrerInfo,
|
||||
nullptr /* no observer */, loadFlags,
|
||||
aLinkPreload ? NS_LITERAL_STRING("link") : NS_LITERAL_STRING("img"),
|
||||
getter_AddRefs(request), policyType, false /* urgent */, aLinkPreload);
|
||||
|
||||
// Pin image-reference to avoid evicting it from the img-cache before
|
||||
// the "real" load occurs. Unpinned in DispatchContentLoadedEvents and
|
||||
// unlink
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mPreloadingImages.Put(uri, std::move(request));
|
||||
if (!aLinkPreload && NS_SUCCEEDED(rv)) {
|
||||
mPreloadingImages.Put(aUri, std::move(request));
|
||||
}
|
||||
}
|
||||
|
||||
void Document::MaybePreLoadImage(nsIURI* aUri,
|
||||
const nsAString& aCrossOriginAttr,
|
||||
ReferrerPolicyEnum aReferrerPolicy,
|
||||
bool aIsImgSet, bool aLinkPreload) {
|
||||
if (aLinkPreload) {
|
||||
// Check if the image was already preloaded in this document to avoid
|
||||
// duplicate preloading.
|
||||
PreloadHashKey key = PreloadHashKey::CreateAsImage(
|
||||
aUri, NodePrincipal(), dom::Element::StringToCORSMode(aCrossOriginAttr),
|
||||
aReferrerPolicy);
|
||||
if (!mPreloadService.PreloadExists(&key)) {
|
||||
PreLoadImage(aUri, aCrossOriginAttr, aReferrerPolicy, aIsImgSet,
|
||||
aLinkPreload);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Early exit if the img is already present in the img-cache
|
||||
// which indicates that the "real" load has already started and
|
||||
// that we shouldn't preload it.
|
||||
if (nsContentUtils::IsImageInCache(aUri, this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Image not in cache - trigger preload
|
||||
PreLoadImage(aUri, aCrossOriginAttr, aReferrerPolicy, aIsImgSet,
|
||||
aLinkPreload);
|
||||
}
|
||||
|
||||
void Document::MaybePreconnect(nsIURI* aOrigURI, mozilla::CORSMode aCORSMode) {
|
||||
NS_MutateURI mutator(aOrigURI);
|
||||
if (NS_FAILED(mutator.GetStatus())) {
|
||||
|
@ -2907,7 +2907,11 @@ class Document : public nsINode,
|
||||
* when this image is for loading <picture> or <img srcset> images.
|
||||
*/
|
||||
void MaybePreLoadImage(nsIURI* uri, const nsAString& aCrossOriginAttr,
|
||||
ReferrerPolicyEnum aReferrerPolicy, bool aIsImgSet);
|
||||
ReferrerPolicyEnum aReferrerPolicy, bool aIsImgSet,
|
||||
bool aLinkPreload);
|
||||
void PreLoadImage(nsIURI* uri, const nsAString& aCrossOriginAttr,
|
||||
ReferrerPolicyEnum aReferrerPolicy, bool aIsImgSet,
|
||||
bool aLinkPreload);
|
||||
|
||||
/**
|
||||
* Called by images to forget an image preload when they start doing
|
||||
|
@ -3341,7 +3341,7 @@ nsresult nsContentUtils::LoadImage(
|
||||
nsIReferrerInfo* aReferrerInfo, imgINotificationObserver* aObserver,
|
||||
int32_t aLoadFlags, const nsAString& initiatorType,
|
||||
imgRequestProxy** aRequest, uint32_t aContentPolicyType,
|
||||
bool aUseUrgentStartForChannel) {
|
||||
bool aUseUrgentStartForChannel, bool aLinkPreload) {
|
||||
MOZ_ASSERT(aURI, "Must have a URI");
|
||||
MOZ_ASSERT(aContext, "Must have a context");
|
||||
MOZ_ASSERT(aLoadingDocument, "Must have a document");
|
||||
@ -3377,6 +3377,7 @@ nsresult nsContentUtils::LoadImage(
|
||||
aContentPolicyType, /* content policy type */
|
||||
initiatorType, /* the load initiator */
|
||||
aUseUrgentStartForChannel, /* urgent-start flag */
|
||||
aLinkPreload, /* <link preload> initiator */
|
||||
aRequest);
|
||||
}
|
||||
|
||||
|
@ -921,7 +921,7 @@ class nsContentUtils {
|
||||
int32_t aLoadFlags, const nsAString& initiatorType,
|
||||
imgRequestProxy** aRequest,
|
||||
uint32_t aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE,
|
||||
bool aUseUrgentStartForChannel = false);
|
||||
bool aUseUrgentStartForChannel = false, bool aLinkPreload = false);
|
||||
|
||||
/**
|
||||
* Obtain an image loader that respects the given document/channel's privacy
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "prtime.h"
|
||||
@ -1197,6 +1198,21 @@ NS_IMPL_ISUPPORTS(imgLoader, imgILoader, nsIContentSniffer, imgICache,
|
||||
static imgLoader* gNormalLoader = nullptr;
|
||||
static imgLoader* gPrivateBrowsingLoader = nullptr;
|
||||
|
||||
/* static */
|
||||
mozilla::CORSMode imgLoader::ConvertToCORSMode(uint32_t aImgCORS) {
|
||||
switch (aImgCORS) {
|
||||
case imgIRequest::CORS_NONE:
|
||||
return CORSMode::CORS_NONE;
|
||||
case imgIRequest::CORS_ANONYMOUS:
|
||||
return CORSMode::CORS_ANONYMOUS;
|
||||
case imgIRequest::CORS_USE_CREDENTIALS:
|
||||
return CORSMode::CORS_USE_CREDENTIALS;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "Unexpected imgIRequest CORS value");
|
||||
return CORSMode::CORS_NONE;
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<imgLoader> imgLoader::CreateImageLoader() {
|
||||
// In some cases, such as xpctests, XPCOM modules are not automatically
|
||||
@ -1665,7 +1681,7 @@ bool imgLoader::ValidateRequestWithNewChannel(
|
||||
imgINotificationObserver* aObserver, Document* aLoadingDocument,
|
||||
uint64_t aInnerWindowId, nsLoadFlags aLoadFlags,
|
||||
nsContentPolicyType aLoadPolicyType, imgRequestProxy** aProxyRequest,
|
||||
nsIPrincipal* aTriggeringPrincipal, int32_t aCORSMode,
|
||||
nsIPrincipal* aTriggeringPrincipal, int32_t aCORSMode, bool aLinkPreload,
|
||||
bool* aNewChannelCreated) {
|
||||
// now we need to insert a new channel request object in between the real
|
||||
// request and the proxy that basically delays loading the image until it
|
||||
@ -1675,7 +1691,7 @@ bool imgLoader::ValidateRequestWithNewChannel(
|
||||
|
||||
// If we're currently in the middle of validating this request, just hand
|
||||
// back a proxy to it; the required work will be done for us.
|
||||
if (request->GetValidator()) {
|
||||
if (imgCacheValidator* validator = request->GetValidator()) {
|
||||
rv = CreateNewProxyForRequest(request, aURI, aLoadGroup, aLoadingDocument,
|
||||
aObserver, aLoadFlags, aProxyRequest);
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -1691,8 +1707,18 @@ bool imgLoader::ValidateRequestWithNewChannel(
|
||||
// resulting from methods such as StartDecoding(). See bug 579122.
|
||||
proxy->MarkValidating();
|
||||
|
||||
if (aLinkPreload) {
|
||||
MOZ_ASSERT(aLoadingDocument);
|
||||
MOZ_ASSERT(aReferrerInfo);
|
||||
proxy->PrioritizeAsPreload();
|
||||
auto preloadKey = PreloadHashKey::CreateAsImage(
|
||||
aURI, aTriggeringPrincipal, ConvertToCORSMode(aCORSMode),
|
||||
aReferrerInfo->ReferrerPolicy());
|
||||
proxy->NotifyOpen(&preloadKey, aLoadingDocument, true);
|
||||
}
|
||||
|
||||
// Attach the proxy without notifying
|
||||
request->GetValidator()->AddProxy(proxy);
|
||||
validator->AddProxy(proxy);
|
||||
}
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
@ -1750,6 +1776,16 @@ bool imgLoader::ValidateRequestWithNewChannel(
|
||||
// resulting from methods such as StartDecoding(). See bug 579122.
|
||||
req->MarkValidating();
|
||||
|
||||
if (aLinkPreload) {
|
||||
MOZ_ASSERT(aLoadingDocument);
|
||||
MOZ_ASSERT(aReferrerInfo);
|
||||
req->PrioritizeAsPreload();
|
||||
auto preloadKey = PreloadHashKey::CreateAsImage(
|
||||
aURI, aTriggeringPrincipal, ConvertToCORSMode(aCORSMode),
|
||||
aReferrerInfo->ReferrerPolicy());
|
||||
req->NotifyOpen(&preloadKey, aLoadingDocument, true);
|
||||
}
|
||||
|
||||
// Add the proxy without notifying
|
||||
hvc->AddProxy(req);
|
||||
|
||||
@ -1773,7 +1809,7 @@ bool imgLoader::ValidateEntry(
|
||||
nsLoadFlags aLoadFlags, nsContentPolicyType aLoadPolicyType,
|
||||
bool aCanMakeNewChannel, bool* aNewChannelCreated,
|
||||
imgRequestProxy** aProxyRequest, nsIPrincipal* aTriggeringPrincipal,
|
||||
int32_t aCORSMode) {
|
||||
int32_t aCORSMode, bool aLinkPreload) {
|
||||
LOG_SCOPE(gImgLog, "imgLoader::ValidateEntry");
|
||||
|
||||
// If the expiration time is zero, then the request has not gotten far enough
|
||||
@ -1892,7 +1928,8 @@ bool imgLoader::ValidateEntry(
|
||||
return ValidateRequestWithNewChannel(
|
||||
request, aURI, aInitialDocumentURI, aReferrerInfo, aLoadGroup,
|
||||
aObserver, aLoadingDocument, innerWindowID, aLoadFlags, aLoadPolicyType,
|
||||
aProxyRequest, aTriggeringPrincipal, aCORSMode, aNewChannelCreated);
|
||||
aProxyRequest, aTriggeringPrincipal, aCORSMode, aLinkPreload,
|
||||
aNewChannelCreated);
|
||||
}
|
||||
|
||||
return !validateRequest;
|
||||
@ -2051,11 +2088,11 @@ imgLoader::LoadImageXPCOM(
|
||||
aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
|
||||
}
|
||||
imgRequestProxy* proxy;
|
||||
nsresult rv =
|
||||
LoadImage(aURI, aInitialDocumentURI, aReferrerInfo, aTriggeringPrincipal,
|
||||
0, aLoadGroup, aObserver, aLoadingDocument, aLoadingDocument,
|
||||
aLoadFlags, aCacheKey, aContentPolicyType, EmptyString(),
|
||||
/* aUseUrgentStartForChannel */ false, &proxy);
|
||||
nsresult rv = LoadImage(
|
||||
aURI, aInitialDocumentURI, aReferrerInfo, aTriggeringPrincipal, 0,
|
||||
aLoadGroup, aObserver, aLoadingDocument, aLoadingDocument, aLoadFlags,
|
||||
aCacheKey, aContentPolicyType, EmptyString(),
|
||||
/* aUseUrgentStartForChannel */ false, /* aListPreload */ false, &proxy);
|
||||
*_retval = proxy;
|
||||
return rv;
|
||||
}
|
||||
@ -2067,7 +2104,7 @@ nsresult imgLoader::LoadImage(
|
||||
nsINode* aContext, Document* aLoadingDocument, nsLoadFlags aLoadFlags,
|
||||
nsISupports* aCacheKey, nsContentPolicyType aContentPolicyType,
|
||||
const nsAString& initiatorType, bool aUseUrgentStartForChannel,
|
||||
imgRequestProxy** _retval) {
|
||||
bool aLinkPreload, imgRequestProxy** _retval) {
|
||||
VerifyCacheSizes();
|
||||
|
||||
NS_ASSERTION(aURI, "imgLoader::LoadImage -- NULL URI pointer");
|
||||
@ -2137,6 +2174,9 @@ nsresult imgLoader::LoadImage(
|
||||
if (aLoadFlags & nsIRequest::LOAD_BACKGROUND) {
|
||||
// Propagate background loading...
|
||||
requestFlags |= nsIRequest::LOAD_BACKGROUND;
|
||||
} else if (aLinkPreload) {
|
||||
// Set background loading if it is <link rel=preload>
|
||||
requestFlags |= nsIRequest::LOAD_BACKGROUND;
|
||||
}
|
||||
|
||||
int32_t corsmode = imgIRequest::CORS_NONE;
|
||||
@ -2146,6 +2186,54 @@ nsresult imgLoader::LoadImage(
|
||||
corsmode = imgIRequest::CORS_USE_CREDENTIALS;
|
||||
}
|
||||
|
||||
// Look in the preloaded images of loading document first.
|
||||
if (StaticPrefs::network_preload_experimental() && !aLinkPreload &&
|
||||
aLoadingDocument) {
|
||||
auto key = PreloadHashKey::CreateAsImage(
|
||||
aURI, aTriggeringPrincipal, ConvertToCORSMode(corsmode),
|
||||
aReferrerInfo ? aReferrerInfo->ReferrerPolicy()
|
||||
: ReferrerPolicy::_empty);
|
||||
if (RefPtr<PreloaderBase> preload =
|
||||
aLoadingDocument->Preloads().LookupPreload(&key)) {
|
||||
RefPtr<imgRequestProxy> proxy = do_QueryObject(preload);
|
||||
MOZ_ASSERT(proxy);
|
||||
|
||||
MOZ_LOG(gImgLog, LogLevel::Debug,
|
||||
("[this=%p] imgLoader::LoadImage -- preloaded [proxy=%p]"
|
||||
" [document=%p]\n",
|
||||
this, proxy.get(), aLoadingDocument));
|
||||
proxy->NotifyUsage();
|
||||
// XXXedgar: we link the preloaded image to all subsequent "real" load,
|
||||
// where Blink seems only link the preloaded image to the next "real"
|
||||
// load.
|
||||
// There is a spec discussion for "preload cache", see
|
||||
// https://github.com/w3c/preload/issues/97. And it is also not clear how
|
||||
// preload image interacts with list of available images, see
|
||||
// https://github.com/whatwg/html/issues/4474.
|
||||
imgRequest* request = proxy->GetOwner();
|
||||
nsresult rv =
|
||||
CreateNewProxyForRequest(request, aURI, aLoadGroup, aLoadingDocument,
|
||||
aObserver, requestFlags, _retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
imgRequestProxy* newProxy = *_retval;
|
||||
if (imgCacheValidator* validator = request->GetValidator()) {
|
||||
newProxy->MarkValidating();
|
||||
// Attach the proxy without notifying and this will add us to the load
|
||||
// group.
|
||||
validator->AddProxy(newProxy);
|
||||
} else {
|
||||
// It's OK to add here even if the request is done. If it is, it'll send
|
||||
// a OnStopRequest()and the proxy will be removed from the loadgroup in
|
||||
// imgRequestProxy::OnLoadComplete.
|
||||
newProxy->AddToLoadGroup();
|
||||
newProxy->NotifyListener();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<imgCacheEntry> entry;
|
||||
|
||||
// Look in the cache for our URI, and then validate it.
|
||||
@ -2164,7 +2252,7 @@ nsresult imgLoader::LoadImage(
|
||||
if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerInfo,
|
||||
aLoadGroup, aObserver, aLoadingDocument, requestFlags,
|
||||
aContentPolicyType, true, &newChannelCreated, _retval,
|
||||
aTriggeringPrincipal, corsmode)) {
|
||||
aTriggeringPrincipal, corsmode, aLinkPreload)) {
|
||||
request = entry->GetRequest();
|
||||
|
||||
// If this entry has no proxies, its request has no reference to the
|
||||
@ -2324,6 +2412,16 @@ nsresult imgLoader::LoadImage(
|
||||
newChannel->SetNotificationCallbacks(requestor);
|
||||
}
|
||||
|
||||
if (aLinkPreload) {
|
||||
MOZ_ASSERT(aLoadingDocument);
|
||||
MOZ_ASSERT(aReferrerInfo);
|
||||
proxy->PrioritizeAsPreload();
|
||||
auto preloadKey = PreloadHashKey::CreateAsImage(
|
||||
aURI, aTriggeringPrincipal, ConvertToCORSMode(corsmode),
|
||||
aReferrerInfo->ReferrerPolicy());
|
||||
proxy->NotifyOpen(&preloadKey, aLoadingDocument, true);
|
||||
}
|
||||
|
||||
// Note that it's OK to add here even if the request is done. If it is,
|
||||
// it'll send a OnStopRequest() to the proxy in imgRequestProxy::Notify and
|
||||
// the proxy will be removed from the loadgroup.
|
||||
@ -2419,7 +2517,8 @@ nsresult imgLoader::LoadImageWithChannel(nsIChannel* channel,
|
||||
|
||||
if (ValidateEntry(entry, uri, nullptr, nullptr, nullptr, aObserver,
|
||||
aLoadingDocument, requestFlags, policyType, false,
|
||||
nullptr, nullptr, nullptr, imgIRequest::CORS_NONE)) {
|
||||
nullptr, nullptr, nullptr, imgIRequest::CORS_NONE,
|
||||
false)) {
|
||||
request = entry->GetRequest();
|
||||
} else {
|
||||
nsCOMPtr<nsICacheInfoChannel> cacheChan(do_QueryInterface(channel));
|
||||
@ -2788,6 +2887,11 @@ void imgCacheValidator::RemoveProxy(imgRequestProxy* aProxy) {
|
||||
mProxies.RemoveElement(aProxy);
|
||||
}
|
||||
|
||||
void imgCacheValidator::PrioritizeAsPreload() {
|
||||
MOZ_ASSERT(mNewRequest);
|
||||
mNewRequest->PrioritizeAsPreload();
|
||||
}
|
||||
|
||||
void imgCacheValidator::UpdateProxies(bool aCancelRequest, bool aSyncNotify) {
|
||||
MOZ_ASSERT(mRequest);
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
#define mozilla_image_imgLoader_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
@ -246,7 +248,8 @@ class imgLoader final : public imgILoader,
|
||||
nsINode* aContext, mozilla::dom::Document* aLoadingDocument,
|
||||
nsLoadFlags aLoadFlags, nsISupports* aCacheKey,
|
||||
nsContentPolicyType aContentPolicyType, const nsAString& initiatorType,
|
||||
bool aUseUrgentStartForChannel, imgRequestProxy** _retval);
|
||||
bool aUseUrgentStartForChannel, bool aLinkPreload,
|
||||
imgRequestProxy** _retval);
|
||||
|
||||
[[nodiscard]] nsresult LoadImageWithChannel(
|
||||
nsIChannel* channel, imgINotificationObserver* aObserver,
|
||||
@ -338,21 +341,23 @@ class imgLoader final : public imgILoader,
|
||||
bool SetHasNoProxies(imgRequest* aRequest, imgCacheEntry* aEntry);
|
||||
bool SetHasProxies(imgRequest* aRequest);
|
||||
|
||||
// This method converts imgIRequest::CORS_* values to mozilla::CORSMode
|
||||
// values.
|
||||
static mozilla::CORSMode ConvertToCORSMode(uint32_t aImgCORS);
|
||||
|
||||
private: // methods
|
||||
static already_AddRefed<imgLoader> CreateImageLoader();
|
||||
|
||||
bool PreferLoadFromCache(nsIURI* aURI) const;
|
||||
|
||||
bool ValidateEntry(imgCacheEntry* aEntry, nsIURI* aKey,
|
||||
nsIURI* aInitialDocumentURI,
|
||||
nsIReferrerInfo* aReferrerInfo, nsILoadGroup* aLoadGroup,
|
||||
imgINotificationObserver* aObserver,
|
||||
mozilla::dom::Document* aLoadingDocument,
|
||||
nsLoadFlags aLoadFlags,
|
||||
nsContentPolicyType aContentPolicyType,
|
||||
bool aCanMakeNewChannel, bool* aNewChannelCreated,
|
||||
imgRequestProxy** aProxyRequest,
|
||||
nsIPrincipal* aLoadingPrincipal, int32_t aCORSMode);
|
||||
bool ValidateEntry(
|
||||
imgCacheEntry* aEntry, nsIURI* aURI, nsIURI* aInitialDocumentURI,
|
||||
nsIReferrerInfo* aReferrerInfo, nsILoadGroup* aLoadGroup,
|
||||
imgINotificationObserver* aObserver,
|
||||
mozilla::dom::Document* aLoadingDocument, nsLoadFlags aLoadFlags,
|
||||
nsContentPolicyType aLoadPolicyType, bool aCanMakeNewChannel,
|
||||
bool* aNewChannelCreated, imgRequestProxy** aProxyRequest,
|
||||
nsIPrincipal* aTriggeringPrincipal, int32_t aCORSMode, bool aLinkPreload);
|
||||
|
||||
bool ValidateRequestWithNewChannel(
|
||||
imgRequest* request, nsIURI* aURI, nsIURI* aInitialDocumentURI,
|
||||
@ -361,7 +366,7 @@ class imgLoader final : public imgILoader,
|
||||
mozilla::dom::Document* aLoadingDocument, uint64_t aInnerWindowId,
|
||||
nsLoadFlags aLoadFlags, nsContentPolicyType aContentPolicyType,
|
||||
imgRequestProxy** aProxyRequest, nsIPrincipal* aLoadingPrincipal,
|
||||
int32_t aCORSMode, bool* aNewChannelCreated);
|
||||
int32_t aCORSMode, bool aLinkPreload, bool* aNewChannelCreated);
|
||||
|
||||
// aURI may be different from imgRequest's URI in the case of blob URIs, as we
|
||||
// can share requests with different URIs.
|
||||
@ -481,6 +486,8 @@ class imgCacheValidator : public nsIStreamListener,
|
||||
void AddProxy(imgRequestProxy* aProxy);
|
||||
void RemoveProxy(imgRequestProxy* aProxy);
|
||||
|
||||
void PrioritizeAsPreload();
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "nsIChannel.h"
|
||||
#include "nsICacheInfoChannel.h"
|
||||
#include "nsIClassOfService.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
#include "nsIInputStream.h"
|
||||
@ -67,7 +68,9 @@ imgRequest::imgRequest(imgLoader* aLoader, const ImageCacheKey& aCacheKey)
|
||||
mIsInCache(false),
|
||||
mDecodeRequested(false),
|
||||
mNewPartPending(false),
|
||||
mHadInsecureRedirect(false) {
|
||||
mHadInsecureRedirect(false),
|
||||
mIsDeniedCrossSiteCORSRequest(false),
|
||||
mIsCrossSiteNoCORSRequest(false) {
|
||||
LOG_FUNC(gImgLog, "imgRequest::imgRequest()");
|
||||
}
|
||||
|
||||
@ -642,6 +645,15 @@ imgRequest::OnStartRequest(nsIRequest* aRequest) {
|
||||
|
||||
RefPtr<Image> image;
|
||||
|
||||
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest)) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = httpChannel->LoadInfo();
|
||||
mIsDeniedCrossSiteCORSRequest =
|
||||
loadInfo->GetTainting() == LoadTainting::CORS &&
|
||||
(NS_FAILED(httpChannel->GetStatus(&rv)) || NS_FAILED(rv));
|
||||
mIsCrossSiteNoCORSRequest = loadInfo->GetTainting() == LoadTainting::Opaque;
|
||||
}
|
||||
|
||||
// Figure out if we're multipart.
|
||||
nsCOMPtr<nsIMultiPartChannel> multiPartChannel = do_QueryInterface(aRequest);
|
||||
MOZ_ASSERT(multiPartChannel || !mIsMultiPartChannel,
|
||||
@ -983,6 +995,13 @@ void imgRequest::FinishPreparingForNewPart(const NewPartResult& aResult) {
|
||||
|
||||
bool imgRequest::ImageAvailable() const { return mImageAvailable; }
|
||||
|
||||
void imgRequest::PrioritizeAsPreload() {
|
||||
if (nsCOMPtr<nsIClassOfService> cos = do_QueryInterface(mChannel)) {
|
||||
cos->AddClassFlags(nsIClassOfService::Unblocked);
|
||||
}
|
||||
AdjustPriorityInternal(nsISupportsPriority::PRIORITY_HIGHEST);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgRequest::OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInStr,
|
||||
uint64_t aOffset, uint32_t aCount) {
|
||||
|
@ -201,6 +201,14 @@ class imgRequest final : public nsIStreamListener,
|
||||
|
||||
bool ImageAvailable() const;
|
||||
|
||||
void PrioritizeAsPreload();
|
||||
|
||||
bool IsDeniedCrossSiteCORSRequest() const {
|
||||
return mIsDeniedCrossSiteCORSRequest;
|
||||
}
|
||||
|
||||
bool IsCrossSiteNoCORSRequest() const { return mIsCrossSiteNoCORSRequest; }
|
||||
|
||||
private:
|
||||
friend class FinishPreparingForNewPartRunnable;
|
||||
|
||||
@ -289,6 +297,8 @@ class imgRequest final : public nsIStreamListener,
|
||||
bool mDecodeRequested : 1;
|
||||
bool mNewPartPending : 1;
|
||||
bool mHadInsecureRedirect : 1;
|
||||
bool mIsDeniedCrossSiteCORSRequest : 1;
|
||||
bool mIsCrossSiteNoCORSRequest : 1;
|
||||
};
|
||||
|
||||
#endif // mozilla_image_imgRequest_h
|
||||
|
@ -93,10 +93,11 @@ NS_IMPL_ADDREF(imgRequestProxy)
|
||||
NS_IMPL_RELEASE(imgRequestProxy)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(imgRequestProxy)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, imgIRequest)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, PreloaderBase)
|
||||
NS_INTERFACE_MAP_ENTRY(imgIRequest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequest)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
|
||||
NS_INTERFACE_MAP_ENTRY_CONCRETE(imgRequestProxy)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITimedChannel, TimedChannel() != nullptr)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
@ -1035,6 +1036,22 @@ void imgRequestProxy::OnLoadComplete(bool aLastPart) {
|
||||
if (aLastPart || (mLoadFlags & nsIRequest::LOAD_BACKGROUND) == 0) {
|
||||
if (aLastPart) {
|
||||
RemoveFromLoadGroup();
|
||||
|
||||
nsresult errorCode = NS_OK;
|
||||
// if the load is cross origin without CORS, or the CORS access is
|
||||
// rejected, always fire load event to avoid leaking site information for
|
||||
// <link rel=preload>.
|
||||
// XXXedgar, currently we don't do the same thing for <img>.
|
||||
imgRequest* request = GetOwner();
|
||||
if (!request || !(request->IsDeniedCrossSiteCORSRequest() ||
|
||||
request->IsCrossSiteNoCORSRequest())) {
|
||||
uint32_t status = imgIRequest::STATUS_NONE;
|
||||
GetImageStatus(&status);
|
||||
if (status & imgIRequest::STATUS_ERROR) {
|
||||
errorCode = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
NotifyStop(errorCode);
|
||||
} else {
|
||||
// More data is coming, so change the request to be a background request
|
||||
// and put it back in the loadgroup.
|
||||
@ -1190,6 +1207,15 @@ imgCacheValidator* imgRequestProxy::GetValidator() const {
|
||||
return owner->GetValidator();
|
||||
}
|
||||
|
||||
void imgRequestProxy::PrioritizeAsPreload() {
|
||||
if (imgRequest* owner = GetOwner()) {
|
||||
owner->PrioritizeAsPreload();
|
||||
}
|
||||
if (imgCacheValidator* validator = GetValidator()) {
|
||||
validator->PrioritizeAsPreload();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////// imgRequestProxyStatic methods
|
||||
|
||||
class StaticBehaviour : public ProxyBehaviour {
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/PreloaderBase.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
@ -40,7 +41,8 @@ class ProgressTracker;
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
class imgRequestProxy : public imgIRequest,
|
||||
class imgRequestProxy : public mozilla::PreloaderBase,
|
||||
public imgIRequest,
|
||||
public mozilla::image::IProgressObserver,
|
||||
public nsISupportsPriority,
|
||||
public nsITimedChannel {
|
||||
@ -52,6 +54,7 @@ class imgRequestProxy : public imgIRequest,
|
||||
typedef mozilla::image::Image Image;
|
||||
typedef mozilla::image::ProgressTracker ProgressTracker;
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IMGREQUESTPROXY_CID)
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(imgRequestProxy)
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_IMGIREQUEST
|
||||
@ -124,6 +127,11 @@ class imgRequestProxy : public imgIRequest,
|
||||
nsresult GetStaticRequest(Document* aLoadingDocument,
|
||||
imgRequestProxy** aReturn);
|
||||
|
||||
imgRequest* GetOwner() const;
|
||||
|
||||
// PreloaderBase
|
||||
virtual void PrioritizeAsPreload() override;
|
||||
|
||||
protected:
|
||||
friend class mozilla::image::ProgressTracker;
|
||||
friend class imgStatusNotifyRunnable;
|
||||
@ -173,7 +181,6 @@ class imgRequestProxy : public imgIRequest,
|
||||
|
||||
already_AddRefed<Image> GetImage() const;
|
||||
bool HasImage() const;
|
||||
imgRequest* GetOwner() const;
|
||||
imgCacheValidator* GetValidator() const;
|
||||
|
||||
nsresult PerformClone(imgINotificationObserver* aObserver,
|
||||
@ -228,6 +235,8 @@ class imgRequestProxy : public imgIRequest,
|
||||
bool mHadDispatch : 1;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(imgRequestProxy, NS_IMGREQUESTPROXY_CID)
|
||||
|
||||
// Used for static image proxies for which no requests are available, so
|
||||
// certain behaviours must be overridden to compensate.
|
||||
class imgRequestProxyStatic : public imgRequestProxy {
|
||||
|
@ -2473,6 +2473,7 @@ nsresult nsImageFrame::LoadIcon(const nsAString& aSpec,
|
||||
nullptr, /* Not associated with any particular document */
|
||||
loadFlags, nullptr, contentPolicyType, EmptyString(),
|
||||
false, /* aUseUrgentStartForChannel */
|
||||
false, /* aLinkPreload */
|
||||
aRequest);
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ void nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor) {
|
||||
aExecutor->PreloadImage(
|
||||
mUrlOrSizes, mCrossOriginOrMedia, mCharsetOrSrcset,
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
|
||||
mReferrerPolicyOrIntegrity);
|
||||
mReferrerPolicyOrIntegrity, mIsLinkPreload);
|
||||
break;
|
||||
case eSpeculativeLoadOpenPicture:
|
||||
aExecutor->PreloadOpenPicture();
|
||||
|
@ -73,7 +73,7 @@ class nsHtml5SpeculativeLoad {
|
||||
|
||||
inline void InitImage(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
|
||||
nsHtml5String aReferrerPolicy, nsHtml5String aSrcset,
|
||||
nsHtml5String aSizes) {
|
||||
nsHtml5String aSizes, bool aLinkPreload) {
|
||||
MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
|
||||
"Trying to reinitialize a speculative load!");
|
||||
mOpCode = eSpeculativeLoadImage;
|
||||
@ -88,6 +88,7 @@ class nsHtml5SpeculativeLoad {
|
||||
aSrcset.ToString(mCharsetOrSrcset);
|
||||
aSizes.ToString(
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
|
||||
mIsLinkPreload = aLinkPreload;
|
||||
}
|
||||
|
||||
// <picture> elements have multiple <source> nodes followed by an <img>,
|
||||
|
@ -186,7 +186,7 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
|
||||
nsHtml5String sizes =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
|
||||
mSpeculativeLoadQueue.AppendElement()->InitImage(
|
||||
url, crossOrigin, referrerPolicy, srcset, sizes);
|
||||
url, crossOrigin, referrerPolicy, srcset, sizes, false);
|
||||
}
|
||||
} else if (nsGkAtoms::source == aName) {
|
||||
nsHtml5String srcset =
|
||||
@ -306,6 +306,13 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
|
||||
mSpeculativeLoadQueue.AppendElement()->InitStyle(
|
||||
url, charset, crossOrigin, referrerPolicy, integrity,
|
||||
true);
|
||||
} else if (as.LowerCaseEqualsASCII("image")) {
|
||||
nsHtml5String srcset = aAttributes->getValue(
|
||||
nsHtml5AttributeName::ATTR_IMAGESRCSET);
|
||||
nsHtml5String sizes = aAttributes->getValue(
|
||||
nsHtml5AttributeName::ATTR_IMAGESIZES);
|
||||
mSpeculativeLoadQueue.AppendElement()->InitImage(
|
||||
url, crossOrigin, referrerPolicy, srcset, sizes, true);
|
||||
}
|
||||
// Other "as" values will be supported later.
|
||||
}
|
||||
@ -316,7 +323,7 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_POSTER);
|
||||
if (url) {
|
||||
mSpeculativeLoadQueue.AppendElement()->InitImage(
|
||||
url, nullptr, nullptr, nullptr, nullptr);
|
||||
url, nullptr, nullptr, nullptr, nullptr, false);
|
||||
}
|
||||
} else if (nsGkAtoms::style == aName) {
|
||||
mImportScanner.Start();
|
||||
@ -369,7 +376,7 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_XLINK_HREF);
|
||||
if (url) {
|
||||
mSpeculativeLoadQueue.AppendElement()->InitImage(
|
||||
url, nullptr, nullptr, nullptr, nullptr);
|
||||
url, nullptr, nullptr, nullptr, nullptr, false);
|
||||
}
|
||||
} else if (nsGkAtoms::script == aName) {
|
||||
nsHtml5TreeOperation* treeOp =
|
||||
|
@ -1004,10 +1004,12 @@ void nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL,
|
||||
aLinkPreload);
|
||||
}
|
||||
|
||||
void nsHtml5TreeOpExecutor::PreloadImage(
|
||||
const nsAString& aURL, const nsAString& aCrossOrigin,
|
||||
const nsAString& aSrcset, const nsAString& aSizes,
|
||||
const nsAString& aImageReferrerPolicy) {
|
||||
void nsHtml5TreeOpExecutor::PreloadImage(const nsAString& aURL,
|
||||
const nsAString& aCrossOrigin,
|
||||
const nsAString& aSrcset,
|
||||
const nsAString& aSizes,
|
||||
const nsAString& aImageReferrerPolicy,
|
||||
bool aLinkPreload) {
|
||||
nsCOMPtr<nsIURI> baseURI = BaseURIForPreload();
|
||||
bool isImgSet = false;
|
||||
nsCOMPtr<nsIURI> uri =
|
||||
@ -1016,7 +1018,7 @@ void nsHtml5TreeOpExecutor::PreloadImage(
|
||||
// use document wide referrer policy
|
||||
mDocument->MaybePreLoadImage(uri, aCrossOrigin,
|
||||
GetPreloadReferrerPolicy(aImageReferrerPolicy),
|
||||
isImgSet);
|
||||
isImgSet, aLinkPreload);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,7 +243,7 @@ class nsHtml5TreeOpExecutor final
|
||||
|
||||
void PreloadImage(const nsAString& aURL, const nsAString& aCrossOrigin,
|
||||
const nsAString& aSrcset, const nsAString& aSizes,
|
||||
const nsAString& aImageReferrerPolicy);
|
||||
const nsAString& aImageReferrerPolicy, bool aLinkPreload);
|
||||
|
||||
void PreloadOpenPicture();
|
||||
|
||||
|
@ -23,6 +23,7 @@ PreloadHashKey::PreloadHashKey(PreloadHashKey&& aToMove)
|
||||
mAs = std::move(aToMove.mAs);
|
||||
mCORSMode = std::move(aToMove.mCORSMode);
|
||||
mReferrerPolicy = std::move(aToMove.mReferrerPolicy);
|
||||
mPrincipal = std::move(aToMove.mPrincipal);
|
||||
|
||||
switch (mAs) {
|
||||
case ResourceType::SCRIPT:
|
||||
@ -51,6 +52,7 @@ PreloadHashKey& PreloadHashKey::operator=(const PreloadHashKey& aOther) {
|
||||
mAs = aOther.mAs;
|
||||
mCORSMode = aOther.mCORSMode;
|
||||
mReferrerPolicy = aOther.mReferrerPolicy;
|
||||
mPrincipal = aOther.mPrincipal;
|
||||
|
||||
switch (mAs) {
|
||||
case ResourceType::SCRIPT:
|
||||
@ -104,8 +106,8 @@ PreloadHashKey PreloadHashKey::CreateAsStyle(
|
||||
CORSMode aCORSMode, css::SheetParsingMode aParsingMode) {
|
||||
PreloadHashKey key(aURI, ResourceType::STYLE);
|
||||
key.mCORSMode = aCORSMode;
|
||||
key.mPrincipal = aPrincipal;
|
||||
|
||||
key.mStyle.mPrincipal = aPrincipal;
|
||||
key.mStyle.mParsingMode = aParsingMode;
|
||||
key.mStyle.mReferrerInfo = aReferrerInfo;
|
||||
|
||||
@ -121,11 +123,31 @@ PreloadHashKey PreloadHashKey::CreateAsStyle(
|
||||
aSheetLoadData.mSheet->ParsingMode());
|
||||
}
|
||||
|
||||
// static
|
||||
PreloadHashKey PreloadHashKey::CreateAsImage(
|
||||
nsIURI* aURI, nsIPrincipal* aPrincipal, CORSMode aCORSMode,
|
||||
dom::ReferrerPolicy const& aReferrerPolicy) {
|
||||
PreloadHashKey key(aURI, ResourceType::IMAGE);
|
||||
key.mReferrerPolicy = aReferrerPolicy;
|
||||
key.mCORSMode = aCORSMode;
|
||||
key.mPrincipal = aPrincipal;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
bool PreloadHashKey::KeyEquals(KeyTypePointer aOther) const {
|
||||
if (mAs != aOther->mAs || mCORSMode != aOther->mCORSMode ||
|
||||
mReferrerPolicy != aOther->mReferrerPolicy) {
|
||||
return false;
|
||||
}
|
||||
if (!mPrincipal != !aOther->mPrincipal) {
|
||||
// One or the other has a principal, but not both... not equal
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mPrincipal && !mPrincipal->Equals(aOther->mPrincipal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nsURIHashKey::KeyEquals(
|
||||
static_cast<const nsURIHashKey*>(aOther)->GetKey())) {
|
||||
@ -139,10 +161,6 @@ bool PreloadHashKey::KeyEquals(KeyTypePointer aOther) const {
|
||||
}
|
||||
break;
|
||||
case ResourceType::STYLE: {
|
||||
if (!mStyle.mPrincipal != !aOther->mStyle.mPrincipal) {
|
||||
// One or the other has a principal, but not both... not equal
|
||||
return false;
|
||||
}
|
||||
if (mStyle.mParsingMode != aOther->mStyle.mParsingMode) {
|
||||
return false;
|
||||
}
|
||||
@ -152,14 +170,13 @@ bool PreloadHashKey::KeyEquals(KeyTypePointer aOther) const {
|
||||
!eq) {
|
||||
return false;
|
||||
}
|
||||
if (mStyle.mPrincipal && (NS_FAILED(mStyle.mPrincipal->Equals(
|
||||
aOther->mStyle.mPrincipal, &eq)) ||
|
||||
!eq)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ResourceType::IMAGE:
|
||||
// No more checks needed. The image cache key consists of the document
|
||||
// (which we are scoped into), origin attributes (which we compare as part
|
||||
// of the principal check) and the URL. imgLoader::ValidateEntry compares
|
||||
// CORS, referrer info and principal, which we do by default.
|
||||
break;
|
||||
case ResourceType::FONT:
|
||||
break;
|
||||
|
@ -56,8 +56,12 @@ class PreloadHashKey : public nsURIHashKey {
|
||||
css::SheetParsingMode aParsingMode);
|
||||
static PreloadHashKey CreateAsStyle(css::SheetLoadData& aSheetLoadData);
|
||||
|
||||
// Construct key for "image"
|
||||
static PreloadHashKey CreateAsImage(
|
||||
nsIURI* aURI, nsIPrincipal* aPrincipal, CORSMode aCORSMode,
|
||||
dom::ReferrerPolicy const& aReferrerPolicy);
|
||||
|
||||
// TODO
|
||||
// static CreateAsImage(...);
|
||||
// static CreateAsFont(...);
|
||||
// static CreateAsFetch(...);
|
||||
|
||||
@ -83,13 +87,13 @@ class PreloadHashKey : public nsURIHashKey {
|
||||
|
||||
CORSMode mCORSMode = CORS_NONE;
|
||||
enum dom::ReferrerPolicy mReferrerPolicy = dom::ReferrerPolicy::_empty;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
||||
struct {
|
||||
dom::ScriptKind mScriptKind = dom::ScriptKind::eClassic;
|
||||
} mScript;
|
||||
|
||||
struct {
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
|
||||
css::SheetParsingMode mParsingMode = css::eAuthorSheetFeatures;
|
||||
} mStyle;
|
||||
|
@ -80,6 +80,7 @@ already_AddRefed<PreloaderBase> PreloadService::PreloadLinkElement(
|
||||
aLinkElement->GetReferrerPolicy(referrerPolicyAttr);
|
||||
auto referrerPolicy = PreloadReferrerPolicy(referrerPolicyAttr);
|
||||
|
||||
bool isImgSet = false;
|
||||
PreloadHashKey preloadKey;
|
||||
|
||||
if (as.LowerCaseEqualsASCII("script")) {
|
||||
@ -96,6 +97,21 @@ already_AddRefed<PreloaderBase> PreloadService::PreloadLinkElement(
|
||||
uri, mDocument->NodePrincipal(), referrerInfo,
|
||||
dom::Element::StringToCORSMode(crossOrigin),
|
||||
css::eAuthorSheetFeatures /* see Loader::LoadSheet */);
|
||||
} else if (as.LowerCaseEqualsASCII("image")) {
|
||||
aLinkElement->GetImageSrcset(srcset);
|
||||
aLinkElement->GetImageSizes(sizes);
|
||||
nsAutoString url;
|
||||
aLinkElement->GetHref(url);
|
||||
uri = mDocument->ResolvePreloadImage(BaseURIForPreload(), url, srcset,
|
||||
sizes, &isImgSet);
|
||||
if (!uri) {
|
||||
NotifyNodeEvent(aLinkElement, false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
preloadKey = PreloadHashKey::CreateAsImage(
|
||||
uri, mDocument->NodePrincipal(),
|
||||
dom::Element::StringToCORSMode(crossOrigin), referrerPolicy);
|
||||
} else {
|
||||
NotifyNodeEvent(aLinkElement, false);
|
||||
return nullptr;
|
||||
@ -108,6 +124,8 @@ already_AddRefed<PreloaderBase> PreloadService::PreloadLinkElement(
|
||||
integrity, true /* isInHead - TODO */);
|
||||
} else if (as.LowerCaseEqualsASCII("style")) {
|
||||
PreloadStyle(uri, charset, crossOrigin, referrerPolicyAttr, integrity);
|
||||
} else if (as.LowerCaseEqualsASCII("image")) {
|
||||
PreloadImage(uri, crossOrigin, referrerPolicyAttr, isImgSet);
|
||||
}
|
||||
|
||||
preload = LookupPreload(&preloadKey);
|
||||
@ -142,6 +160,14 @@ void PreloadService::PreloadStyle(nsIURI* aURI, const nsAString& aCharset,
|
||||
true);
|
||||
}
|
||||
|
||||
void PreloadService::PreloadImage(nsIURI* aURI, const nsAString& aCrossOrigin,
|
||||
const nsAString& aImageReferrerPolicy,
|
||||
bool aIsImgSet) {
|
||||
mDocument->PreLoadImage(aURI, aCrossOrigin,
|
||||
PreloadReferrerPolicy(aImageReferrerPolicy),
|
||||
aIsImgSet, true);
|
||||
}
|
||||
|
||||
// static
|
||||
void PreloadService::NotifyNodeEvent(nsINode* aNode, bool aSuccess) {
|
||||
if (!aNode->IsInComposedDoc()) {
|
||||
|
@ -18,6 +18,7 @@ namespace dom {
|
||||
|
||||
class HTMLLinkElement;
|
||||
class Document;
|
||||
enum class ReferrerPolicy : uint8_t;
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@ -71,6 +72,9 @@ class PreloadService {
|
||||
const nsAString& aReferrerPolicy,
|
||||
const nsAString& aIntegrity);
|
||||
|
||||
void PreloadImage(nsIURI* aURI, const nsAString& aCrossOrigin,
|
||||
const nsAString& aImageReferrerPolicy, bool aIsImgSet);
|
||||
|
||||
static void NotifyNodeEvent(nsINode* aNode, bool aSuccess);
|
||||
|
||||
private:
|
||||
|
@ -81,8 +81,8 @@ void PreloaderBase::AddLoadBackgroundFlag(nsIChannel* aChannel) {
|
||||
aChannel->SetLoadFlags(loadFlags | nsIRequest::LOAD_BACKGROUND);
|
||||
}
|
||||
|
||||
void PreloaderBase::NotifyOpen(PreloadHashKey* aKey, nsIChannel* aChannel,
|
||||
dom::Document* aDocument, bool aIsPreload) {
|
||||
void PreloaderBase::NotifyOpen(PreloadHashKey* aKey, dom::Document* aDocument,
|
||||
bool aIsPreload) {
|
||||
if (aDocument && !aDocument->Preloads().RegisterPreload(aKey, this)) {
|
||||
// This means there is already a preload registered under this key in this
|
||||
// document. We only allow replacement when this is a regular load.
|
||||
@ -92,9 +92,14 @@ void PreloaderBase::NotifyOpen(PreloadHashKey* aKey, nsIChannel* aChannel,
|
||||
aDocument->Preloads().RegisterPreload(aKey, this);
|
||||
}
|
||||
|
||||
mChannel = aChannel;
|
||||
mKey = *aKey;
|
||||
mIsUsed = !aIsPreload;
|
||||
}
|
||||
|
||||
void PreloaderBase::NotifyOpen(PreloadHashKey* aKey, nsIChannel* aChannel,
|
||||
dom::Document* aDocument, bool aIsPreload) {
|
||||
NotifyOpen(aKey, aDocument, aIsPreload);
|
||||
mChannel = aChannel;
|
||||
|
||||
// * Start the usage timer if aIsPreload.
|
||||
|
||||
|
@ -47,6 +47,8 @@ class PreloaderBase : public SupportsWeakPtr<PreloaderBase>,
|
||||
// Called by resource loaders to register this preload in the document's
|
||||
// preload service to provide coalescing, and access to the preload when it
|
||||
// should be used for an actual load.
|
||||
void NotifyOpen(PreloadHashKey* aKey, dom::Document* aDocument,
|
||||
bool aIsPreload);
|
||||
void NotifyOpen(PreloadHashKey* aKey, nsIChannel* aChannel,
|
||||
dom::Document* aDocument, bool aIsPreload);
|
||||
|
||||
@ -62,6 +64,9 @@ class PreloaderBase : public SupportsWeakPtr<PreloaderBase>,
|
||||
// (OnStartRequest or equal) and when it finished (OnStopRequest or equal)
|
||||
void NotifyStart(nsIRequest* aRequest);
|
||||
void NotifyStop(nsIRequest* aRequest, nsresult aStatus);
|
||||
// Use this variant only in complement to NotifyOpen without providing a
|
||||
// channel.
|
||||
void NotifyStop(nsresult aStatus);
|
||||
|
||||
// Called when this currently existing load has to be asynchronously
|
||||
// revalidated before it can be used. This prevents link preload DOM nodes
|
||||
@ -108,7 +113,6 @@ class PreloaderBase : public SupportsWeakPtr<PreloaderBase>,
|
||||
virtual ~PreloaderBase();
|
||||
|
||||
private:
|
||||
void NotifyStop(nsresult aStatus);
|
||||
void NotifyNodeEvent(nsINode* aNode);
|
||||
|
||||
// A helper class that will update the PreloaderBase.mChannel member when a
|
||||
|
@ -101,12 +101,13 @@ nsresult nsIconLoaderService::LoadIcon(nsIURI* aIconURI, bool aIsInternalIcon =
|
||||
if (aIsInternalIcon) {
|
||||
rv = loader->LoadImage(aIconURI, nullptr, nullptr, nullptr, 0, loadGroup, this, nullptr,
|
||||
nullptr, nsIRequest::LOAD_NORMAL, nullptr, mContentType, EmptyString(),
|
||||
/* aUseUrgentStartForChannel */ false, getter_AddRefs(mIconRequest));
|
||||
/* aUseUrgentStartForChannel */ false, /* aLinkPreload */ false,
|
||||
getter_AddRefs(mIconRequest));
|
||||
} else {
|
||||
rv = loader->LoadImage(aIconURI, nullptr, nullptr, mContent->NodePrincipal(), 0, loadGroup,
|
||||
this, mContent, document, nsIRequest::LOAD_NORMAL, nullptr, mContentType,
|
||||
EmptyString(),
|
||||
/* aUseUrgentStartForChannel */ false, getter_AddRefs(mIconRequest));
|
||||
EmptyString(), /* aUseUrgentStartForChannel */ false,
|
||||
/* aLinkPreload */ false, getter_AddRefs(mIconRequest));
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
|
Loading…
x
Reference in New Issue
Block a user