1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /*
8  * A class that handles loading and evaluation of <script> elements.
9  */
10 
11 #ifndef mozilla_dom_ScriptLoadHandler_h
12 #define mozilla_dom_ScriptLoadHandler_h
13 
14 #include "nsIIncrementalStreamLoader.h"
15 #include "nsISupports.h"
16 #include "mozilla/Maybe.h"
17 #include "mozilla/RefPtr.h"
18 #include "mozilla/UniquePtr.h"
19 
20 namespace JS::loader {
21 class ScriptLoadRequest;
22 }
23 
24 namespace mozilla {
25 
26 class Decoder;
27 
28 namespace dom {
29 
30 class ScriptLoader;
31 class SRICheckDataVerifier;
32 
33 class ScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver {
34  public:
35   explicit ScriptLoadHandler(
36       ScriptLoader* aScriptLoader, JS::loader::ScriptLoadRequest* aRequest,
37       UniquePtr<SRICheckDataVerifier>&& aSRIDataVerifier);
38 
39   NS_DECL_ISUPPORTS
40   NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
41 
42  private:
43   virtual ~ScriptLoadHandler();
44 
45   /*
46    * Decode the given data into the already-allocated internal
47    * |ScriptTextBuffer<Unit>|.
48    *
49    * This function is intended to be called only by |DecodeRawData| after
50    * determining which sort of |ScriptTextBuffer<Unit>| has been allocated.
51    */
52   template <typename Unit>
53   nsresult DecodeRawDataHelper(const uint8_t* aData, uint32_t aDataLength,
54                                bool aEndOfStream);
55 
56   /*
57    * Once the charset is found by the EnsureDecoder function, we can
58    * incrementally convert the charset to the one expected by the JS Parser.
59    */
60   nsresult DecodeRawData(const uint8_t* aData, uint32_t aDataLength,
61                          bool aEndOfStream);
62 
63   /*
64    * Discover the charset by looking at the stream data, the script tag, and
65    * other indicators.  Returns true if charset has been discovered.
66    */
EnsureDecoder(nsIIncrementalStreamLoader * aLoader,const uint8_t * aData,uint32_t aDataLength,bool aEndOfStream)67   bool EnsureDecoder(nsIIncrementalStreamLoader* aLoader, const uint8_t* aData,
68                      uint32_t aDataLength, bool aEndOfStream) {
69     // Check if the decoder has already been created.
70     if (mDecoder) {
71       return true;
72     }
73 
74     return TrySetDecoder(aLoader, aData, aDataLength, aEndOfStream);
75   }
76 
77   /*
78    * Attempt to determine how script data will be decoded, when such
79    * determination hasn't already been made.  (If you don't know whether it's
80    * been made yet, use |EnsureDecoder| above instead.)  Return false if there
81    * isn't enough information yet to make the determination, or true if a
82    * determination was made.
83    */
84   bool TrySetDecoder(nsIIncrementalStreamLoader* aLoader, const uint8_t* aData,
85                      uint32_t aDataLength, bool aEndOfStream);
86 
87   /*
88    * When streaming bytecode, we have the opportunity to fallback early if SRI
89    * does not match the expectation of the document.
90    *
91    * If SRI hash is decoded, `sriLength` is set to the length of the hash.
92    */
93   nsresult MaybeDecodeSRI(uint32_t* sriLength);
94 
95   // Query the channel to find the data type associated with the input stream.
96   nsresult EnsureKnownDataType(nsIIncrementalStreamLoader* aLoader);
97 
98   // ScriptLoader which will handle the parsed script.
99   RefPtr<ScriptLoader> mScriptLoader;
100 
101   // The ScriptLoadRequest for this load. Decoded data are accumulated on it.
102   RefPtr<JS::loader::ScriptLoadRequest> mRequest;
103 
104   // SRI data verifier.
105   UniquePtr<SRICheckDataVerifier> mSRIDataVerifier;
106 
107   // Status of SRI data operations.
108   nsresult mSRIStatus;
109 
110   // Unicode decoder for charset.
111   mozilla::UniquePtr<mozilla::Decoder> mDecoder;
112 
113   // Flipped to true after calling NotifyStart the first time
114   bool mPreloadStartNotified = false;
115 };
116 
117 }  // namespace dom
118 }  // namespace mozilla
119 
120 #endif  // mozilla_dom_ScriptLoadHandler_h
121