☠☠ backed out by e2b41473c7ed ☠ ☠ | |
author | Manuel Bucher <manuel@mozilla.com> |
Fri, 02 Dec 2022 09:45:24 +0000 | |
changeset 644479 | 5090eae24a5cfedad6feda5bc9dd400c501162f5 |
parent 644478 | f8a03d226c73c926268d0f60f8477b4268be9bd4 |
child 644480 | 7cdf3cef27736a14fd8f9db58522da37e103d984 |
push id | 40449 |
push user | csabou@mozilla.com |
push date | Fri, 02 Dec 2022 21:26:33 +0000 |
treeherder | mozilla-central@360f8b71c676 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | necko-reviewers, valentin |
bugs | 1771867 |
milestone | 109.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -6742,16 +6742,21 @@ void Document::SetHeaderData(nsAtom* aHe mAllowDNSPrefetch = aData.IsEmpty() || aData.LowerCaseEqualsLiteral("on"); } if (aHeaderField == nsGkAtoms::handheldFriendly) { mViewportType = Unknown; } } +void Document::SetEarlyHints( + nsTArray<net::EarlyHintConnectArgs>&& aEarlyHints) { + mEarlyHints = std::move(aEarlyHints); +} + void Document::TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource, NotNull<const Encoding*>& aEncoding, nsHtml5TreeOpExecutor* aExecutor) { if (aChannel) { nsAutoCString charsetVal; nsresult rv = aChannel->GetContentCharset(charsetVal); if (NS_SUCCEEDED(rv)) { const Encoding* preferred = Encoding::ForLabel(charsetVal);
--- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -317,16 +317,17 @@ enum BFCacheStatus { ACTIVE_LOCK = 1 << 16, // Status 16 }; } // namespace dom } // namespace mozilla namespace mozilla::net { class ChannelEventQueue; +class EarlyHintConnectArgs; } // namespace mozilla::net // Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs #define NS_IDOCUMENT_IID \ { \ 0xce1f7627, 0x7109, 0x4977, { \ 0xba, 0x77, 0x49, 0x0f, 0xfd, 0xe0, 0x7a, 0xaa \ } \ @@ -1164,16 +1165,25 @@ class Document : public nsINode, /** * Access HTTP header data (this may also get set from other * sources, like HTML META tags). */ void GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const; void SetHeaderData(nsAtom* aheaderField, const nsAString& aData); /** + * Set Early Hint data, moves the arrays into the function, leaving the + * passed variables empty + */ + void SetEarlyHints(nsTArray<net::EarlyHintConnectArgs>&& aEarlyHints); + const nsTArray<net::EarlyHintConnectArgs>& GetEarlyHints() const { + return mEarlyHints; + } + + /** * Create a new presentation shell that will use aContext for its * presentation context (presentation contexts <b>must not</b> be * shared among multiple presentation shells). The caller of this * method is responsible for calling BeginObservingDocument() on the * presshell if the presshell should observe document mutations. */ already_AddRefed<PresShell> CreatePresShell(nsPresContext* aContext, nsViewManager* aViewManager); @@ -5112,16 +5122,18 @@ class Document : public nsINode, // https://drafts.csswg.org/css-round-display/#viewport-fit-descriptor ViewportFitType mViewportFit; PLDHashTable* mSubDocuments; class HeaderData; UniquePtr<HeaderData> mHeaderData; + nsTArray<net::EarlyHintConnectArgs> mEarlyHints; + nsRevocableEventPtr<nsRunnableMethod<Document, void, false>> mPendingTitleChangeEvent; RefPtr<nsDOMNavigationTiming> mTiming; // Recorded time of change to 'loading' state. TimeStamp mLoadingTimeStamp;
--- a/dom/base/moz.build +++ b/dom/base/moz.build @@ -564,16 +564,17 @@ LOCAL_INCLUDES += [ "/js/xpconnect/src", "/js/xpconnect/wrappers", "/layout/base", "/layout/forms", "/layout/generic", "/layout/style", "/layout/xul", "/netwerk/base", + "/netwerk/protocol/http", "/netwerk/url-classifier", "/parser/htmlparser", "/security/manager/ssl", "/widget", "/xpcom/ds", ] if CONFIG["MOZ_WEBRTC"]:
--- a/dom/base/nsContentSink.cpp +++ b/dom/base/nsContentSink.cpp @@ -15,16 +15,18 @@ #include "mozilla/StaticPrefs_browser.h" #include "mozilla/StaticPrefs_content.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/LinkStyle.h" #include "mozilla/css/Loader.h" #include "mozilla/dom/MutationObservers.h" #include "mozilla/dom/SRILogHelper.h" #include "mozilla/StoragePrincipalHelper.h" +#include "mozilla/net/HttpBaseChannel.h" +#include "mozilla/net/NeckoChannelParams.h" #include "nsIDocShell.h" #include "nsILoadContext.h" #include "nsIPrefetchService.h" #include "nsIURI.h" #include "nsNetUtil.h" #include "nsIMIMEHeaderParam.h" #include "nsIProtocolHandler.h" #include "nsIHttpChannel.h" @@ -217,47 +219,62 @@ nsContentSink::StyleSheetLoaded(StyleShe nsresult nsContentSink::ProcessHTTPHeaders(nsIChannel* aChannel) { nsCOMPtr<nsIHttpChannel> httpchannel(do_QueryInterface(aChannel)); if (!httpchannel) { return NS_OK; } + bool gotEarlyHints = false; + if (nsCOMPtr<mozilla::net::HttpBaseChannel> baseChannel = + do_QueryInterface(aChannel)) { + nsTArray<mozilla::net::EarlyHintConnectArgs> earlyHints = + baseChannel->TakeEarlyHints(); + gotEarlyHints = !earlyHints.IsEmpty(); + mDocument->SetEarlyHints(std::move(earlyHints)); + } + // Note that the only header we care about is the "link" header, since we // have all the infrastructure for kicking off stylesheet loads. nsAutoCString linkHeader; nsresult rv = httpchannel->GetResponseHeader("link"_ns, linkHeader); - if (NS_SUCCEEDED(rv) && !linkHeader.IsEmpty()) { + bool gotLinkHeader = NS_SUCCEEDED(rv) && !linkHeader.IsEmpty(); + if (gotLinkHeader) { mDocument->SetHeaderData(nsGkAtoms::link, NS_ConvertASCIItoUTF16(linkHeader)); - + } + if (gotLinkHeader || gotEarlyHints) { NS_ASSERTION(!mProcessLinkHeaderEvent.get(), "Already dispatched an event?"); mProcessLinkHeaderEvent = NewNonOwningRunnableMethod("nsContentSink::DoProcessLinkHeader", this, &nsContentSink::DoProcessLinkHeader); rv = NS_DispatchToCurrentThread(mProcessLinkHeaderEvent.get()); if (NS_FAILED(rv)) { mProcessLinkHeaderEvent.Forget(); } } return NS_OK; } void nsContentSink::DoProcessLinkHeader() { + for (const auto& earlyHint : mDocument->GetEarlyHints()) { + ProcessLinkFromHeader(earlyHint.link(), earlyHint.earlyHintPreloaderId()); + } + nsAutoString value; mDocument->GetHeaderData(nsGkAtoms::link, value); auto linkHeaders = net::ParseLinkHeader(value); for (const auto& linkHeader : linkHeaders) { - ProcessLinkFromHeader(linkHeader); + ProcessLinkFromHeader(linkHeader, 0); } } // check whether the Link header field applies to the context resource // see <http://tools.ietf.org/html/rfc5988#section-5.2> bool nsContentSink::LinkContextIsOurDocument(const nsAString& aAnchor) { if (aAnchor.IsEmpty()) { @@ -292,17 +309,18 @@ bool nsContentSink::LinkContextIsOurDocu if (NS_FAILED(rv)) { // comparison failed return false; } return same; } -nsresult nsContentSink::ProcessLinkFromHeader(const net::LinkHeader& aHeader) { +nsresult nsContentSink::ProcessLinkFromHeader(const net::LinkHeader& aHeader, + uint64_t aEarlyHintPreloaderId) { uint32_t linkTypes = LinkStyle::ParseLinkTypes(aHeader.mRel); // The link relation may apply to a different resource, specified // in the anchor parameter. For the link relations supported so far, // we simply abort if the link applies to a resource different to the // one we've loaded if (!LinkContextIsOurDocument(aHeader.mAnchor)) { return NS_OK; @@ -320,17 +338,18 @@ nsresult nsContentSink::ProcessLinkFromH if (!aHeader.mHref.IsEmpty() && (linkTypes & LinkStyle::ePRECONNECT)) { Preconnect(aHeader.mHref, aHeader.mCrossOrigin); } if (linkTypes & LinkStyle::ePRELOAD) { PreloadHref(aHeader.mHref, aHeader.mAs, aHeader.mType, aHeader.mMedia, aHeader.mIntegrity, aHeader.mSrcset, aHeader.mSizes, - aHeader.mCrossOrigin, aHeader.mReferrerPolicy); + aHeader.mCrossOrigin, aHeader.mReferrerPolicy, + aEarlyHintPreloaderId); } if ((linkTypes & LinkStyle::eMODULE_PRELOAD) && mDocument->ScriptLoader()->GetModuleLoader()) { // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-modulepreload-module-script-graph // Step 1. Disallow further import maps given settings object. mDocument->ScriptLoader()->GetModuleLoader()->DisallowImportMaps(); } @@ -430,17 +449,18 @@ void nsContentSink::PrefetchHref(const n } } void nsContentSink::PreloadHref(const nsAString& aHref, const nsAString& aAs, const nsAString& aType, const nsAString& aMedia, const nsAString& aIntegrity, const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aCORS, - const nsAString& aReferrerPolicy) { + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId) { auto encoding = mDocument->GetDocumentCharacterSet(); nsCOMPtr<nsIURI> uri; NS_NewURI(getter_AddRefs(uri), aHref, encoding, mDocument->GetDocBaseURI()); if (!uri) { // URL parsing failed. return; } @@ -454,19 +474,19 @@ void nsContentSink::PreloadHref(const ns auto policyType = mozilla::net::AsValueToContentPolicy(asAttr); if (policyType == nsIContentPolicy::TYPE_INVALID || !mozilla::net::CheckPreloadAttrs(asAttr, mimeType, aMedia, mDocument)) { // Ignore preload wrong or empty attributes. mozilla::net::WarnIgnoredPreload(*mDocument, *uri); return; } - mDocument->Preloads().PreloadLinkHeader(uri, aHref, policyType, aAs, aType, - aIntegrity, aSrcset, aSizes, aCORS, - aReferrerPolicy); + mDocument->Preloads().PreloadLinkHeader( + uri, aHref, policyType, aAs, aType, aIntegrity, aSrcset, aSizes, aCORS, + aReferrerPolicy, aEarlyHintPreloaderId); } void nsContentSink::PrefetchDNS(const nsAString& aHref) { nsAutoString hostname; bool isHttps = false; if (StringBeginsWith(aHref, u"//"_ns)) { hostname = Substring(aHref, 2);
--- a/dom/base/nsContentSink.h +++ b/dom/base/nsContentSink.h @@ -120,30 +120,33 @@ class nsContentSink : public nsICSSLoade protected: nsContentSink(); virtual ~nsContentSink(); nsresult Init(Document* aDoc, nsIURI* aURI, nsISupports* aContainer, nsIChannel* aChannel); nsresult ProcessHTTPHeaders(nsIChannel* aChannel); - nsresult ProcessLinkFromHeader(const mozilla::net::LinkHeader& aHeader); + // aEarlyHintPreloaderId zero means no early hint channel to connect back + nsresult ProcessLinkFromHeader(const mozilla::net::LinkHeader& aHeader, + uint64_t aEarlyHintPreloaderId); virtual nsresult ProcessStyleLinkFromHeader( const nsAString& aHref, bool aAlternate, const nsAString& aTitle, const nsAString& aIntegrity, const nsAString& aType, const nsAString& aMedia, const nsAString& aReferrerPolicy); void PrefetchHref(const nsAString& aHref, const nsAString& aAs, const nsAString& aType, const nsAString& aMedia); void PreloadHref(const nsAString& aHref, const nsAString& aAs, const nsAString& aType, const nsAString& aMedia, const nsAString& aIntegrity, const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aCORS, - const nsAString& aReferrerPolicy); + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId); // For PrefetchDNS() aHref can either be the usual // URI format or of the form "//www.hostname.com" without a scheme. void PrefetchDNS(const nsAString& aHref); // Gets the cache key (used to identify items in a cache) of the channel. nsresult GetChannelCacheKey(nsIChannel* aChannel, nsACString& aCacheKey);
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -3545,16 +3545,20 @@ mozilla::ipc::IPCResult ContentChild::Re nsCOMPtr<nsIChannel> newChannel; MOZ_ASSERT((aArgs.loadStateInternalLoadFlags() & nsDocShell::InternalLoad::INTERNAL_LOAD_FLAGS_IS_SRCDOC) || aArgs.srcdocData().IsVoid()); rv = nsDocShell::CreateRealChannelForDocument( getter_AddRefs(newChannel), aArgs.uri(), loadInfo, nullptr, aArgs.newLoadFlags(), aArgs.srcdocData(), aArgs.baseUri()); + if (RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(newChannel)) { + httpChannel->SetEarlyHints(std::move(aArgs.earlyHints())); + } + // This is used to report any errors back to the parent by calling // CrossProcessRedirectFinished. RefPtr<HttpChannelChild> httpChild = do_QueryObject(newChannel); auto resolve = [=](const nsresult& aRv) { nsresult rv = aRv; if (httpChild) { rv = httpChild->CrossProcessRedirectFinished(rv); }
--- a/netwerk/ipc/DocumentChannelChild.cpp +++ b/netwerk/ipc/DocumentChannelChild.cpp @@ -262,16 +262,20 @@ IPCResult DocumentChannelChild::RecvRedi aArgs.srcdocData().IsVoid()); nsresult rv = nsDocShell::CreateRealChannelForDocument( getter_AddRefs(newChannel), aArgs.uri(), loadInfo, nullptr, aArgs.newLoadFlags(), aArgs.srcdocData(), aArgs.baseUri()); if (newChannel) { newChannel->SetLoadGroup(mLoadGroup); } + if (RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(newChannel)) { + httpChannel->SetEarlyHints(std::move(aArgs.earlyHints())); + } + // This is used to report any errors back to the parent by calling // CrossProcessRedirectFinished. auto scopeExit = MakeScopeExit([&]() { mRedirectResolver(rv); mRedirectResolver = nullptr; }); if (NS_FAILED(rv)) {
--- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -5940,14 +5940,23 @@ bool HttpBaseChannel::Http3Allowed() con void HttpBaseChannel::SetDummyChannelForImageCache() { mDummyChannelForImageCache = true; MOZ_ASSERT(!mResponseHead, "SetDummyChannelForImageCache should only be called once"); mResponseHead = MakeUnique<nsHttpResponseHead>(); } +void HttpBaseChannel::SetEarlyHints( + nsTArray<EarlyHintConnectArgs>&& aEarlyHints) { + mEarlyHints = std::move(aEarlyHints); +} + +nsTArray<EarlyHintConnectArgs>&& HttpBaseChannel::TakeEarlyHints() { + return std::move(mEarlyHints); +} + void HttpBaseChannel::SetConnectionInfo(nsHttpConnectionInfo* aCI) { mConnectionInfo = aCI ? aCI->Clone() : nullptr; } } // namespace net } // namespace mozilla
--- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -9,16 +9,17 @@ #define mozilla_net_HttpBaseChannel_h #include <utility> #include "mozilla/AtomicBitfields.h" #include "mozilla/Atomics.h" #include "mozilla/dom/DOMTypes.h" #include "mozilla/net/DNS.h" +#include "mozilla/net/NeckoChannelParams.h" #include "mozilla/net/NeckoCommon.h" #include "mozilla/net/PrivateBrowsingChannel.h" #include "nsCOMPtr.h" #include "nsHashPropertyBag.h" #include "nsHttp.h" #include "nsHttpHandler.h" #include "nsHttpRequestHead.h" #include "nsIClassOfService.h" @@ -780,16 +781,28 @@ class HttpBaseChannel : public nsHashPro UniquePtr<ProfileChunkedBuffer> mSource; uint32_t mLoadFlags; uint32_t mCaps; ClassOfService mClassOfService; + public: + void SetEarlyHints( + nsTArray<mozilla::net::EarlyHintConnectArgs>&& aEarlyHints); + nsTArray<mozilla::net::EarlyHintConnectArgs>&& TakeEarlyHints(); + + protected: + // Storing Http 103 Early Hint preloads. The parent process is responsible to + // start the early hint preloads, but the http child needs to be able to look + // them up. They are sent via IPC and stored in this variable. This is set on + // main document channel + nsTArray<EarlyHintConnectArgs> mEarlyHints; + // clang-format off MOZ_ATOMIC_BITFIELDS(mAtomicBitfields1, 32, ( (uint32_t, UpgradeToSecure, 1), (uint32_t, ApplyConversion, 1), // Set to true if DoApplyContentConversions has been applied to // our default mListener. (uint32_t, HasAppliedConversion, 1), (uint32_t, IsPending, 1),
--- a/netwerk/protocol/http/nsIHttpChannelInternal.idl +++ b/netwerk/protocol/http/nsIHttpChannelInternal.idl @@ -10,16 +10,17 @@ #include "nsStringFwd.h" #include "nsTArrayForwardDeclare.h" template<class T> class nsCOMArray; namespace mozilla { class TimeStamp; namespace net { class nsHttpConnectionInfo; class WebSocketConnectionBase; +class EarlyHintConnectArgs; } namespace dom { enum class RequestMode : uint8_t; } } %} [ptr] native nsHttpConnectionInfo(mozilla::net::nsHttpConnectionInfo); [ptr] native StringArray(nsTArray<nsCString>);
--- a/parser/html/nsHtml5TreeOpExecutor.cpp +++ b/parser/html/nsHtml5TreeOpExecutor.cpp @@ -1280,29 +1280,29 @@ void nsHtml5TreeOpExecutor::PreloadFont( const nsAString& aCrossOrigin, const nsAString& aMedia, const nsAString& aReferrerPolicy) { nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia); if (!uri) { return; } - mDocument->Preloads().PreloadFont(uri, aCrossOrigin, aReferrerPolicy); + mDocument->Preloads().PreloadFont(uri, aCrossOrigin, aReferrerPolicy, 0); } void nsHtml5TreeOpExecutor::PreloadFetch(const nsAString& aURL, const nsAString& aCrossOrigin, const nsAString& aMedia, const nsAString& aReferrerPolicy) { nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYetAndMediaApplies(aURL, aMedia); if (!uri) { return; } - mDocument->Preloads().PreloadFetch(uri, aCrossOrigin, aReferrerPolicy); + mDocument->Preloads().PreloadFetch(uri, aCrossOrigin, aReferrerPolicy, 0); } void nsHtml5TreeOpExecutor::PreloadOpenPicture() { mDocument->PreloadPictureOpened(); } void nsHtml5TreeOpExecutor::PreloadEndPicture() { mDocument->PreloadPictureClosed();
--- a/uriloader/preload/PreloadService.cpp +++ b/uriloader/preload/PreloadService.cpp @@ -82,52 +82,53 @@ already_AddRefed<PreloaderBase> PreloadS aLinkElement->GetHref(url); aLinkElement->GetCrossOrigin(crossOrigin); aLinkElement->GetIntegrity(integrity); aLinkElement->GetReferrerPolicy(referrerPolicy); aLinkElement->GetType(type); auto result = PreloadOrCoalesce(uri, url, aPolicyType, as, type, charset, srcset, sizes, integrity, crossOrigin, - referrerPolicy, /* aFromHeader = */ false); + referrerPolicy, /* aFromHeader = */ false, 0); if (!result.mPreloader) { NotifyNodeEvent(aLinkElement, result.mAlreadyComplete); return nullptr; } result.mPreloader->AddLinkPreloadNode(aLinkElement); return result.mPreloader.forget(); } void PreloadService::PreloadLinkHeader( nsIURI* aURI, const nsAString& aURL, nsContentPolicyType aPolicyType, const nsAString& aAs, const nsAString& aType, const nsAString& aIntegrity, const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aCORS, - const nsAString& aReferrerPolicy) { + const nsAString& aReferrerPolicy, uint64_t aEarlyHintPreloaderId) { if (aPolicyType == nsIContentPolicy::TYPE_INVALID) { MOZ_ASSERT_UNREACHABLE("Caller should check"); return; } if (!StaticPrefs::network_preload()) { return; } PreloadOrCoalesce(aURI, aURL, aPolicyType, aAs, aType, u""_ns, aSrcset, aSizes, aIntegrity, aCORS, aReferrerPolicy, - /* aFromHeader = */ true); + /* aFromHeader = */ true, aEarlyHintPreloaderId); } PreloadService::PreloadOrCoalesceResult PreloadService::PreloadOrCoalesce( nsIURI* aURI, const nsAString& aURL, nsContentPolicyType aPolicyType, const nsAString& aAs, const nsAString& aType, const nsAString& aCharset, const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aIntegrity, const nsAString& aCORS, - const nsAString& aReferrerPolicy, bool aFromHeader) { + const nsAString& aReferrerPolicy, bool aFromHeader, + uint64_t aEarlyHintPreloaderId) { if (!aURI) { MOZ_ASSERT_UNREACHABLE("Should not pass null nsIURI"); return {nullptr, false}; } bool isImgSet = false; PreloadHashKey preloadKey; nsCOMPtr<nsIURI> uri = aURI; @@ -158,75 +159,79 @@ PreloadService::PreloadOrCoalesceResult } if (RefPtr<PreloaderBase> preload = LookupPreload(preloadKey)) { return {std::move(preload), false}; } if (aAs.LowerCaseEqualsASCII("script")) { PreloadScript(uri, aType, aCharset, aCORS, aReferrerPolicy, aIntegrity, - true /* isInHead - TODO */); + true /* isInHead - TODO */, aEarlyHintPreloaderId); } else if (aAs.LowerCaseEqualsASCII("style")) { auto status = mDocument->PreloadStyle( aURI, Encoding::ForLabel(aCharset), aCORS, PreloadReferrerPolicy(aReferrerPolicy), aIntegrity, aFromHeader ? css::StylePreloadKind::FromLinkRelPreloadHeader : css::StylePreloadKind::FromLinkRelPreloadElement); switch (status) { case dom::SheetPreloadStatus::AlreadyComplete: return {nullptr, /* already_complete = */ true}; case dom::SheetPreloadStatus::Errored: case dom::SheetPreloadStatus::InProgress: break; } } else if (aAs.LowerCaseEqualsASCII("image")) { - PreloadImage(uri, aCORS, aReferrerPolicy, isImgSet); + PreloadImage(uri, aCORS, aReferrerPolicy, isImgSet, aEarlyHintPreloaderId); } else if (aAs.LowerCaseEqualsASCII("font")) { - PreloadFont(uri, aCORS, aReferrerPolicy); + PreloadFont(uri, aCORS, aReferrerPolicy, aEarlyHintPreloaderId); } else if (aAs.LowerCaseEqualsASCII("fetch")) { - PreloadFetch(uri, aCORS, aReferrerPolicy); + PreloadFetch(uri, aCORS, aReferrerPolicy, aEarlyHintPreloaderId); } return {LookupPreload(preloadKey), false}; } void PreloadService::PreloadScript(nsIURI* aURI, const nsAString& aType, const nsAString& aCharset, const nsAString& aCrossOrigin, const nsAString& aReferrerPolicy, const nsAString& aIntegrity, - bool aScriptFromHead) { + bool aScriptFromHead, + uint64_t aEarlyHintPreloaderId) { mDocument->ScriptLoader()->PreloadURI( aURI, aCharset, aType, aCrossOrigin, aIntegrity, aScriptFromHead, false, false, false, true, PreloadReferrerPolicy(aReferrerPolicy)); } void PreloadService::PreloadImage(nsIURI* aURI, const nsAString& aCrossOrigin, const nsAString& aImageReferrerPolicy, - bool aIsImgSet) { + bool aIsImgSet, + uint64_t aEarlyHintPreloaderId) { mDocument->PreLoadImage(aURI, aCrossOrigin, PreloadReferrerPolicy(aImageReferrerPolicy), aIsImgSet, true); } void PreloadService::PreloadFont(nsIURI* aURI, const nsAString& aCrossOrigin, - const nsAString& aReferrerPolicy) { + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId) { CORSMode cors = dom::Element::StringToCORSMode(aCrossOrigin); auto key = PreloadHashKey::CreateAsFont(aURI, cors); // * Bug 1618549: Depending on where we decide to do the deduplication, we may // want to check if the font is already being preloaded here. RefPtr<FontPreloader> preloader = new FontPreloader(); dom::ReferrerPolicy referrerPolicy = PreloadReferrerPolicy(aReferrerPolicy); preloader->OpenChannel(key, aURI, cors, referrerPolicy, mDocument); } void PreloadService::PreloadFetch(nsIURI* aURI, const nsAString& aCrossOrigin, - const nsAString& aReferrerPolicy) { + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId) { CORSMode cors = dom::Element::StringToCORSMode(aCrossOrigin); auto key = PreloadHashKey::CreateAsFetch(aURI, cors); // * Bug 1618549: Depending on where we decide to do the deduplication, we may // want to check if a fetch is already being preloaded here. RefPtr<FetchPreloader> preloader = new FetchPreloader(); dom::ReferrerPolicy referrerPolicy = PreloadReferrerPolicy(aReferrerPolicy);
--- a/uriloader/preload/PreloadService.h +++ b/uriloader/preload/PreloadService.h @@ -61,36 +61,45 @@ class PreloadService { const PreloadHashKey& aKey) const; void SetSpeculationBase(nsIURI* aURI) { mSpeculationBaseURI = aURI; } already_AddRefed<nsIURI> GetPreloadURI(const nsAString& aURL); already_AddRefed<PreloaderBase> PreloadLinkElement( dom::HTMLLinkElement* aLink, nsContentPolicyType aPolicyType); + // a non-zero aEarlyHintPreloaderId tells this service that a preload for this + // link was started by the EarlyHintPreloader and the preloaders should + // connect back by setting earlyHintPreloaderId in nsIChannelInternal before + // AsyncOpen. void PreloadLinkHeader(nsIURI* aURI, const nsAString& aURL, nsContentPolicyType aPolicyType, const nsAString& aAs, const nsAString& aType, const nsAString& aIntegrity, const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aCORS, - const nsAString& aReferrerPolicy); + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId); void PreloadScript(nsIURI* aURI, const nsAString& aType, const nsAString& aCharset, const nsAString& aCrossOrigin, const nsAString& aReferrerPolicy, - const nsAString& aIntegrity, bool aScriptFromHead); + const nsAString& aIntegrity, bool aScriptFromHead, + uint64_t aEarlyHintPreloaderId); void PreloadImage(nsIURI* aURI, const nsAString& aCrossOrigin, - const nsAString& aImageReferrerPolicy, bool aIsImgSet); + const nsAString& aImageReferrerPolicy, bool aIsImgSet, + uint64_t aEarlyHintPreloaderId); void PreloadFont(nsIURI* aURI, const nsAString& aCrossOrigin, - const nsAString& aReferrerPolicy); + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId); void PreloadFetch(nsIURI* aURI, const nsAString& aCrossOrigin, - const nsAString& aReferrerPolicy); + const nsAString& aReferrerPolicy, + uint64_t aEarlyHintPreloaderId); static void NotifyNodeEvent(nsINode* aNode, bool aSuccess); private: dom::ReferrerPolicy PreloadReferrerPolicy(const nsAString& aReferrerPolicy); nsIURI* BaseURIForPreload(); struct PreloadOrCoalesceResult { @@ -98,17 +107,18 @@ class PreloadService { bool mAlreadyComplete; }; PreloadOrCoalesceResult PreloadOrCoalesce( nsIURI* aURI, const nsAString& aURL, nsContentPolicyType aPolicyType, const nsAString& aAs, const nsAString& aType, const nsAString& aCharset, const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aIntegrity, const nsAString& aCORS, - const nsAString& aReferrerPolicy, bool aFromHeader); + const nsAString& aReferrerPolicy, bool aFromHeader, + uint64_t aEarlyHintPreloaderId); private: nsRefPtrHashtable<PreloadHashKey, PreloaderBase> mPreloads; // Raw pointer only, we are intended to be a direct member of dom::Document dom::Document* mDocument; // Set by `nsHtml5TreeOpExecutor::SetSpeculationBase`.