/src/mozilla-central/parser/html/nsHtml5SpeculativeLoad.h
Line | Count | Source (jump to first uncovered line) |
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/. */ |
4 | | |
5 | | #ifndef nsHtml5SpeculativeLoad_h |
6 | | #define nsHtml5SpeculativeLoad_h |
7 | | |
8 | | #include "nsString.h" |
9 | | #include "nsContentUtils.h" |
10 | | #include "nsHtml5DocumentMode.h" |
11 | | #include "nsHtml5String.h" |
12 | | |
13 | | class nsHtml5TreeOpExecutor; |
14 | | |
15 | | enum eHtml5SpeculativeLoad |
16 | | { |
17 | | eSpeculativeLoadUninitialized, |
18 | | eSpeculativeLoadBase, |
19 | | eSpeculativeLoadCSP, |
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 |
34 | | }; |
35 | | |
36 | | class nsHtml5SpeculativeLoad |
37 | | { |
38 | | using Encoding = mozilla::Encoding; |
39 | | template<typename T> |
40 | | using NotNull = mozilla::NotNull<T>; |
41 | | |
42 | | public: |
43 | | nsHtml5SpeculativeLoad(); |
44 | | ~nsHtml5SpeculativeLoad(); |
45 | | |
46 | | inline void InitBase(nsHtml5String aUrl) |
47 | 0 | { |
48 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
49 | 0 | "Trying to reinitialize a speculative load!"); |
50 | 0 | mOpCode = eSpeculativeLoadBase; |
51 | 0 | aUrl.ToString(mUrlOrSizes); |
52 | 0 | } |
53 | | |
54 | | inline void InitMetaCSP(nsHtml5String aCSP) |
55 | 0 | { |
56 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
57 | 0 | "Trying to reinitialize a speculative load!"); |
58 | 0 | mOpCode = eSpeculativeLoadCSP; |
59 | 0 | nsString csp; // Not Auto, because using it to hold nsStringBuffer* |
60 | 0 | aCSP.ToString(csp); |
61 | 0 | mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign( |
62 | 0 | nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>(csp)); |
63 | 0 | } |
64 | | |
65 | | inline void InitMetaReferrerPolicy(nsHtml5String aReferrerPolicy) |
66 | 0 | { |
67 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
68 | 0 | "Trying to reinitialize a speculative load!"); |
69 | 0 | mOpCode = eSpeculativeLoadMetaReferrer; |
70 | 0 | nsString |
71 | 0 | referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* |
72 | 0 | aReferrerPolicy.ToString(referrerPolicy); |
73 | 0 | mReferrerPolicyOrIntegrity.Assign( |
74 | 0 | nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( |
75 | 0 | referrerPolicy)); |
76 | 0 | } |
77 | | |
78 | | inline void InitImage(nsHtml5String aUrl, |
79 | | nsHtml5String aCrossOrigin, |
80 | | nsHtml5String aReferrerPolicy, |
81 | | nsHtml5String aSrcset, |
82 | | nsHtml5String aSizes) |
83 | 0 | { |
84 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
85 | 0 | "Trying to reinitialize a speculative load!"); |
86 | 0 | mOpCode = eSpeculativeLoadImage; |
87 | 0 | aUrl.ToString(mUrlOrSizes); |
88 | 0 | aCrossOrigin.ToString(mCrossOriginOrMedia); |
89 | 0 | nsString |
90 | 0 | referrerPolicy; // Not Auto, because using it to hold nsStringBuffer* |
91 | 0 | aReferrerPolicy.ToString(referrerPolicy); |
92 | 0 | mReferrerPolicyOrIntegrity.Assign( |
93 | 0 | nsContentUtils::TrimWhitespace<nsContentUtils::IsHTMLWhitespace>( |
94 | 0 | referrerPolicy)); |
95 | 0 | aSrcset.ToString(mCharsetOrSrcset); |
96 | 0 | aSizes.ToString( |
97 | 0 | mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); |
98 | 0 | } |
99 | | |
100 | | // <picture> elements have multiple <source> nodes followed by an <img>, |
101 | | // where we use the first valid source, which may be the img. Because we |
102 | | // can't determine validity at this point without parsing CSS and getting |
103 | | // main thread state, we push preload operations for picture pushed and |
104 | | // popped, so that the target of the preload ops can determine what picture |
105 | | // and nesting level each source/img from the main preloading code exists |
106 | | // at. |
107 | | inline void InitOpenPicture() |
108 | 0 | { |
109 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
110 | 0 | "Trying to reinitialize a speculative load!"); |
111 | 0 | mOpCode = eSpeculativeLoadOpenPicture; |
112 | 0 | } |
113 | | |
114 | | inline void InitEndPicture() |
115 | 0 | { |
116 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
117 | 0 | "Trying to reinitialize a speculative load!"); |
118 | 0 | mOpCode = eSpeculativeLoadEndPicture; |
119 | 0 | } |
120 | | |
121 | | inline void InitPictureSource(nsHtml5String aSrcset, |
122 | | nsHtml5String aSizes, |
123 | | nsHtml5String aType, |
124 | | nsHtml5String aMedia) |
125 | 0 | { |
126 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
127 | 0 | "Trying to reinitialize a speculative load!"); |
128 | 0 | mOpCode = eSpeculativeLoadPictureSource; |
129 | 0 | aSrcset.ToString(mCharsetOrSrcset); |
130 | 0 | aSizes.ToString(mUrlOrSizes); |
131 | 0 | aType.ToString( |
132 | 0 | mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); |
133 | 0 | aMedia.ToString(mCrossOriginOrMedia); |
134 | 0 | } |
135 | | |
136 | | inline void InitScript(nsHtml5String aUrl, |
137 | | nsHtml5String aCharset, |
138 | | nsHtml5String aType, |
139 | | nsHtml5String aCrossOrigin, |
140 | | nsHtml5String aIntegrity, |
141 | | bool aParserInHead, |
142 | | bool aAsync, |
143 | | bool aDefer, |
144 | | bool aNoModule) |
145 | 0 | { |
146 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
147 | 0 | "Trying to reinitialize a speculative load!"); |
148 | 0 | if (aNoModule) { |
149 | 0 | mOpCode = aParserInHead ? eSpeculativeLoadNoModuleScriptFromHead |
150 | 0 | : eSpeculativeLoadNoModuleScript; |
151 | 0 | } else { |
152 | 0 | mOpCode = |
153 | 0 | aParserInHead ? eSpeculativeLoadScriptFromHead : eSpeculativeLoadScript; |
154 | 0 | } |
155 | 0 | aUrl.ToString(mUrlOrSizes); |
156 | 0 | aCharset.ToString(mCharsetOrSrcset); |
157 | 0 | aType.ToString( |
158 | 0 | mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); |
159 | 0 | aCrossOrigin.ToString(mCrossOriginOrMedia); |
160 | 0 | aIntegrity.ToString(mReferrerPolicyOrIntegrity); |
161 | 0 | mIsAsync = aAsync; |
162 | 0 | mIsDefer = aDefer; |
163 | 0 | } |
164 | | |
165 | | inline void InitStyle(nsHtml5String aUrl, |
166 | | nsHtml5String aCharset, |
167 | | nsHtml5String aCrossOrigin, |
168 | | nsHtml5String aReferrerPolicy, |
169 | | nsHtml5String aIntegrity) |
170 | 0 | { |
171 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
172 | 0 | "Trying to reinitialize a speculative load!"); |
173 | 0 | mOpCode = eSpeculativeLoadStyle; |
174 | 0 | aUrl.ToString(mUrlOrSizes); |
175 | 0 | aCharset.ToString(mCharsetOrSrcset); |
176 | 0 | aCrossOrigin.ToString(mCrossOriginOrMedia); |
177 | 0 | aReferrerPolicy.ToString(mReferrerPolicyOrIntegrity); |
178 | 0 | aIntegrity.ToString( |
179 | 0 | mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity); |
180 | 0 | } |
181 | | |
182 | | /** |
183 | | * "Speculative" manifest loads aren't truly speculative--if a manifest |
184 | | * gets loaded, we are committed to it. There can never be a <script> |
185 | | * before the manifest, so the situation of having to undo a manifest due |
186 | | * to document.write() never arises. The reason why a parser |
187 | | * thread-discovered manifest gets loaded via the speculative load queue |
188 | | * as opposed to tree operation queue is that the manifest must get |
189 | | * processed before any actual speculative loads such as scripts. Thus, |
190 | | * manifests seen by the parser thread have to maintain the queue order |
191 | | * relative to true speculative loads. See bug 541079. |
192 | | */ |
193 | | inline void InitManifest(nsHtml5String aUrl) |
194 | 0 | { |
195 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
196 | 0 | "Trying to reinitialize a speculative load!"); |
197 | 0 | mOpCode = eSpeculativeLoadManifest; |
198 | 0 | aUrl.ToString(mUrlOrSizes); |
199 | 0 | } |
200 | | |
201 | | /** |
202 | | * "Speculative" charset setting isn't truly speculative. If the charset |
203 | | * is set via this operation, we are committed to it unless chardet or |
204 | | * a late meta cause a reload. The reason why a parser |
205 | | * thread-discovered charset gets communicated via the speculative load |
206 | | * queue as opposed to tree operation queue is that the charset change |
207 | | * must get processed before any actual speculative loads such as style |
208 | | * sheets. Thus, encoding decisions by the parser thread have to maintain |
209 | | * the queue order relative to true speculative loads. See bug 675499. |
210 | | */ |
211 | | inline void InitSetDocumentCharset(NotNull<const Encoding*> aEncoding, |
212 | | int32_t aCharsetSource) |
213 | 0 | { |
214 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
215 | 0 | "Trying to reinitialize a speculative load!"); |
216 | 0 | mOpCode = eSpeculativeLoadSetDocumentCharset; |
217 | 0 | mCharsetOrSrcset.~nsString(); |
218 | 0 | mEncoding = aEncoding; |
219 | 0 | mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign( |
220 | 0 | (char16_t)aCharsetSource); |
221 | 0 | } |
222 | | |
223 | | /** |
224 | | * Speculative document mode setting isn't really speculative. Once it |
225 | | * happens, we are committed to it. However, this information needs to |
226 | | * travel in the speculation queue in order to have this information |
227 | | * available before parsing the speculatively loaded style sheets. |
228 | | */ |
229 | | inline void InitSetDocumentMode(nsHtml5DocumentMode aMode) |
230 | 0 | { |
231 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
232 | 0 | "Trying to reinitialize a speculative load!"); |
233 | 0 | mOpCode = eSpeculativeLoadSetDocumentMode; |
234 | 0 | mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity.Assign( |
235 | 0 | (char16_t)aMode); |
236 | 0 | } |
237 | | |
238 | | inline void InitPreconnect(nsHtml5String aUrl, nsHtml5String aCrossOrigin) |
239 | 0 | { |
240 | 0 | MOZ_ASSERT(mOpCode == eSpeculativeLoadUninitialized, |
241 | 0 | "Trying to reinitialize a speculative load!"); |
242 | 0 | mOpCode = eSpeculativeLoadPreconnect; |
243 | 0 | aUrl.ToString(mUrlOrSizes); |
244 | 0 | aCrossOrigin.ToString(mCrossOriginOrMedia); |
245 | 0 | } |
246 | | |
247 | | void Perform(nsHtml5TreeOpExecutor* aExecutor); |
248 | | |
249 | | private: |
250 | | nsHtml5SpeculativeLoad(const nsHtml5SpeculativeLoad&) = delete; |
251 | | nsHtml5SpeculativeLoad& operator=(const nsHtml5SpeculativeLoad&) = delete; |
252 | | |
253 | | eHtml5SpeculativeLoad mOpCode; |
254 | | |
255 | | /** |
256 | | * Whether the refering element has async and/or defer attributes. |
257 | | */ |
258 | | bool mIsAsync; |
259 | | bool mIsDefer; |
260 | | |
261 | | /* If mOpCode is eSpeculativeLoadPictureSource, this is the value of the |
262 | | * "sizes" attribute. If the attribute is not set, this will be a void |
263 | | * string. Otherwise it empty or the value of the url. |
264 | | */ |
265 | | nsString mUrlOrSizes; |
266 | | /** |
267 | | * If mOpCode is eSpeculativeLoadScript[FromHead], this is the value of the |
268 | | * "integrity" attribute. If the attribute is not set, this will be a void |
269 | | * string. Otherwise it is empty or the value of the referrer policy. |
270 | | */ |
271 | | nsString mReferrerPolicyOrIntegrity; |
272 | | /** |
273 | | * If mOpCode is eSpeculativeLoadStyle or eSpeculativeLoadScript[FromHead] |
274 | | * then this is the value of the "charset" attribute. For |
275 | | * eSpeculativeLoadSetDocumentCharset it is the charset that the |
276 | | * document's charset is being set to. If mOpCode is eSpeculativeLoadImage |
277 | | * or eSpeculativeLoadPictureSource, this is the value of the "srcset" |
278 | | * attribute. If the attribute is not set, this will be a void string. |
279 | | * Otherwise it's empty. |
280 | | */ |
281 | | union { |
282 | | nsString mCharsetOrSrcset; |
283 | | const Encoding* mEncoding; |
284 | | }; |
285 | | /** |
286 | | * If mOpCode is eSpeculativeLoadSetDocumentCharset, this is a |
287 | | * one-character string whose single character's code point is to be |
288 | | * interpreted as a charset source integer. If mOpCode is |
289 | | * eSpeculativeLoadSetDocumentMode, this is a one-character string whose |
290 | | * single character's code point is to be interpreted as an |
291 | | * nsHtml5DocumentMode. If mOpCode is eSpeculativeLoadCSP, this is a meta |
292 | | * element's CSP value. If mOpCode is eSpeculativeLoadImage, this is the |
293 | | * value of the "sizes" attribute. If the attribute is not set, this will |
294 | | * be a void string. If mOpCode is eSpeculativeLoadStyle, this |
295 | | * is the value of the "integrity" attribute. If the attribute is not set, |
296 | | * this will be a void string. Otherwise it is empty or the value of the |
297 | | * referrer policy. Otherwise, it is empty or the value of the type attribute. |
298 | | */ |
299 | | nsString mTypeOrCharsetSourceOrDocumentModeOrMetaCSPOrSizesOrIntegrity; |
300 | | /** |
301 | | * If mOpCode is eSpeculativeLoadImage or eSpeculativeLoadScript[FromHead] |
302 | | * or eSpeculativeLoadPreconnect this is the value of the "crossorigin" |
303 | | * attribute. If the attribute is not set, this will be a void string. |
304 | | * If mOpCode is eSpeculativeLoadPictureSource, this is the value of the |
305 | | * "media" attribute. If the attribute is not set, this will be a void |
306 | | * string. |
307 | | */ |
308 | | nsString mCrossOriginOrMedia; |
309 | | }; |
310 | | |
311 | | #endif // nsHtml5SpeculativeLoad_h |