diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index db5d64dd633a..5e18485b4672 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -21,6 +21,7 @@ #include "mozilla/SchedulerGroup.h" #include "mozilla/URLPreloader.h" #include "nsIRunnable.h" +#include "nsISupportsPriority.h" #include "nsITimedChannel.h" #include "nsICachingChannel.h" #include "nsSyncLoadService.h" @@ -412,6 +413,14 @@ SheetLoadData::AfterProcessNextEvent(nsIThreadInternal* aThread, return NS_OK; } +void SheetLoadData::PrioritizeAsPreload(nsIChannel* aChannel) { + if (nsCOMPtr sp = do_QueryInterface(aChannel)) { + sp->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST); + } +} + +void SheetLoadData::PrioritizeAsPreload() { PrioritizeAsPreload(Channel()); } + void SheetLoadData::FireLoadEvent(nsIThreadInternal* aThread) { // First remove ourselves as a thread observer. But we need to keep // ourselves alive while doing that! @@ -1239,6 +1248,9 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState) { SheetLoadDataHashKey key(aLoadData); mLoadsPerformed.PutEntry(key); + + auto preloadKey = PreloadHashKey::CreateAsStyle(aLoadData); + bool coalescedLoad = false; if (mSheets) { // If we have at least one other load ongoing, then we can defer it until // all non-pending loads are done. @@ -1249,17 +1261,23 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState) { mSheets->DeferSheetLoad(aLoadData); return NS_OK; } - if (mSheets->CoalesceLoad(key, aLoadData, aSheetState)) { + + if ((coalescedLoad = mSheets->CoalesceLoad(key, aLoadData, aSheetState))) { if (aSheetState == SheetState::Pending) { ++mPendingLoadCount; + return NS_OK; } - - // All done here; once the load completes we'll be marked complete - // automatically - return NS_OK; } } + aLoadData.NotifyOpen(preloadKey, mDocument, + aLoadData.mIsPreload == IsPreload::FromLink); + if (coalescedLoad) { + // All done here; once the load completes we'll be marked complete + // automatically. + return NS_OK; + } + nsCOMPtr loadGroup; nsCOMPtr cookieJarSettings; if (mDocument) { @@ -1339,8 +1357,8 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState) { cos->AddClassFlags(nsIClassOfService::Leader); } if (aLoadData.mIsPreload == IsPreload::FromLink) { - StreamLoader::PrioritizeAsPreload(channel); - StreamLoader::AddLoadBackgroundFlag(channel); + SheetLoadData::PrioritizeAsPreload(channel); + SheetLoadData::AddLoadBackgroundFlag(channel); } } @@ -1414,16 +1432,12 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState) { nsINetworkPredictor::LEARN_LOAD_SUBRESOURCE, mDocument); } - auto preloadKey = PreloadHashKey::CreateAsStyle(aLoadData); - streamLoader->NotifyOpen(preloadKey, channel, mDocument, - aLoadData.mIsPreload == IsPreload::FromLink); - rv = channel->AsyncOpen(streamLoader); if (NS_FAILED(rv)) { LOG_ERROR((" Failed to create stream loader")); - // ChannelOpenFailed makes sure that nodes will get the - // proper notification about not being able to load this resource. streamLoader->ChannelOpenFailed(rv); + // NOTE: NotifyStop will be done in SheetComplete -> NotifyObservers. + aLoadData.NotifyStart(channel); SheetComplete(aLoadData, rv); return rv; } @@ -1497,6 +1511,7 @@ void Loader::NotifyObservers(SheetLoadData& aData, nsresult aStatus) { if (aData.mURI) { MOZ_DIAGNOSTIC_ASSERT(mOngoingLoadCount); --mOngoingLoadCount; + aData.NotifyStop(aStatus); } if (aData.mMustNotify) { diff --git a/layout/style/SheetLoadData.h b/layout/style/SheetLoadData.h index c229679a3734..21a5f07b7bcb 100644 --- a/layout/style/SheetLoadData.h +++ b/layout/style/SheetLoadData.h @@ -10,6 +10,7 @@ #include "mozilla/css/Loader.h" #include "mozilla/css/SheetParsingMode.h" #include "mozilla/Encoding.h" +#include "mozilla/PreloaderBase.h" #include "mozilla/NotNull.h" #include "mozilla/UniquePtr.h" #include "nsIThreadInternal.h" @@ -37,7 +38,9 @@ static_assert(eAuthorSheetFeatures == 0 && eUserSheetFeatures == 1 && "sheet parsing mode constants won't fit " "in SheetLoadData::mParsingMode"); -class SheetLoadData final : public nsIRunnable, public nsIThreadObserver { +class SheetLoadData final : public PreloaderBase, + public nsIRunnable, + public nsIThreadObserver { using MediaMatched = dom::LinkStyle::MediaMatched; using IsAlternate = dom::LinkStyle::IsAlternate; using IsPreload = Loader::IsPreload; @@ -47,6 +50,10 @@ class SheetLoadData final : public nsIRunnable, public nsIThreadObserver { virtual ~SheetLoadData(); public: + // PreloaderBase + static void PrioritizeAsPreload(nsIChannel* aChannel); + void PrioritizeAsPreload() final; + // Data for loading a sheet linked from a document SheetLoadData(Loader* aLoader, const nsAString& aTitle, nsIURI* aURI, StyleSheet* aSheet, bool aSyncLoad, nsINode* aOwningNode, diff --git a/layout/style/StreamLoader.cpp b/layout/style/StreamLoader.cpp index 7e762f94d3ad..256177fdaaaa 100644 --- a/layout/style/StreamLoader.cpp +++ b/layout/style/StreamLoader.cpp @@ -11,7 +11,6 @@ #include "nsContentUtils.h" #include "nsIChannel.h" #include "nsIInputStream.h" -#include "nsISupportsPriority.h" #include @@ -31,19 +30,11 @@ StreamLoader::~StreamLoader() { NS_IMPL_ISUPPORTS(StreamLoader, nsIStreamListener) -// static -void StreamLoader::PrioritizeAsPreload(nsIChannel* aChannel) { - if (nsCOMPtr sp = do_QueryInterface(aChannel)) { - sp->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST); - } -} - -void StreamLoader::PrioritizeAsPreload() { PrioritizeAsPreload(Channel()); } - /* nsIRequestObserver implementation */ NS_IMETHODIMP StreamLoader::OnStartRequest(nsIRequest* aRequest) { - NotifyStart(aRequest); + MOZ_ASSERT(aRequest); + mSheetLoadData->NotifyStart(aRequest); // It's kinda bad to let Web content send a number that results // in a potentially large allocation directly, but efficiency of @@ -72,8 +63,6 @@ StreamLoader::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) { #endif nsresult rv = mStatus; - auto notifyStop = MakeScopeExit([&] { NotifyStop(aRequest, rv); }); - // Decoded data nsCString utf8String; { @@ -93,11 +82,6 @@ StreamLoader::OnStopRequest(nsIRequest* aRequest, nsresult aStatus) { rv = mSheetLoadData->VerifySheetReadyToParse(aStatus, mBOMBytes, bytes, channel); if (rv != NS_OK_PARSE_SHEET) { - // VerifySheetReadyToParse returns `NS_OK` when there was something wrong - // with the script. We need to override the result so that any tags associted to this load will be notified the "error" - // event. It's fine because this error goes no where. - rv = NS_ERROR_NOT_AVAILABLE; return rv; } diff --git a/layout/style/StreamLoader.h b/layout/style/StreamLoader.h index 135d0d30c678..96c1588d17c5 100644 --- a/layout/style/StreamLoader.h +++ b/layout/style/StreamLoader.h @@ -11,31 +11,24 @@ #include "nsString.h" #include "mozilla/css/SheetLoadData.h" #include "mozilla/Assertions.h" -#include "mozilla/PreloaderBase.h" class nsIInputStream; namespace mozilla { namespace css { -class StreamLoader : public PreloaderBase, public nsIStreamListener { +class StreamLoader : public nsIStreamListener { public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER - // PreloaderBase - static void PrioritizeAsPreload(nsIChannel* aChannel); - virtual void PrioritizeAsPreload() override; - explicit StreamLoader(SheetLoadData&); void ChannelOpenFailed(nsresult rv) { #ifdef NIGHTLY_BUILD mChannelOpenFailed = true; #endif - NotifyStart(Channel()); - NotifyStop(Channel(), rv); } private: