/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsHtml5SpeculativeLoad_h #define nsHtml5SpeculativeLoad_h #include "nsString.h" #include "nsContentUtils.h" #include "nsHtml5DocumentMode.h" #include "nsHtml5String.h" #include "ReferrerInfo.h" class nsHtml5TreeOpExecutor; enum eHtml5SpeculativeLoad { eSpeculativeLoadUninitialized, eSpeculativeLoadBase, eSpeculativeLoadCSP, eSpeculativeLoadMetaReferrer, eSpeculativeLoadImage, eSpeculativeLoadOpenPicture, eSpeculativeLoadEndPicture, eSpeculativeLoadPictureSource, eSpeculativeLoadScript, eSpeculativeLoadScriptFromHead, eSpeculativeLoadNoModuleScript, eSpeculativeLoadNoModuleScriptFromHead, eSpeculativeLoadStyle, eSpeculativeLoadManifest, eSpeculativeLoadSetDocumentCharset, eSpeculativeLoadSetDocumentMode, eSpeculativeLoadPreconnect, eSpeculativeLoadFont, eSpeculativeLoadFetch }; class nsHtml5SpeculativeLoad { using Encoding = mozilla::Encoding; template using NotNull = mozilla::NotNull; public: nsHtml5SpeculativeLoad(); ~nsHtml5SpeculativeLoad(); inline void InitBase(nsHtml5String aUrl) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadBase; aUrl.ToString(mUrlOrSizes); } inline void InitMetaCSP(nsHtml5String aCSP) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadCSP; nsString csp; // Not Auto, because using it to hold nsStringBuffer* aCSP.ToString(csp); mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign( nsContentUtils::TrimWhitespace(csp)); } inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadMetaReferrer; nsString referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* aReferrerPolicy.ToString(referrerPolicy); mReferrerPolicyOrIntegrity.Assign( nsContentUtils::TrimWhitespace( referrerPolicy)); } inline void InitImage(nsHtml5String aUrl, nsHtml5String aCrossOrigin, nsHtml5String aReferrerPolicy, nsHtml5String aSrcset, nsHtml5String aSizes, bool aLinkPreload) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadImage; aUrl.ToString(mUrlOrSizes); aCrossOrigin.ToString(mCrossOriginOrMedia); nsString referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* aReferrerPolicy.ToString(referrerPolicy); mReferrerPolicyOrIntegrity.Assign( nsContentUtils::TrimWhitespace( referrerPolicy)); aSrcset.ToString(mCharsetOrSrcset); aSizes.ToString( mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); mIsLinkPreload = aLinkPreload; } inline void InitFont(nsHtml5String aUrl, nsHtml5String aCrossOrigin, nsHtml5String aReferrerPolicy) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadFont; aUrl.ToString(mUrlOrSizes); aCrossOrigin.ToString(mCrossOriginOrMedia); nsString referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* aReferrerPolicy.ToString(referrerPolicy); mReferrerPolicyOrIntegrity.Assign( nsContentUtils::TrimWhitespace( referrerPolicy)); // This can be only triggered by mIsLinkPreload = true; } inline void InitFetch(nsHtml5String aUrl, nsHtml5String aCrossOrigin, nsHtml5String aReferrerPolicy) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadFetch; aUrl.ToString(mUrlOrSizes); aCrossOrigin.ToString(mCrossOriginOrMedia); nsString referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* aReferrerPolicy.ToString(referrerPolicy); mReferrerPolicyOrIntegrity.Assign( nsContentUtils::TrimWhitespace( referrerPolicy)); // This method can be only be triggered by , // hence this operation is always a preload. mIsLinkPreload = true; } // elements have multiple nodes followed by an , // where we use the first valid source, which may be the img. Because we // can't determine validity at this point without parsing CSS and getting // main thread state, we push preload operations for picture pushed and // popped, so that the target of the preload ops can determine what picture // and nesting level each source/img from the main preloading code exists // at. inline void InitOpenPicture() { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadOpenPicture; } inline void InitEndPicture() { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadEndPicture; } inline void InitPictureSource(nsHtml5String aSrcset, nsHtml5String aSizes, nsHtml5String aType, nsHtml5String aMedia) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadPictureSource; aSrcset.ToString(mCharsetOrSrcset); aSizes.ToString(mUrlOrSizes); aType.ToString( mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); aMedia.ToString(mCrossOriginOrMedia); } inline void InitScript(nsHtml5String aUrl, nsHtml5String aCharset, nsHtml5String aType, nsHtml5String aCrossOrigin, nsHtml5String aIntegrity, nsHtml5String aReferrerPolicy, bool aParserInHead, bool aAsync, bool aDefer, bool aNoModule, bool aLinkPreload) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); if (aNoModule) { mOpCode = aParserInHead ? eSpeculativeLoadNoModuleScriptFromHead : eSpeculativeLoadNoModuleScript; } else { mOpCode = aParserInHead ? eSpeculativeLoadScriptFromHead : eSpeculativeLoadScript; } aUrl.ToString(mUrlOrSizes); aCharset.ToString(mCharsetOrSrcset); aType.ToString( mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); aCrossOrigin.ToString(mCrossOriginOrMedia); aIntegrity.ToString(mReferrerPolicyOrIntegrity); nsAutoString referrerPolicy; aReferrerPolicy.ToString(referrerPolicy); referrerPolicy = nsContentUtils::TrimWhitespace( referrerPolicy); mScriptReferrerPolicy = mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString( referrerPolicy); mIsAsync = aAsync; mIsDefer = aDefer; mIsLinkPreload = aLinkPreload; } inline void InitImportStyle(nsString&& aUrl) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadStyle; mUrlOrSizes = std::move(aUrl); mCharsetOrSrcset.SetIsVoid(true); mCrossOriginOrMedia.SetIsVoid(true); mReferrerPolicyOrIntegrity.SetIsVoid(true); mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.SetIsVoid( true); } inline void InitStyle(nsHtml5String aUrl, nsHtml5String aCharset, nsHtml5String aCrossOrigin, nsHtml5String aReferrerPolicy, nsHtml5String aIntegrity, bool aLinkPreload) { MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, "Trying to reinitialize a speculative load!"); mOpCode = eSpeculativeLoadStyle; aUrl.ToString(mUrlOrSizes); aCharset.ToString(mCharsetOrSrcset); aCrossOrigin.ToString(mCrossOriginOrMedia); nsString referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* aReferrerPolicy.ToString(referrerPolicy); mReferrerPolicyOrIntegrity.Assign( nsContentUtils::TrimWhitespace( referrerPolicy)); aIntegrity.ToString( mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); mIsLinkPreload = aLinkPreload; } /** * "Speculative" manifest loads aren't truly speculative--if a manifest * gets loaded, we are committed to it. There can never be a