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 mozilla {
21 
22 class Decoder;
23 
24 namespace dom {
25 
26 class ScriptLoadRequest;
27 class ScriptLoader;
28 class SRICheckDataVerifier;
29 
30 class ScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver {
31  public:
32   explicit ScriptLoadHandler(
33       ScriptLoader* aScriptLoader, ScriptLoadRequest* aRequest,
34       UniquePtr<SRICheckDataVerifier>&& aSRIDataVerifier);
35 
36   NS_DECL_ISUPPORTS
37   NS_DECL_NSIINCREMENTALSTREAMLOADEROBSERVER
38 
39  private:
40   virtual ~ScriptLoadHandler();
41 
42   /*
43    * Decode the given data into the already-allocated internal
44    * |ScriptTextBuffer<Unit>|.
45    *
46    * This function is intended to be called only by |DecodeRawData| after
47    * determining which sort of |ScriptTextBuffer<Unit>| has been allocated.
48    */
49   template <typename Unit>
50   nsresult DecodeRawDataHelper(const uint8_t* aData, uint32_t aDataLength,
51                                bool aEndOfStream);
52 
53   /*
54    * Once the charset is found by the EnsureDecoder function, we can
55    * incrementally convert the charset to the one expected by the JS Parser.
56    */
57   nsresult DecodeRawData(const uint8_t* aData, uint32_t aDataLength,
58                          bool aEndOfStream);
59 
60   /*
61    * Discover the charset by looking at the stream data, the script tag, and
62    * other indicators.  Returns true if charset has been discovered.
63    */
EnsureDecoder(nsIIncrementalStreamLoader * aLoader,const uint8_t * aData,uint32_t aDataLength,bool aEndOfStream)64   bool EnsureDecoder(nsIIncrementalStreamLoader* aLoader, const uint8_t* aData,
65                      uint32_t aDataLength, bool aEndOfStream) {
66     // Check if the decoder has already been created.
67     if (mDecoder) {
68       return true;
69     }
70 
71     return TrySetDecoder(aLoader, aData, aDataLength, aEndOfStream);
72   }
73 
74   /*
75    * Attempt to determine how script data will be decoded, when such
76    * determination hasn't already been made.  (If you don't know whether it's
77    * been made yet, use |EnsureDecoder| above instead.)  Return false if there
78    * isn't enough information yet to make the determination, or true if a
79    * determination was made.
80    */
81   bool TrySetDecoder(nsIIncrementalStreamLoader* aLoader, const uint8_t* aData,
82                      uint32_t aDataLength, bool aEndOfStream);
83 
84   /*
85    * When streaming bytecode, we have the opportunity to fallback early if SRI
86    * does not match the expectation of the document.
87    *
88    * If SRI hash is decoded, `sriLength` is set to the length of the hash.
89    */
90   nsresult MaybeDecodeSRI(uint32_t* sriLength);
91 
92   // Query the channel to find the data type associated with the input stream.
93   nsresult EnsureKnownDataType(nsIIncrementalStreamLoader* aLoader);
94 
95   // ScriptLoader which will handle the parsed script.
96   RefPtr<ScriptLoader> mScriptLoader;
97 
98   // The ScriptLoadRequest for this load. Decoded data are accumulated on it.
99   RefPtr<ScriptLoadRequest> mRequest;
100 
101   // SRI data verifier.
102   UniquePtr<SRICheckDataVerifier> mSRIDataVerifier;
103 
104   // Status of SRI data operations.
105   nsresult mSRIStatus;
106 
107   // Unicode decoder for charset.
108   mozilla::UniquePtr<mozilla::Decoder> mDecoder;
109 
110   // Flipped to true after calling NotifyStart the first time
111   bool mPreloadStartNotified = false;
112 };
113 
114 }  // namespace dom
115 }  // namespace mozilla
116 
117 #endif  // mozilla_dom_ScriptLoadHandler_h
118