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
9 #include "nsContentUtils.h"
10 #include "nsHtml5DocumentMode.h"
11 #include "nsHtml5String.h"
12 #include "ReferrerInfo.h"
14 class nsHtml5TreeOpExecutor
;
16 enum eHtml5SpeculativeLoad
{
17 eSpeculativeLoadUninitialized
,
20 eSpeculativeLoadMetaReferrer
,
21 eSpeculativeLoadImage
,
22 eSpeculativeLoadOpenPicture
,
23 eSpeculativeLoadEndPicture
,
24 eSpeculativeLoadPictureSource
,
25 eSpeculativeLoadScript
,
26 eSpeculativeLoadScriptFromHead
,
27 eSpeculativeLoadNoModuleScript
,
28 eSpeculativeLoadNoModuleScriptFromHead
,
29 eSpeculativeLoadStyle
,
30 eSpeculativeLoadManifest
,
31 eSpeculativeLoadSetDocumentCharset
,
32 eSpeculativeLoadSetDocumentMode
,
33 eSpeculativeLoadPreconnect
,
38 class nsHtml5SpeculativeLoad
{
39 using Encoding
= mozilla::Encoding
;
41 using NotNull
= mozilla::NotNull
<T
>;
44 nsHtml5SpeculativeLoad();
45 ~nsHtml5SpeculativeLoad();
47 inline void InitBase(nsHtml5String aUrl
) {
48 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
49 "Trying to reinitialize a speculative load!");
50 mOpCode
= eSpeculativeLoadBase
;
51 aUrl
.ToString(mUrlOrSizes
);
54 inline void InitMetaCSP(nsHtml5String aCSP
) {
55 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
56 "Trying to reinitialize a speculative load!");
57 mOpCode
= eSpeculativeLoadCSP
;
58 nsString csp
; // Not Auto, because using it to hold nsStringBuffer*
60 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
.Assign(
61 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(csp
));
64 inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy
) {
65 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
66 "Trying to reinitialize a speculative load!");
67 mOpCode
= eSpeculativeLoadMetaReferrer
;
69 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
70 aReferrerPolicy
.ToString(referrerPolicy
);
71 mReferrerPolicyOrIntegrity
.Assign(
72 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
76 inline void InitImage(nsHtml5String aUrl
, nsHtml5String aCrossOrigin
,
77 nsHtml5String aReferrerPolicy
, nsHtml5String aSrcset
,
78 nsHtml5String aSizes
, bool aLinkPreload
) {
79 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
80 "Trying to reinitialize a speculative load!");
81 mOpCode
= eSpeculativeLoadImage
;
82 aUrl
.ToString(mUrlOrSizes
);
83 aCrossOrigin
.ToString(mCrossOriginOrMedia
);
85 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
86 aReferrerPolicy
.ToString(referrerPolicy
);
87 mReferrerPolicyOrIntegrity
.Assign(
88 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
90 aSrcset
.ToString(mCharsetOrSrcset
);
92 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
);
93 mIsLinkPreload
= aLinkPreload
;
96 inline void InitFont(nsHtml5String aUrl
, nsHtml5String aCrossOrigin
,
97 nsHtml5String aReferrerPolicy
) {
98 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
99 "Trying to reinitialize a speculative load!");
100 mOpCode
= eSpeculativeLoadFont
;
101 aUrl
.ToString(mUrlOrSizes
);
102 aCrossOrigin
.ToString(mCrossOriginOrMedia
);
104 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
105 aReferrerPolicy
.ToString(referrerPolicy
);
106 mReferrerPolicyOrIntegrity
.Assign(
107 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
109 // This can be only triggered by <link rel=preload type=font>
110 mIsLinkPreload
= true;
113 inline void InitFetch(nsHtml5String aUrl
, nsHtml5String aCrossOrigin
,
114 nsHtml5String aReferrerPolicy
) {
115 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
116 "Trying to reinitialize a speculative load!");
117 mOpCode
= eSpeculativeLoadFetch
;
118 aUrl
.ToString(mUrlOrSizes
);
119 aCrossOrigin
.ToString(mCrossOriginOrMedia
);
121 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
122 aReferrerPolicy
.ToString(referrerPolicy
);
123 mReferrerPolicyOrIntegrity
.Assign(
124 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
127 // This method can be only be triggered by <link rel=preload type=fetch>,
128 // hence this operation is always a preload.
129 mIsLinkPreload
= true;
132 // <picture> elements have multiple <source> nodes followed by an <img>,
133 // where we use the first valid source, which may be the img. Because we
134 // can't determine validity at this point without parsing CSS and getting
135 // main thread state, we push preload operations for picture pushed and
136 // popped, so that the target of the preload ops can determine what picture
137 // and nesting level each source/img from the main preloading code exists
139 inline void InitOpenPicture() {
140 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
141 "Trying to reinitialize a speculative load!");
142 mOpCode
= eSpeculativeLoadOpenPicture
;
145 inline void InitEndPicture() {
146 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
147 "Trying to reinitialize a speculative load!");
148 mOpCode
= eSpeculativeLoadEndPicture
;
151 inline void InitPictureSource(nsHtml5String aSrcset
, nsHtml5String aSizes
,
152 nsHtml5String aType
, nsHtml5String aMedia
) {
153 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
154 "Trying to reinitialize a speculative load!");
155 mOpCode
= eSpeculativeLoadPictureSource
;
156 aSrcset
.ToString(mCharsetOrSrcset
);
157 aSizes
.ToString(mUrlOrSizes
);
159 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
);
160 aMedia
.ToString(mCrossOriginOrMedia
);
163 inline void InitScript(nsHtml5String aUrl
, nsHtml5String aCharset
,
164 nsHtml5String aType
, nsHtml5String aCrossOrigin
,
165 nsHtml5String aIntegrity
,
166 nsHtml5String aReferrerPolicy
, bool aParserInHead
,
167 bool aAsync
, bool aDefer
, bool aNoModule
,
169 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
170 "Trying to reinitialize a speculative load!");
172 mOpCode
= aParserInHead
? eSpeculativeLoadNoModuleScriptFromHead
173 : eSpeculativeLoadNoModuleScript
;
175 mOpCode
= aParserInHead
? eSpeculativeLoadScriptFromHead
176 : eSpeculativeLoadScript
;
178 aUrl
.ToString(mUrlOrSizes
);
179 aCharset
.ToString(mCharsetOrSrcset
);
181 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
);
182 aCrossOrigin
.ToString(mCrossOriginOrMedia
);
183 aIntegrity
.ToString(mReferrerPolicyOrIntegrity
);
184 nsAutoString referrerPolicy
;
185 aReferrerPolicy
.ToString(referrerPolicy
);
187 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
189 mScriptReferrerPolicy
=
190 mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString(
195 mIsLinkPreload
= aLinkPreload
;
198 inline void InitImportStyle(nsString
&& aUrl
) {
199 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
200 "Trying to reinitialize a speculative load!");
201 mOpCode
= eSpeculativeLoadStyle
;
202 mUrlOrSizes
= std::move(aUrl
);
203 mCharsetOrSrcset
.SetIsVoid(true);
204 mCrossOriginOrMedia
.SetIsVoid(true);
205 mReferrerPolicyOrIntegrity
.SetIsVoid(true);
206 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
.SetIsVoid(
210 inline void InitStyle(nsHtml5String aUrl
, nsHtml5String aCharset
,
211 nsHtml5String aCrossOrigin
,
212 nsHtml5String aReferrerPolicy
, nsHtml5String aIntegrity
,
214 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
215 "Trying to reinitialize a speculative load!");
216 mOpCode
= eSpeculativeLoadStyle
;
217 aUrl
.ToString(mUrlOrSizes
);
218 aCharset
.ToString(mCharsetOrSrcset
);
219 aCrossOrigin
.ToString(mCrossOriginOrMedia
);
221 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
222 aReferrerPolicy
.ToString(referrerPolicy
);
223 mReferrerPolicyOrIntegrity
.Assign(
224 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
227 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
);
228 mIsLinkPreload
= aLinkPreload
;
232 * "Speculative" manifest loads aren't truly speculative--if a manifest
233 * gets loaded, we are committed to it. There can never be a <script>
234 * before the manifest, so the situation of having to undo a manifest due
235 * to document.write() never arises. The reason why a parser
236 * thread-discovered manifest gets loaded via the speculative load queue
237 * as opposed to tree operation queue is that the manifest must get
238 * processed before any actual speculative loads such as scripts. Thus,
239 * manifests seen by the parser thread have to maintain the queue order
240 * relative to true speculative loads. See bug 541079.
242 inline void InitManifest(nsHtml5String aUrl
) {
243 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
244 "Trying to reinitialize a speculative load!");
245 mOpCode
= eSpeculativeLoadManifest
;
246 aUrl
.ToString(mUrlOrSizes
);
250 * "Speculative" charset setting isn't truly speculative. If the charset
251 * is set via this operation, we are committed to it unless chardet or
252 * a late meta cause a reload. The reason why a parser
253 * thread-discovered charset gets communicated via the speculative load
254 * queue as opposed to tree operation queue is that the charset change
255 * must get processed before any actual speculative loads such as style
256 * sheets. Thus, encoding decisions by the parser thread have to maintain
257 * the queue order relative to true speculative loads. See bug 675499.
259 inline void InitSetDocumentCharset(NotNull
<const Encoding
*> aEncoding
,
260 int32_t aCharsetSource
) {
261 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
262 "Trying to reinitialize a speculative load!");
263 mOpCode
= eSpeculativeLoadSetDocumentCharset
;
264 mCharsetOrSrcset
.~nsString();
265 mEncoding
= aEncoding
;
266 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
.Assign(
267 (char16_t
)aCharsetSource
);
271 * Speculative document mode setting isn't really speculative. Once it
272 * happens, we are committed to it. However, this information needs to
273 * travel in the speculation queue in order to have this information
274 * available before parsing the speculatively loaded style sheets.
276 inline void InitSetDocumentMode(nsHtml5DocumentMode aMode
) {
277 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
278 "Trying to reinitialize a speculative load!");
279 mOpCode
= eSpeculativeLoadSetDocumentMode
;
280 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
.Assign(
284 inline void InitPreconnect(nsHtml5String aUrl
, nsHtml5String aCrossOrigin
) {
285 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
286 "Trying to reinitialize a speculative load!");
287 mOpCode
= eSpeculativeLoadPreconnect
;
288 aUrl
.ToString(mUrlOrSizes
);
289 aCrossOrigin
.ToString(mCrossOriginOrMedia
);
292 void Perform(nsHtml5TreeOpExecutor
* aExecutor
);
295 nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad
&) = delete;
296 nsHtml5SpeculativeLoad
& operator=(const nsHtml5SpeculativeLoad
&) = delete;
298 eHtml5SpeculativeLoad mOpCode
;
301 * Whether the refering element has async and/or defer attributes.
307 * True if and only if this is a speculative load initiated by <link
308 * rel="preload"> tag encounter. Passed to the handling loader as an
309 * indication to raise the priority.
313 /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
314 * "sizes" attribute. If the attribute is not set, this will be a void
315 * string. Otherwise it empty or the value of the url.
317 nsString mUrlOrSizes
;
319 * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
320 * "integrity" attribute. If the attribute is not set, this will be a void
321 * string. Otherwise it is empty or the value of the referrer policy.
323 nsString mReferrerPolicyOrIntegrity
;
325 * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
326 * then this is the value of the "charset" attribute. For
327 * eSpeculativeLoadSetDocumentCharset it is the charset that the
328 * document's charset is being set to. If mOpCode is eSpeculativeLoadImage
329 * or eSpeculativeLoadPictureSource, this is the value of the "srcset"
330 * attribute. If the attribute is not set, this will be a void string.
331 * Otherwise it's empty.
334 nsString mCharsetOrSrcset
;
335 const Encoding
* mEncoding
;
338 * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a
339 * one-character string whose single character's code point is to be
340 * interpreted as a charset source integer. If mOpCode is
341 * eSpeculativeLoadSetDocumentMode, this is a one-character string whose
342 * single character's code point is to be interpreted as an
343 * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta
344 * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the
345 * value of the "sizes" attribute. If the attribute is not set, this will
346 * be a void string. If mOpCode is eSpeculativeLoadStyle, this
347 * is the value of the "integrity" attribute. If the attribute is not set,
348 * this will be a void string. Otherwise it is empty or the value of the
349 * referrer policy. Otherwise, it is empty or the value of the type attribute.
351 nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
;
353 * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
354 * or eSpeculativeLoadPreconnect this is the value of the "crossorigin"
355 * attribute. If the attribute is not set, this will be a void string.
356 * If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
357 * "media" attribute. If the attribute is not set, this will be a void
360 nsString mCrossOriginOrMedia
;
362 * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
363 * of the "referrerpolicy" attribute. This field holds one of the values
364 * (REFERRER_POLICY_*) defined in nsIHttpChannel.
366 mozilla::dom::ReferrerPolicy mScriptReferrerPolicy
;
369 #endif // nsHtml5SpeculativeLoad_h