Bug 1865610: part 10) Add `fetchpriority` attribute support for `rel=preload as=fetch...
[gecko.git] / parser / html / nsHtml5SpeculativeLoad.h
blobd53d3a5b46cc7bcc9660224dd649ecbf7749a457
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef nsHtml5SpeculativeLoad_h
6 #define nsHtml5SpeculativeLoad_h
8 #include "nsString.h"
9 #include "nsContentUtils.h"
10 #include "nsHtml5DocumentMode.h"
11 #include "nsHtml5String.h"
12 #include "ReferrerInfo.h"
14 class nsHtml5TreeOpExecutor;
16 enum eHtml5SpeculativeLoad {
17 eSpeculativeLoadUninitialized,
18 eSpeculativeLoadBase,
19 eSpeculativeLoadCSP,
20 eSpeculativeLoadMetaReferrer,
21 eSpeculativeLoadImage,
22 eSpeculativeLoadOpenPicture,
23 eSpeculativeLoadEndPicture,
24 eSpeculativeLoadPictureSource,
25 eSpeculativeLoadScript,
26 eSpeculativeLoadScriptFromHead,
27 eSpeculativeLoadStyle,
28 eSpeculativeLoadManifest,
29 eSpeculativeLoadSetDocumentCharset,
30 eSpeculativeLoadSetDocumentMode,
31 eSpeculativeLoadPreconnect,
32 eSpeculativeLoadFont,
33 eSpeculativeLoadFetch,
34 eSpeculativeLoadMaybeComplainAboutCharset
37 class nsHtml5SpeculativeLoad {
38 using Encoding = mozilla::Encoding;
39 template <typename T>
40 using NotNull = mozilla::NotNull<T>;
42 public:
43 nsHtml5SpeculativeLoad();
44 ~nsHtml5SpeculativeLoad();
46 inline void InitBase(nsHtml5String aUrl) {
47 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
48 "Trying to reinitialize a speculative load!");
49 mOpCode = eSpeculativeLoadBase;
50 aUrl.ToString(mUrlOrSizes);
53 inline void InitMetaCSP(nsHtml5String aCSP) {
54 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
55 "Trying to reinitialize a speculative load!");
56 mOpCode = eSpeculativeLoadCSP;
57 nsString csp; // Not Auto, because using it to hold nsStringBuffer*
58 aCSP.ToString(csp);
59 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
60 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp));
63 inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) {
64 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
65 "Trying to reinitialize a speculative load!");
66 mOpCode = eSpeculativeLoadMetaReferrer;
67 nsString
68 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
69 aReferrerPolicy.ToString(referrerPolicy);
70 mReferrerPolicyOrIntegrity.Assign(
71 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
72 referrerPolicy));
75 inline void InitImage(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
76 nsHtml5String aMedia, nsHtml5String aReferrerPolicy,
77 nsHtml5String aSrcset, nsHtml5String aSizes,
78 bool aLinkPreload) {
79 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
80 "Trying to reinitialize a speculative load!");
81 mOpCode = eSpeculativeLoadImage;
82 aUrl.ToString(mUrlOrSizes);
83 aCrossOrigin.ToString(mCrossOrigin);
84 aMedia.ToString(mMedia);
85 nsString
86 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
87 aReferrerPolicy.ToString(referrerPolicy);
88 mReferrerPolicyOrIntegrity.Assign(
89 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
90 referrerPolicy));
91 aSrcset.ToString(mCharsetOrSrcset);
92 aSizes.ToString(
93 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
94 mIsLinkPreload = aLinkPreload;
97 inline void InitFont(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
98 nsHtml5String aMedia, nsHtml5String aReferrerPolicy,
99 nsHtml5String aFetchPriority) {
100 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
101 "Trying to reinitialize a speculative load!");
102 mOpCode = eSpeculativeLoadFont;
103 aUrl.ToString(mUrlOrSizes);
104 aCrossOrigin.ToString(mCrossOrigin);
105 aMedia.ToString(mMedia);
106 nsString
107 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
108 aReferrerPolicy.ToString(referrerPolicy);
109 mReferrerPolicyOrIntegrity.Assign(
110 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
111 referrerPolicy));
112 aFetchPriority.ToString(mFetchPriority);
113 // This can be only triggered by <link rel=preload type=font>
114 mIsLinkPreload = true;
117 inline void InitFetch(nsHtml5String aUrl, nsHtml5String aCrossOrigin,
118 nsHtml5String aMedia, nsHtml5String aReferrerPolicy,
119 nsHtml5String aFetchPriority) {
120 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
121 "Trying to reinitialize a speculative load!");
122 mOpCode = eSpeculativeLoadFetch;
123 aUrl.ToString(mUrlOrSizes);
124 aCrossOrigin.ToString(mCrossOrigin);
125 aMedia.ToString(mMedia);
126 nsString
127 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
128 aReferrerPolicy.ToString(referrerPolicy);
129 mReferrerPolicyOrIntegrity.Assign(
130 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
131 referrerPolicy));
132 aFetchPriority.ToString(mFetchPriority);
134 // This method can be only be triggered by <link rel=preload type=fetch>,
135 // hence this operation is always a preload.
136 mIsLinkPreload = true;
139 // <picture> elements have multiple <source> nodes followed by an <img>,
140 // where we use the first valid source, which may be the img. Because we
141 // can't determine validity at this point without parsing CSS and getting
142 // main thread state, we push preload operations for picture pushed and
143 // popped, so that the target of the preload ops can determine what picture
144 // and nesting level each source/img from the main preloading code exists
145 // at.
146 inline void InitOpenPicture() {
147 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
148 "Trying to reinitialize a speculative load!");
149 mOpCode = eSpeculativeLoadOpenPicture;
152 inline void InitEndPicture() {
153 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
154 "Trying to reinitialize a speculative load!");
155 mOpCode = eSpeculativeLoadEndPicture;
158 inline void InitPictureSource(nsHtml5String aSrcset, nsHtml5String aSizes,
159 nsHtml5String aType, nsHtml5String aMedia) {
160 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
161 "Trying to reinitialize a speculative load!");
162 mOpCode = eSpeculativeLoadPictureSource;
163 aSrcset.ToString(mCharsetOrSrcset);
164 aSizes.ToString(mUrlOrSizes);
165 aType.ToString(
166 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
167 aMedia.ToString(mMedia);
170 inline void InitScript(nsHtml5String aUrl, nsHtml5String aCharset,
171 nsHtml5String aType, nsHtml5String aCrossOrigin,
172 nsHtml5String aMedia, nsHtml5String aNonce,
173 nsHtml5String aFetchPriority, nsHtml5String aIntegrity,
174 nsHtml5String aReferrerPolicy, bool aParserInHead,
175 bool aAsync, bool aDefer, bool aLinkPreload) {
176 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
177 "Trying to reinitialize a speculative load!");
178 mOpCode =
179 aParserInHead ? eSpeculativeLoadScriptFromHead : eSpeculativeLoadScript;
180 aUrl.ToString(mUrlOrSizes);
181 aCharset.ToString(mCharsetOrSrcset);
182 aType.ToString(
183 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
184 aCrossOrigin.ToString(mCrossOrigin);
185 aMedia.ToString(mMedia);
186 aNonce.ToString(mNonce);
187 aFetchPriority.ToString(mFetchPriority);
188 aIntegrity.ToString(mReferrerPolicyOrIntegrity);
189 nsAutoString referrerPolicy;
190 aReferrerPolicy.ToString(referrerPolicy);
191 referrerPolicy =
192 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
193 referrerPolicy);
194 mScriptReferrerPolicy =
195 mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString(
196 referrerPolicy);
198 mIsAsync = aAsync;
199 mIsDefer = aDefer;
200 mIsLinkPreload = aLinkPreload;
203 inline void InitImportStyle(nsString&& aUrl) {
204 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
205 "Trying to reinitialize a speculative load!");
206 mOpCode = eSpeculativeLoadStyle;
207 mUrlOrSizes = std::move(aUrl);
208 mCharsetOrSrcset.SetIsVoid(true);
209 mCrossOrigin.SetIsVoid(true);
210 mMedia.SetIsVoid(true);
211 mReferrerPolicyOrIntegrity.SetIsVoid(true);
212 mNonce.SetIsVoid(true);
213 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.SetIsVoid(
214 true);
217 inline void InitStyle(nsHtml5String aUrl, nsHtml5String aCharset,
218 nsHtml5String aCrossOrigin, nsHtml5String aMedia,
219 nsHtml5String aReferrerPolicy, nsHtml5String aNonce,
220 nsHtml5String aIntegrity, bool aLinkPreload,
221 nsHtml5String aFetchPriority) {
222 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
223 "Trying to reinitialize a speculative load!");
224 mOpCode = eSpeculativeLoadStyle;
225 aUrl.ToString(mUrlOrSizes);
226 aCharset.ToString(mCharsetOrSrcset);
227 aCrossOrigin.ToString(mCrossOrigin);
228 aMedia.ToString(mMedia);
229 nsString
230 referrerPolicy; // Not Auto, because using it to hold nsStringBuffer*
231 aReferrerPolicy.ToString(referrerPolicy);
232 mReferrerPolicyOrIntegrity.Assign(
233 nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(
234 referrerPolicy));
235 aNonce.ToString(mNonce);
236 aIntegrity.ToString(
237 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity);
238 mIsLinkPreload = aLinkPreload;
239 aFetchPriority.ToString(mFetchPriority);
243 * "Speculative" manifest loads aren't truly speculative--if a manifest
244 * gets loaded, we are committed to it. There can never be a <script>
245 * before the manifest, so the situation of having to undo a manifest due
246 * to document.write() never arises. The reason why a parser
247 * thread-discovered manifest gets loaded via the speculative load queue
248 * as opposed to tree operation queue is that the manifest must get
249 * processed before any actual speculative loads such as scripts. Thus,
250 * manifests seen by the parser thread have to maintain the queue order
251 * relative to true speculative loads. See bug 541079.
253 inline void InitManifest(nsHtml5String aUrl) {
254 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
255 "Trying to reinitialize a speculative load!");
256 mOpCode = eSpeculativeLoadManifest;
257 aUrl.ToString(mUrlOrSizes);
261 * We communicate the encoding change via the speculative operation
262 * queue in order to act upon it as soon as possible and so as not to
263 * have speculative loads generated after an encoding change fail to
264 * make use of the encoding change.
266 inline void InitSetDocumentCharset(NotNull<const Encoding*> aEncoding,
267 int32_t aCharsetSource,
268 bool aCommitEncodingSpeculation) {
269 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
270 "Trying to reinitialize a speculative load!");
271 mOpCode = eSpeculativeLoadSetDocumentCharset;
272 mCharsetOrSrcset.~nsString();
273 mEncoding = aEncoding;
274 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
275 (char16_t)aCharsetSource);
276 mCommitEncodingSpeculation = aCommitEncodingSpeculation;
279 inline void InitMaybeComplainAboutCharset(const char* aMsgId, bool aError,
280 int32_t aLineNumber) {
281 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
282 "Trying to reinitialize a speculative load!");
283 mOpCode = eSpeculativeLoadMaybeComplainAboutCharset;
284 mCharsetOrSrcset.~nsString();
285 mMsgId = aMsgId;
286 mIsError = aError;
287 // Transport a 32-bit integer as two 16-bit code units of a string
288 // in order to avoid adding an integer field to the object.
289 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1733043 for a better
290 // eventual approach.
291 char16_t high = (char16_t)(((uint32_t)aLineNumber) >> 16);
292 char16_t low = (char16_t)(((uint32_t)aLineNumber) & 0xFFFF);
293 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(high);
294 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Append(low);
298 * Speculative document mode setting isn't really speculative. Once it
299 * happens, we are committed to it. However, this information needs to
300 * travel in the speculation queue in order to have this information
301 * available before parsing the speculatively loaded style sheets.
303 inline void InitSetDocumentMode(nsHtml5DocumentMode aMode) {
304 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
305 "Trying to reinitialize a speculative load!");
306 mOpCode = eSpeculativeLoadSetDocumentMode;
307 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign(
308 (char16_t)aMode);
311 inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) {
312 MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized,
313 "Trying to reinitialize a speculative load!");
314 mOpCode = eSpeculativeLoadPreconnect;
315 aUrl.ToString(mUrlOrSizes);
316 aCrossOrigin.ToString(mCrossOrigin);
319 void Perform(nsHtml5TreeOpExecutor* aExecutor);
321 private:
322 nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad&) = delete;
323 nsHtml5SpeculativeLoad& operator=(const nsHtml5SpeculativeLoad&) = delete;
325 eHtml5SpeculativeLoad mOpCode;
328 * Whether the refering element has async attribute.
330 bool mIsAsync;
333 * Whether the refering element has defer attribute.
335 bool mIsDefer;
338 * True if and only if this is a speculative load initiated by <link
339 * rel="preload"> or <link rel="modulepreload"> tag encounter. Passed to the
340 * handling loader as an indication to raise the priority.
342 bool mIsLinkPreload;
345 * Whether the charset complaint is an error.
347 bool mIsError;
350 * Whether setting document encoding involves also committing to an encoding
351 * speculation.
353 bool mCommitEncodingSpeculation;
355 /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
356 * "sizes" attribute. If the attribute is not set, this will be a void
357 * string. Otherwise it empty or the value of the url.
359 nsString mUrlOrSizes;
361 * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
362 * "integrity" attribute. If the attribute is not set, this will be a void
363 * string. Otherwise it is empty or the value of the referrer policy.
365 nsString mReferrerPolicyOrIntegrity;
367 * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
368 * then this is the value of the "charset" attribute. For
369 * eSpeculativeLoadSetDocumentCharset it is the charset that the
370 * document's charset is being set to. If mOpCode is eSpeculativeLoadImage
371 * or eSpeculativeLoadPictureSource, this is the value of the "srcset"
372 * attribute. If the attribute is not set, this will be a void string.
373 * Otherwise it's empty.
374 * For eSpeculativeLoadMaybeComplainAboutCharset mMsgId is used.
376 union {
377 nsString mCharsetOrSrcset;
378 const Encoding* mEncoding;
379 const char* mMsgId;
382 * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a
383 * one-character string whose single character's code point is to be
384 * interpreted as a charset source integer. If mOpCode is
385 * eSpeculativeLoadSetDocumentMode, this is a one-character string whose
386 * single character's code point is to be interpreted as an
387 * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta
388 * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the
389 * value of the "sizes" attribute. If the attribute is not set, this will
390 * be a void string. If mOpCode is eSpeculativeLoadStyle, this
391 * is the value of the "integrity" attribute. If the attribute is not set,
392 * this will be a void string. Otherwise, it is empty or the value of the type
393 * attribute.
395 nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity;
397 * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
398 * or eSpeculativeLoadPreconnect or eSpeculativeLoadStyle this is the value of
399 * the "crossorigin" attribute. If the attribute is not set, this will be a
400 * void string.
402 nsString mCrossOrigin;
404 * If mOpCode is eSpeculativeLoadPictureSource or eSpeculativeLoadStyle or
405 * Fetch or Image or Media or Script this is the value of the relevant "media"
406 * attribute of the <link rel="preload"> or <link rel="stylesheet">. If the
407 * attribute is not set, or the preload didn't originate from a <link>, this
408 * will be a void string.
410 nsString mMedia;
412 * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
413 * of the "nonce" attribute.
415 nsString mNonce;
417 * If mOpCode is eSpeculativeLoadNoModuleScript[FromHead] or
418 * eSpeculativeLoadScript[FromHead] this represents the value of the
419 * "fetchpriority" attribute.
421 nsString mFetchPriority;
423 * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
424 * of the "referrerpolicy" attribute. This field holds one of the values
425 * (REFERRER_POLICY_*) defined in nsIHttpChannel.
427 mozilla::dom::ReferrerPolicy mScriptReferrerPolicy;
430 #endif // nsHtml5SpeculativeLoad_h