Coverage Report

Created: 2018-09-25 14:53

/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