mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1594449 - <link rel="preload"> implemented as a speculative load initiated during the prescan phase in the HTML5 parser, disabled by default, only supports "script" and "styles" types, r=ckerschb
Differential Revision: https://phabricator.services.mozilla.com/D52019 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
10f4461247
commit
ce072f8e6a
@ -11310,18 +11310,20 @@ NS_IMPL_ISUPPORTS(StubCSSLoaderObserver, nsICSSLoaderObserver)
|
||||
void Document::PreloadStyle(nsIURI* uri, const Encoding* aEncoding,
|
||||
const nsAString& aCrossOriginAttr,
|
||||
const enum ReferrerPolicy aReferrerPolicy,
|
||||
const nsAString& aIntegrity) {
|
||||
const nsAString& aIntegrity, bool aIsLinkPreload) {
|
||||
// The CSSLoader will retain this object after we return.
|
||||
nsCOMPtr<nsICSSLoaderObserver> obs = new StubCSSLoaderObserver();
|
||||
|
||||
nsCOMPtr<nsIReferrerInfo> referrerInfo =
|
||||
ReferrerInfo::CreateFromDocumentAndPolicyOverride(this, aReferrerPolicy);
|
||||
|
||||
auto preloadType = aIsLinkPreload ? css::Loader::IsPreload::FromLink
|
||||
: css::Loader::IsPreload::FromParser;
|
||||
|
||||
// Charset names are always ASCII.
|
||||
Unused << CSSLoader()->LoadSheet(
|
||||
uri, css::Loader::IsPreload::Yes, NodePrincipal(), aEncoding,
|
||||
referrerInfo, obs, Element::StringToCORSMode(aCrossOriginAttr),
|
||||
aIntegrity);
|
||||
uri, preloadType, NodePrincipal(), aEncoding, referrerInfo, obs,
|
||||
Element::StringToCORSMode(aCrossOriginAttr), aIntegrity);
|
||||
}
|
||||
|
||||
RefPtr<StyleSheet> Document::LoadChromeSheetSync(nsIURI* uri) {
|
||||
|
@ -3213,7 +3213,7 @@ class Document : public nsINode,
|
||||
void PreloadStyle(nsIURI* aURI, const Encoding* aEncoding,
|
||||
const nsAString& aCrossOriginAttr,
|
||||
ReferrerPolicyEnum aReferrerPolicy,
|
||||
const nsAString& aIntegrity);
|
||||
const nsAString& aIntegrity, bool aIsLinkPreload);
|
||||
|
||||
/**
|
||||
* Called by the chrome registry to load style sheets.
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/EventStates.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPrefs_network.h"
|
||||
#include "mozilla/dom/BindContext.h"
|
||||
#include "mozilla/dom/DocumentInlines.h"
|
||||
#include "mozilla/dom/HTMLLinkElementBinding.h"
|
||||
@ -402,7 +403,8 @@ static const DOMTokenListSupportedToken sSupportedRelValues[] = {
|
||||
|
||||
nsDOMTokenList* HTMLLinkElement::RelList() {
|
||||
if (!mRelList) {
|
||||
if (Preferences::GetBool("network.preload")) {
|
||||
if (Preferences::GetBool("network.preload") ||
|
||||
StaticPrefs::network_preload_experimental()) {
|
||||
mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues);
|
||||
} else {
|
||||
mRelList =
|
||||
|
@ -156,8 +156,11 @@ inline ModuleLoadRequest* ScriptLoadRequest::AsModuleRequest() {
|
||||
return static_cast<ModuleLoadRequest*>(this);
|
||||
}
|
||||
|
||||
void ScriptLoadRequest::SetScriptMode(bool aDeferAttr, bool aAsyncAttr) {
|
||||
if (aAsyncAttr) {
|
||||
void ScriptLoadRequest::SetScriptMode(bool aDeferAttr, bool aAsyncAttr,
|
||||
bool aLinkPreload) {
|
||||
if (aLinkPreload) {
|
||||
mScriptMode = ScriptMode::eLinkPreload;
|
||||
} else if (aAsyncAttr) {
|
||||
mScriptMode = ScriptMode::eAsync;
|
||||
} else if (aDeferAttr || IsModuleRequest()) {
|
||||
mScriptMode = ScriptMode::eDeferred;
|
||||
|
@ -210,9 +210,19 @@ class ScriptLoadRequest
|
||||
: ScriptText<Utf8Unit>().clearAndFree();
|
||||
}
|
||||
|
||||
enum class ScriptMode : uint8_t { eBlocking, eDeferred, eAsync };
|
||||
enum class ScriptMode : uint8_t {
|
||||
eBlocking,
|
||||
eDeferred,
|
||||
eAsync,
|
||||
eLinkPreload // this is a load initiated by <link rel="preload"
|
||||
// as="script"> tag
|
||||
};
|
||||
|
||||
void SetScriptMode(bool aDeferAttr, bool aAsyncAttr);
|
||||
void SetScriptMode(bool aDeferAttr, bool aAsyncAttr, bool aLinkPreload);
|
||||
|
||||
bool IsLinkPreloadScript() const {
|
||||
return mScriptMode == ScriptMode::eLinkPreload;
|
||||
}
|
||||
|
||||
bool IsBlockingScript() const { return mScriptMode == ScriptMode::eBlocking; }
|
||||
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsICacheInfoChannel.h"
|
||||
#include "nsITimedChannel.h"
|
||||
#include "nsIScriptElement.h"
|
||||
#include "nsISupportsPriority.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
@ -1369,7 +1370,18 @@ nsresult ScriptLoader::StartLoad(ScriptLoadRequest* aRequest) {
|
||||
|
||||
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
||||
if (cos) {
|
||||
if (aRequest->mScriptFromHead && aRequest->IsBlockingScript()) {
|
||||
if (aRequest->IsLinkPreloadScript()) {
|
||||
// This is <link rel="preload" as="script"> initiated speculative load,
|
||||
// put it to the group that is not blocked by leaders and doesn't block
|
||||
// follower at the same time. Giving it a much higher priority will make
|
||||
// this request be processed ahead of other Unblocked requests, but with
|
||||
// the same weight as Leaders. This will make us behave similar way for
|
||||
// both http2 and http1.
|
||||
cos->AddClassFlags(nsIClassOfService::Unblocked);
|
||||
if (nsCOMPtr<nsISupportsPriority> sp = do_QueryInterface(channel)) {
|
||||
sp->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST);
|
||||
}
|
||||
} else if (aRequest->mScriptFromHead && aRequest->IsBlockingScript()) {
|
||||
// synchronous head scripts block loading of most other non js/css
|
||||
// content such as images, Leader implicitely disallows tailing
|
||||
cos->AddClassFlags(nsIClassOfService::Leader);
|
||||
@ -1619,7 +1631,7 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
|
||||
// It's possible these attributes changed since we started the preload so
|
||||
// update them here.
|
||||
request->SetScriptMode(aElement->GetScriptDeferred(),
|
||||
aElement->GetScriptAsync());
|
||||
aElement->GetScriptAsync(), false);
|
||||
|
||||
AccumulateCategorical(LABELS_DOM_SCRIPT_PRELOAD_RESULT::Used);
|
||||
} else {
|
||||
@ -1646,7 +1658,7 @@ bool ScriptLoader::ProcessExternalScript(nsIScriptElement* aElement,
|
||||
ourCORSMode, sriMetadata, referrerPolicy);
|
||||
request->mIsInline = false;
|
||||
request->SetScriptMode(aElement->GetScriptDeferred(),
|
||||
aElement->GetScriptAsync());
|
||||
aElement->GetScriptAsync(), false);
|
||||
// keep request->mScriptFromHead to false so we don't treat non preloaded
|
||||
// scripts as blockers for full page load. See bug 792438.
|
||||
|
||||
@ -1795,7 +1807,7 @@ bool ScriptLoader::ProcessInlineScript(nsIScriptElement* aElement,
|
||||
// inline classic scripts ignore both these attributes.
|
||||
MOZ_ASSERT(!aElement->GetScriptDeferred());
|
||||
MOZ_ASSERT_IF(!request->IsModuleRequest(), !aElement->GetScriptAsync());
|
||||
request->SetScriptMode(false, aElement->GetScriptAsync());
|
||||
request->SetScriptMode(false, aElement->GetScriptAsync(), false);
|
||||
|
||||
LOG(("ScriptLoadRequest (%p): Created request for inline script",
|
||||
request.get()));
|
||||
@ -3724,6 +3736,7 @@ void ScriptLoader::PreloadURI(nsIURI* aURI, const nsAString& aCharset,
|
||||
const nsAString& aCrossOrigin,
|
||||
const nsAString& aIntegrity, bool aScriptFromHead,
|
||||
bool aAsync, bool aDefer, bool aNoModule,
|
||||
bool aLinkPreload,
|
||||
const ReferrerPolicy aReferrerPolicy) {
|
||||
NS_ENSURE_TRUE_VOID(mDocument);
|
||||
// Check to see if scripts has been turned off.
|
||||
@ -3762,7 +3775,7 @@ void ScriptLoader::PreloadURI(nsIURI* aURI, const nsAString& aCharset,
|
||||
Element::StringToCORSMode(aCrossOrigin), sriMetadata, aReferrerPolicy);
|
||||
request->mIsInline = false;
|
||||
request->mScriptFromHead = aScriptFromHead;
|
||||
request->SetScriptMode(aDefer, aAsync);
|
||||
request->SetScriptMode(aDefer, aAsync, aLinkPreload);
|
||||
request->SetIsPreloadRequest();
|
||||
|
||||
if (LOG_ENABLED()) {
|
||||
|
@ -322,6 +322,7 @@ class ScriptLoader final : public nsISupports {
|
||||
const nsAString& aType, const nsAString& aCrossOrigin,
|
||||
const nsAString& aIntegrity, bool aScriptFromHead,
|
||||
bool aAsync, bool aDefer, bool aNoModule,
|
||||
bool aLinkPreload,
|
||||
const ReferrerPolicy aReferrerPolicy);
|
||||
|
||||
/**
|
||||
|
@ -1058,9 +1058,9 @@ nsresult Loader::CheckContentPolicy(nsIPrincipal* aLoadingPrincipal,
|
||||
}
|
||||
|
||||
nsContentPolicyType contentPolicyType =
|
||||
aIsPreload == IsPreload::Yes
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
|
||||
aIsPreload == IsPreload::No
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD;
|
||||
|
||||
nsCOMPtr<nsILoadInfo> secCheckLoadInfo = new net::LoadInfo(
|
||||
aLoadingPrincipal, aTriggeringPrincipal, aRequestingNode,
|
||||
@ -1341,9 +1341,9 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
|
||||
nsILoadInfo::SEC_ALLOW_CHROME;
|
||||
|
||||
nsContentPolicyType contentPolicyType =
|
||||
aIsPreload == IsPreload::Yes
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
|
||||
aIsPreload == IsPreload::No
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD;
|
||||
|
||||
// Just load it
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
@ -1482,9 +1482,9 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
|
||||
securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
|
||||
|
||||
nsContentPolicyType contentPolicyType =
|
||||
aIsPreload == IsPreload::Yes
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET;
|
||||
aIsPreload == IsPreload::No
|
||||
? nsIContentPolicy::TYPE_INTERNAL_STYLESHEET
|
||||
: nsIContentPolicy::TYPE_INTERNAL_STYLESHEET_PRELOAD;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
// Note we are calling NS_NewChannelWithTriggeringPrincipal here with a node
|
||||
@ -1528,6 +1528,11 @@ nsresult Loader::LoadSheet(SheetLoadData& aLoadData, SheetState aSheetState,
|
||||
if (nsCOMPtr<nsIClassOfService> cos = do_QueryInterface(channel)) {
|
||||
cos->AddClassFlags(nsIClassOfService::Leader);
|
||||
}
|
||||
if (aIsPreload == IsPreload::FromLink) {
|
||||
if (nsCOMPtr<nsISupportsPriority> sp = do_QueryInterface(channel)) {
|
||||
sp->AdjustPriority(nsISupportsPriority::PRIORITY_HIGHEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel)) {
|
||||
|
@ -205,7 +205,12 @@ class Loader final {
|
||||
nsIURI*, SheetParsingMode = eAuthorSheetFeatures,
|
||||
UseSystemPrincipal = UseSystemPrincipal::No);
|
||||
|
||||
enum class IsPreload { No, Yes };
|
||||
/**
|
||||
* Yes: this is a speculative load initiated by a <script> tag
|
||||
* Link: this is a speculative load as well, but initiated by <link
|
||||
* rel="preload" as="style"> tag
|
||||
*/
|
||||
enum class IsPreload { No, FromParser, FromLink };
|
||||
|
||||
/**
|
||||
* Asynchronously load the stylesheet at aURL. If a successful result is
|
||||
|
@ -6827,6 +6827,13 @@
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Whether to use the new experimental preload code based on the speculative loader
|
||||
# inside the html5 parser.
|
||||
- name: network.preload-experimental
|
||||
type: RelaxedAtomicBool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Telemetry of traffic categories. Whether or not to enable HttpTrafficAnalyzer.
|
||||
- name: network.traffic_analyzer.enabled
|
||||
type: RelaxedAtomicBool
|
||||
|
@ -12,6 +12,7 @@ nsHtml5SpeculativeLoad::nsHtml5SpeculativeLoad()
|
||||
: mOpCode(eSpeculativeLoadUninitialized),
|
||||
mIsAsync(false),
|
||||
mIsDefer(false),
|
||||
mIsLinkPreload(false),
|
||||
mEncoding(nullptr) {
|
||||
MOZ_COUNT_CTOR(nsHtml5SpeculativeLoad);
|
||||
new (&mCharsetOrSrcset) nsString;
|
||||
@ -61,34 +62,39 @@ void nsHtml5SpeculativeLoad::Perform(nsHtml5TreeOpExecutor* aExecutor) {
|
||||
mUrlOrSizes, mCharsetOrSrcset,
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
|
||||
mCrossOriginOrMedia, mReferrerPolicyOrIntegrity,
|
||||
mScriptReferrerPolicy, false, mIsAsync, mIsDefer, false);
|
||||
mScriptReferrerPolicy, false, mIsAsync, mIsDefer, false,
|
||||
mIsLinkPreload);
|
||||
break;
|
||||
case eSpeculativeLoadScriptFromHead:
|
||||
aExecutor->PreloadScript(
|
||||
mUrlOrSizes, mCharsetOrSrcset,
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
|
||||
mCrossOriginOrMedia, mReferrerPolicyOrIntegrity,
|
||||
mScriptReferrerPolicy, true, mIsAsync, mIsDefer, false);
|
||||
mScriptReferrerPolicy, true, mIsAsync, mIsDefer, false,
|
||||
mIsLinkPreload);
|
||||
break;
|
||||
case eSpeculativeLoadNoModuleScript:
|
||||
aExecutor->PreloadScript(
|
||||
mUrlOrSizes, mCharsetOrSrcset,
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
|
||||
mCrossOriginOrMedia, mReferrerPolicyOrIntegrity,
|
||||
mScriptReferrerPolicy, false, mIsAsync, mIsDefer, true);
|
||||
mScriptReferrerPolicy, false, mIsAsync, mIsDefer, true,
|
||||
mIsLinkPreload);
|
||||
break;
|
||||
case eSpeculativeLoadNoModuleScriptFromHead:
|
||||
aExecutor->PreloadScript(
|
||||
mUrlOrSizes, mCharsetOrSrcset,
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
|
||||
mCrossOriginOrMedia, mReferrerPolicyOrIntegrity,
|
||||
mScriptReferrerPolicy, true, mIsAsync, mIsDefer, true);
|
||||
mScriptReferrerPolicy, true, mIsAsync, mIsDefer, true,
|
||||
mIsLinkPreload);
|
||||
break;
|
||||
case eSpeculativeLoadStyle:
|
||||
aExecutor->PreloadStyle(
|
||||
mUrlOrSizes, mCharsetOrSrcset, mCrossOriginOrMedia,
|
||||
mReferrerPolicyOrIntegrity,
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity,
|
||||
mIsLinkPreload);
|
||||
break;
|
||||
case eSpeculativeLoadManifest:
|
||||
aExecutor->ProcessOfflineManifest(mUrlOrSizes);
|
||||
|
@ -125,7 +125,8 @@ class nsHtml5SpeculativeLoad {
|
||||
nsHtml5String aType, nsHtml5String aCrossOrigin,
|
||||
nsHtml5String aIntegrity,
|
||||
nsHtml5String aReferrerPolicy, bool aParserInHead,
|
||||
bool aAsync, bool aDefer, bool aNoModule) {
|
||||
bool aAsync, bool aDefer, bool aNoModule,
|
||||
bool aLinkPreload) {
|
||||
MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
|
||||
"Trying to reinitialize a speculative load!");
|
||||
if (aNoModule) {
|
||||
@ -152,6 +153,7 @@ class nsHtml5SpeculativeLoad {
|
||||
|
||||
mIsAsync = aAsync;
|
||||
mIsDefer = aDefer;
|
||||
mIsLinkPreload = aLinkPreload;
|
||||
}
|
||||
|
||||
inline void InitImportStyle(nsString&& aUrl) {
|
||||
@ -168,8 +170,8 @@ class nsHtml5SpeculativeLoad {
|
||||
|
||||
inline void InitStyle(nsHtml5String aUrl, nsHtml5String aCharset,
|
||||
nsHtml5String aCrossOrigin,
|
||||
nsHtml5String aReferrerPolicy,
|
||||
nsHtml5String aIntegrity) {
|
||||
nsHtml5String aReferrerPolicy, nsHtml5String aIntegrity,
|
||||
bool aLinkPreload) {
|
||||
MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
|
||||
"Trying to reinitialize a speculative load!");
|
||||
mOpCode = eSpeculativeLoadStyle;
|
||||
@ -184,6 +186,7 @@ class nsHtml5SpeculativeLoad {
|
||||
referrerPolicy));
|
||||
aIntegrity.ToString(
|
||||
mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
|
||||
mIsLinkPreload = aLinkPreload;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -261,6 +264,13 @@ class nsHtml5SpeculativeLoad {
|
||||
bool mIsAsync;
|
||||
bool mIsDefer;
|
||||
|
||||
/**
|
||||
* True if and only if this is a speculative load initiated by <link
|
||||
* rel="preload"> tag encounter. Passed to the handling loader as an
|
||||
* indication to raise the priority.
|
||||
*/
|
||||
bool mIsLinkPreload;
|
||||
|
||||
/* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
|
||||
* "sizes" attribute. If the attribute is not set, this will be a void
|
||||
* string. Otherwise it empty or the value of the url.
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "nsError.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/StaticPrefs_network.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder)
|
||||
@ -230,7 +231,8 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
|
||||
aAttributes->contains(nsHtml5AttributeName::ATTR_NOMODULE);
|
||||
mSpeculativeLoadQueue.AppendElement()->InitScript(
|
||||
url, charset, type, crossOrigin, integrity, referrerPolicy,
|
||||
mode == nsHtml5TreeBuilder::IN_HEAD, async, defer, noModule);
|
||||
mode == nsHtml5TreeBuilder::IN_HEAD, async, defer, noModule,
|
||||
false);
|
||||
mCurrentHtmlScriptIsAsyncOrDefer = async || defer;
|
||||
}
|
||||
} else if (nsGkAtoms::link == aName) {
|
||||
@ -252,7 +254,8 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
|
||||
nsHtml5String referrerPolicy = aAttributes->getValue(
|
||||
nsHtml5AttributeName::ATTR_REFERRERPOLICY);
|
||||
mSpeculativeLoadQueue.AppendElement()->InitStyle(
|
||||
url, charset, crossOrigin, referrerPolicy, integrity);
|
||||
url, charset, crossOrigin, referrerPolicy, integrity,
|
||||
false);
|
||||
}
|
||||
} else if (rel.LowerCaseEqualsASCII("preconnect")) {
|
||||
nsHtml5String url =
|
||||
@ -263,6 +266,43 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
|
||||
mSpeculativeLoadQueue.AppendElement()->InitPreconnect(
|
||||
url, crossOrigin);
|
||||
}
|
||||
} else if (StaticPrefs::network_preload_experimental() &&
|
||||
rel.LowerCaseEqualsASCII("preload")) {
|
||||
nsHtml5String url =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF);
|
||||
if (url) {
|
||||
nsHtml5String as =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_AS);
|
||||
nsHtml5String charset =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_CHARSET);
|
||||
nsHtml5String crossOrigin = aAttributes->getValue(
|
||||
nsHtml5AttributeName::ATTR_CROSSORIGIN);
|
||||
nsHtml5String integrity =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_INTEGRITY);
|
||||
nsHtml5String referrerPolicy = aAttributes->getValue(
|
||||
nsHtml5AttributeName::ATTR_REFERRERPOLICY);
|
||||
|
||||
// Note that respective speculative loaders for scripts and
|
||||
// styles check all additional attributes to be equal to use the
|
||||
// speculative load. So, if any of them is specified and the
|
||||
// preload has to take the expected effect, those attributes
|
||||
// must also be specified on the actual tag to use the preload.
|
||||
// Omitting an attribute on both will make the values equal
|
||||
// (empty) and thus use the preload.
|
||||
if (as.LowerCaseEqualsASCII("script")) {
|
||||
nsHtml5String type =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_TYPE);
|
||||
mSpeculativeLoadQueue.AppendElement()->InitScript(
|
||||
url, charset, type, crossOrigin, integrity,
|
||||
referrerPolicy, mode == nsHtml5TreeBuilder::IN_HEAD,
|
||||
false, false, false, true);
|
||||
} else if (as.LowerCaseEqualsASCII("style")) {
|
||||
mSpeculativeLoadQueue.AppendElement()->InitStyle(
|
||||
url, charset, crossOrigin, referrerPolicy, integrity,
|
||||
true);
|
||||
}
|
||||
// Other "as" values will be supported later.
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (nsGkAtoms::video == aName) {
|
||||
@ -350,7 +390,8 @@ nsIContentHandle* nsHtml5TreeBuilder::createElement(
|
||||
nsHtml5AttributeName::ATTR_REFERRERPOLICY);
|
||||
mSpeculativeLoadQueue.AppendElement()->InitScript(
|
||||
url, nullptr, type, crossOrigin, integrity, referrerPolicy,
|
||||
mode == nsHtml5TreeBuilder::IN_HEAD, false, false, false);
|
||||
mode == nsHtml5TreeBuilder::IN_HEAD, false, false, false,
|
||||
false);
|
||||
}
|
||||
} else if (nsGkAtoms::style == aName) {
|
||||
mImportScanner.Start();
|
||||
|
@ -978,29 +978,31 @@ void nsHtml5TreeOpExecutor::PreloadScript(
|
||||
const nsAString& aURL, const nsAString& aCharset, const nsAString& aType,
|
||||
const nsAString& aCrossOrigin, const nsAString& aIntegrity,
|
||||
dom::ReferrerPolicy aReferrerPolicy, bool aScriptFromHead, bool aAsync,
|
||||
bool aDefer, bool aNoModule) {
|
||||
bool aDefer, bool aNoModule, bool aLinkPreload) {
|
||||
nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
mDocument->ScriptLoader()->PreloadURI(
|
||||
uri, aCharset, aType, aCrossOrigin, aIntegrity, aScriptFromHead, aAsync,
|
||||
aDefer, aNoModule, GetPreloadReferrerPolicy(aReferrerPolicy));
|
||||
aDefer, aNoModule, aLinkPreload,
|
||||
GetPreloadReferrerPolicy(aReferrerPolicy));
|
||||
}
|
||||
|
||||
void nsHtml5TreeOpExecutor::PreloadStyle(const nsAString& aURL,
|
||||
const nsAString& aCharset,
|
||||
const nsAString& aCrossOrigin,
|
||||
const nsAString& aReferrerPolicy,
|
||||
const nsAString& aIntegrity) {
|
||||
const nsAString& aIntegrity,
|
||||
bool aLinkPreload) {
|
||||
nsCOMPtr<nsIURI> uri = ConvertIfNotPreloadedYet(aURL);
|
||||
if (!uri) {
|
||||
return;
|
||||
}
|
||||
|
||||
mDocument->PreloadStyle(uri, Encoding::ForLabel(aCharset), aCrossOrigin,
|
||||
GetPreloadReferrerPolicy(aReferrerPolicy),
|
||||
aIntegrity);
|
||||
GetPreloadReferrerPolicy(aReferrerPolicy), aIntegrity,
|
||||
aLinkPreload);
|
||||
}
|
||||
|
||||
void nsHtml5TreeOpExecutor::PreloadImage(
|
||||
|
@ -233,12 +233,13 @@ class nsHtml5TreeOpExecutor final
|
||||
const nsAString& aType, const nsAString& aCrossOrigin,
|
||||
const nsAString& aIntegrity,
|
||||
ReferrerPolicy aReferrerPolicy, bool aScriptFromHead,
|
||||
bool aAsync, bool aDefer, bool aNoModule);
|
||||
bool aAsync, bool aDefer, bool aNoModule,
|
||||
bool aLinkPreload);
|
||||
|
||||
void PreloadStyle(const nsAString& aURL, const nsAString& aCharset,
|
||||
const nsAString& aCrossOrigin,
|
||||
const nsAString& aReferrerPolicy,
|
||||
const nsAString& aIntegrity);
|
||||
const nsAString& aIntegrity, bool aLinkPreload);
|
||||
|
||||
void PreloadImage(const nsAString& aURL, const nsAString& aCrossOrigin,
|
||||
const nsAString& aSrcset, const nsAString& aSizes,
|
||||
|
Loading…
Reference in New Issue
Block a user