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 aMedia
, nsHtml5String aReferrerPolicy
,
78 nsHtml5String aSrcset
, nsHtml5String aSizes
,
80 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
81 "Trying to reinitialize a speculative load!");
82 mOpCode
= eSpeculativeLoadImage
;
83 aUrl
.ToString(mUrlOrSizes
);
84 aCrossOrigin
.ToString(mCrossOrigin
);
85 aMedia
.ToString(mMedia
);
87 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
88 aReferrerPolicy
.ToString(referrerPolicy
);
89 mReferrerPolicyOrIntegrity
.Assign(
90 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
92 aSrcset
.ToString(mCharsetOrSrcset
);
94 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
);
95 mIsLinkPreload
= aLinkPreload
;
98 inline void InitFont(nsHtml5String aUrl
, nsHtml5String aCrossOrigin
,
99 nsHtml5String aMedia
, nsHtml5String aReferrerPolicy
) {
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
);
107 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
108 aReferrerPolicy
.ToString(referrerPolicy
);
109 mReferrerPolicyOrIntegrity
.Assign(
110 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
112 // This can be only triggered by <link rel=preload type=font>
113 mIsLinkPreload
= true;
116 inline void InitFetch(nsHtml5String aUrl
, nsHtml5String aCrossOrigin
,
117 nsHtml5String aMedia
, nsHtml5String aReferrerPolicy
) {
118 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
119 "Trying to reinitialize a speculative load!");
120 mOpCode
= eSpeculativeLoadFetch
;
121 aUrl
.ToString(mUrlOrSizes
);
122 aCrossOrigin
.ToString(mCrossOrigin
);
123 aMedia
.ToString(mMedia
);
125 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
126 aReferrerPolicy
.ToString(referrerPolicy
);
127 mReferrerPolicyOrIntegrity
.Assign(
128 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
131 // This method can be only be triggered by <link rel=preload type=fetch>,
132 // hence this operation is always a preload.
133 mIsLinkPreload
= true;
136 // <picture> elements have multiple <source> nodes followed by an <img>,
137 // where we use the first valid source, which may be the img. Because we
138 // can't determine validity at this point without parsing CSS and getting
139 // main thread state, we push preload operations for picture pushed and
140 // popped, so that the target of the preload ops can determine what picture
141 // and nesting level each source/img from the main preloading code exists
143 inline void InitOpenPicture() {
144 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
145 "Trying to reinitialize a speculative load!");
146 mOpCode
= eSpeculativeLoadOpenPicture
;
149 inline void InitEndPicture() {
150 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
151 "Trying to reinitialize a speculative load!");
152 mOpCode
= eSpeculativeLoadEndPicture
;
155 inline void InitPictureSource(nsHtml5String aSrcset
, nsHtml5String aSizes
,
156 nsHtml5String aType
, nsHtml5String aMedia
) {
157 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
158 "Trying to reinitialize a speculative load!");
159 mOpCode
= eSpeculativeLoadPictureSource
;
160 aSrcset
.ToString(mCharsetOrSrcset
);
161 aSizes
.ToString(mUrlOrSizes
);
163 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
);
164 aMedia
.ToString(mMedia
);
167 inline void InitScript(nsHtml5String aUrl
, nsHtml5String aCharset
,
168 nsHtml5String aType
, nsHtml5String aCrossOrigin
,
169 nsHtml5String aMedia
, nsHtml5String aIntegrity
,
170 nsHtml5String aReferrerPolicy
, bool aParserInHead
,
171 bool aAsync
, bool aDefer
, bool aNoModule
,
173 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
174 "Trying to reinitialize a speculative load!");
176 mOpCode
= aParserInHead
? eSpeculativeLoadNoModuleScriptFromHead
177 : eSpeculativeLoadNoModuleScript
;
179 mOpCode
= aParserInHead
? eSpeculativeLoadScriptFromHead
180 : eSpeculativeLoadScript
;
182 aUrl
.ToString(mUrlOrSizes
);
183 aCharset
.ToString(mCharsetOrSrcset
);
185 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
);
186 aCrossOrigin
.ToString(mCrossOrigin
);
187 aMedia
.ToString(mMedia
);
188 aIntegrity
.ToString(mReferrerPolicyOrIntegrity
);
189 nsAutoString referrerPolicy
;
190 aReferrerPolicy
.ToString(referrerPolicy
);
192 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
194 mScriptReferrerPolicy
=
195 mozilla::dom::ReferrerInfo::ReferrerPolicyAttributeFromString(
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 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
.SetIsVoid(
216 inline void InitStyle(nsHtml5String aUrl
, nsHtml5String aCharset
,
217 nsHtml5String aCrossOrigin
, nsHtml5String aMedia
,
218 nsHtml5String aReferrerPolicy
, nsHtml5String aIntegrity
,
220 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
221 "Trying to reinitialize a speculative load!");
222 mOpCode
= eSpeculativeLoadStyle
;
223 aUrl
.ToString(mUrlOrSizes
);
224 aCharset
.ToString(mCharsetOrSrcset
);
225 aCrossOrigin
.ToString(mCrossOrigin
);
226 aMedia
.ToString(mMedia
);
228 referrerPolicy
; // Not Auto, because using it to hold nsStringBuffer*
229 aReferrerPolicy
.ToString(referrerPolicy
);
230 mReferrerPolicyOrIntegrity
.Assign(
231 nsContentUtils::TrimWhitespace
<nsContentUtils::IsHTMLWhitespace
>(
234 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
);
235 mIsLinkPreload
= aLinkPreload
;
239 * "Speculative" manifest loads aren't truly speculative--if a manifest
240 * gets loaded, we are committed to it. There can never be a <script>
241 * before the manifest, so the situation of having to undo a manifest due
242 * to document.write() never arises. The reason why a parser
243 * thread-discovered manifest gets loaded via the speculative load queue
244 * as opposed to tree operation queue is that the manifest must get
245 * processed before any actual speculative loads such as scripts. Thus,
246 * manifests seen by the parser thread have to maintain the queue order
247 * relative to true speculative loads. See bug 541079.
249 inline void InitManifest(nsHtml5String aUrl
) {
250 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
251 "Trying to reinitialize a speculative load!");
252 mOpCode
= eSpeculativeLoadManifest
;
253 aUrl
.ToString(mUrlOrSizes
);
257 * "Speculative" charset setting isn't truly speculative. If the charset
258 * is set via this operation, we are committed to it unless chardet or
259 * a late meta cause a reload. The reason why a parser
260 * thread-discovered charset gets communicated via the speculative load
261 * queue as opposed to tree operation queue is that the charset change
262 * must get processed before any actual speculative loads such as style
263 * sheets. Thus, encoding decisions by the parser thread have to maintain
264 * the queue order relative to true speculative loads. See bug 675499.
266 inline void InitSetDocumentCharset(NotNull
<const Encoding
*> aEncoding
,
267 int32_t aCharsetSource
) {
268 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
269 "Trying to reinitialize a speculative load!");
270 mOpCode
= eSpeculativeLoadSetDocumentCharset
;
271 mCharsetOrSrcset
.~nsString();
272 mEncoding
= aEncoding
;
273 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
.Assign(
274 (char16_t
)aCharsetSource
);
278 * Speculative document mode setting isn't really speculative. Once it
279 * happens, we are committed to it. However, this information needs to
280 * travel in the speculation queue in order to have this information
281 * available before parsing the speculatively loaded style sheets.
283 inline void InitSetDocumentMode(nsHtml5DocumentMode aMode
) {
284 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
285 "Trying to reinitialize a speculative load!");
286 mOpCode
= eSpeculativeLoadSetDocumentMode
;
287 mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
.Assign(
291 inline void InitPreconnect(nsHtml5String aUrl
, nsHtml5String aCrossOrigin
) {
292 MOZ_ASSERT(mOpCode
== eSpeculativeLoadUninitialized
,
293 "Trying to reinitialize a speculative load!");
294 mOpCode
= eSpeculativeLoadPreconnect
;
295 aUrl
.ToString(mUrlOrSizes
);
296 aCrossOrigin
.ToString(mCrossOrigin
);
299 void Perform(nsHtml5TreeOpExecutor
* aExecutor
);
302 nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad
&) = delete;
303 nsHtml5SpeculativeLoad
& operator=(const nsHtml5SpeculativeLoad
&) = delete;
305 eHtml5SpeculativeLoad mOpCode
;
308 * Whether the refering element has async and/or defer attributes.
314 * True if and only if this is a speculative load initiated by <link
315 * rel="preload"> tag encounter. Passed to the handling loader as an
316 * indication to raise the priority.
320 /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the
321 * "sizes" attribute. If the attribute is not set, this will be a void
322 * string. Otherwise it empty or the value of the url.
324 nsString mUrlOrSizes
;
326 * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the
327 * "integrity" attribute. If the attribute is not set, this will be a void
328 * string. Otherwise it is empty or the value of the referrer policy.
330 nsString mReferrerPolicyOrIntegrity
;
332 * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead]
333 * then this is the value of the "charset" attribute. For
334 * eSpeculativeLoadSetDocumentCharset it is the charset that the
335 * document's charset is being set to. If mOpCode is eSpeculativeLoadImage
336 * or eSpeculativeLoadPictureSource, this is the value of the "srcset"
337 * attribute. If the attribute is not set, this will be a void string.
338 * Otherwise it's empty.
341 nsString mCharsetOrSrcset
;
342 const Encoding
* mEncoding
;
345 * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a
346 * one-character string whose single character's code point is to be
347 * interpreted as a charset source integer. If mOpCode is
348 * eSpeculativeLoadSetDocumentMode, this is a one-character string whose
349 * single character's code point is to be interpreted as an
350 * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta
351 * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the
352 * value of the "sizes" attribute. If the attribute is not set, this will
353 * be a void string. If mOpCode is eSpeculativeLoadStyle, this
354 * is the value of the "integrity" attribute. If the attribute is not set,
355 * this will be a void string. Otherwise it is empty or the value of the
356 * referrer policy. Otherwise, it is empty or the value of the type attribute.
358 nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity
;
360 * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead]
361 * or eSpeculativeLoadPreconnect or eSpeculativeLoadStyle this is the value of
362 * the "crossorigin" attribute. If the attribute is not set, this will be a
365 nsString mCrossOrigin
;
367 * If mOpCode is eSpeculativeLoadPictureSource or eSpeculativeLoadStyle or
368 * Fetch or Image or Media or Script this is the value of the relevant "media"
369 * attribute of the <link rel="preload"> or <link rel="stylesheet">. If the
370 * attribute is not set, or the preload didn't originate from a <link>, this
371 * will be a void string.
375 * If mOpCode is eSpeculativeLoadScript[FromHead] this represents the value
376 * of the "referrerpolicy" attribute. This field holds one of the values
377 * (REFERRER_POLICY_*) defined in nsIHttpChannel.
379 mozilla::dom::ReferrerPolicy mScriptReferrerPolicy
;
382 #endif // nsHtml5SpeculativeLoad_h