1 /*
2  * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20 
21 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_LOADER_H_
22 #define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_LOADER_H_
23 
24 #include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h"
25 #include "third_party/blink/public/platform/web_url_request.h"
26 #include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h"
27 #include "third_party/blink/renderer/core/core_export.h"
28 #include "third_party/blink/renderer/core/html/cross_origin_attribute.h"
29 #include "third_party/blink/renderer/core/script/pending_script.h"
30 #include "third_party/blink/renderer/core/script/script.h"
31 #include "third_party/blink/renderer/core/script/script_runner.h"
32 #include "third_party/blink/renderer/core/script/script_scheduling_type.h"
33 #include "third_party/blink/renderer/platform/bindings/name_client.h"
34 #include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
35 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
36 #include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
37 #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
38 #include "third_party/blink/renderer/platform/wtf/text/text_position.h"
39 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
40 
41 namespace blink {
42 
43 class Resource;
44 class ResourceFetcher;
45 class ScriptElementBase;
46 class Script;
47 class ScriptResource;
48 class Modulator;
49 
50 class CORE_EXPORT ScriptLoader final : public GarbageCollected<ScriptLoader>,
51                                        public PendingScriptClient,
52                                        public NameClient {
53  public:
54   ScriptLoader(ScriptElementBase*, const CreateElementFlags);
55   ~ScriptLoader() override;
56   void Trace(Visitor*) const override;
NameInHeapSnapshot()57   const char* NameInHeapSnapshot() const override { return "ScriptLoader"; }
58 
59   enum LegacyTypeSupport {
60     kDisallowLegacyTypeInTypeAttribute,
61     kAllowLegacyTypeInTypeAttribute
62   };
63 
64   // |out_is_import_map| is set separately from |out_script_type| in order
65   // to avoid adding import maps as a mojom::blink::ScriptType enum, because
66   // import maps are processed quite differently from classic/module scripts.
67   //
68   // TODO(hiroshige, kouhei): Make the method signature simpler.
69   static bool IsValidScriptTypeAndLanguage(
70       const String& type_attribute_value,
71       const String& language_attribute_value,
72       LegacyTypeSupport support_legacy_types,
73       mojom::blink::ScriptType* out_script_type = nullptr,
74       bool* out_is_import_map = nullptr);
75 
76   static bool BlockForNoModule(mojom::blink::ScriptType, bool nomodule);
77 
78   static network::mojom::CredentialsMode ModuleScriptCredentialsMode(
79       CrossOriginAttributeValue);
80 
81   // https://html.spec.whatwg.org/C/#prepare-a-script
82   bool PrepareScript(const TextPosition& script_start_position =
83                          TextPosition::MinimumPosition(),
84                      LegacyTypeSupport = kDisallowLegacyTypeInTypeAttribute);
85 
86   // Gets a PendingScript for external script whose fetch is started in
87   // FetchClassicScript()/FetchModuleScriptTree().
88   // This should be called only once.
89   PendingScript* TakePendingScript(ScriptSchedulingType);
90 
WillBeParserExecuted()91   bool WillBeParserExecuted() const { return will_be_parser_executed_; }
ReadyToBeParserExecuted()92   bool ReadyToBeParserExecuted() const { return ready_to_be_parser_executed_; }
WillExecuteWhenDocumentFinishedParsing()93   bool WillExecuteWhenDocumentFinishedParsing() const {
94     return will_execute_when_document_finished_parsing_;
95   }
IsForceDeferred()96   bool IsForceDeferred() const { return force_deferred_; }
IsParserInserted()97   bool IsParserInserted() const { return parser_inserted_; }
AlreadyStarted()98   bool AlreadyStarted() const { return already_started_; }
IsNonBlocking()99   bool IsNonBlocking() const { return non_blocking_; }
GetScriptType()100   mojom::blink::ScriptType GetScriptType() const { return script_type_; }
101 
102   // Helper functions used by our parent classes.
103   void DidNotifySubtreeInsertionsToDocument();
104   void ChildrenChanged();
105   void HandleSourceAttribute(const String& source_url);
106   void HandleAsyncAttribute();
107 
108   void SetFetchDocWrittenScriptDeferIdle();
109 
110   // Return non-null if controlled by ScriptRunner, or null otherwise.
111   // Only for ScriptRunner::MovePendingScript() and should be removed once
112   // crbug.com/721914 is fixed.
113   PendingScript* GetPendingScriptIfControlledByScriptRunnerForCrossDocMove();
114 
115  private:
116   bool IgnoresLoadRequest() const;
117   bool IsScriptForEventSupported() const;
118 
119   // FetchClassicScript corresponds to Step 21.6 of
120   // https://html.spec.whatwg.org/C/#prepare-a-script
121   // and must NOT be called from outside of PendingScript().
122   //
123   // https://html.spec.whatwg.org/C/#fetch-a-classic-script
124   void FetchClassicScript(const KURL&,
125                           Document&,
126                           const ScriptFetchOptions&,
127                           CrossOriginAttributeValue,
128                           const WTF::TextEncoding&);
129   // https://html.spec.whatwg.org/C/#fetch-a-module-script-tree
130   void FetchModuleScriptTree(const KURL&,
131                              ResourceFetcher*,
132                              Modulator*,
133                              const ScriptFetchOptions&);
134 
135   // Clears the connection to the PendingScript.
136   void DetachPendingScript();
137 
138   // PendingScriptClient
139   void PendingScriptFinished(PendingScript*) override;
140 
141   // Get the effective script text (after Trusted Types checking).
142   String GetScriptText() const;
143 
144   Member<ScriptElementBase> element_;
145 
146   // https://html.spec.whatwg.org/C/#script-processing-model
147   // "A script element has several associated pieces of state.":
148 
149   // <spec href="https://html.spec.whatwg.org/C/#already-started">... Initially,
150   // script elements must have this flag unset ...</spec>
151   bool already_started_ = false;
152 
153   // <spec href="https://html.spec.whatwg.org/C/#parser-document">... Initially,
154   // its value must be null. It is set by the HTML parser and the XML parser on
155   // script elements they insert ...</spec>
156   // We use a WeakMember here because we're keeping the parser-inserted
157   // information separately from the parser document, so ScriptLoader doesn't
158   // need to keep the parser document alive.
159   WeakMember<Document> parser_document_;
160 
161   // <spec href="https://html.spec.whatwg.org/C/#parser-inserted">script
162   // elements with non-null parser documents are known as
163   // "parser-inserted".</spec>
164   // Note that we don't actually implement "parser inserted" in terms of a
165   // non-null |parser_document_| like the spec, because it is possible for
166   // |CreateElementFlags::created_by_parser_| to be true even when
167   // |CreateElementFlags::parser_document_| is null. Therefore, we have to
168   // store this information separately.
169   bool parser_inserted_ = false;
170 
171   // <spec href="https://html.spec.whatwg.org/C/#non-blocking">... Initially,
172   // script elements must have this flag set. ...</spec>
173   bool non_blocking_ = true;
174 
175   // <spec href="https://html.spec.whatwg.org/C/#ready-to-be-parser-executed">
176   // ... Initially, script elements must have this flag unset ...</spec>
177   bool ready_to_be_parser_executed_ = false;
178 
179   // <spec href="https://html.spec.whatwg.org/C/#concept-script-type">... It is
180   // determined when the script is prepared, ...</spec>
181   mojom::blink::ScriptType script_type_ = mojom::blink::ScriptType::kClassic;
182 
183   // <spec href="https://html.spec.whatwg.org/C/#concept-script-external">
184   // ... It is determined when the script is prepared, ...</spec>
185   bool is_external_script_ = false;
186 
187   // Same as "The parser will handle executing the script."
188   bool will_be_parser_executed_;
189 
190   bool will_execute_when_document_finished_parsing_;
191 
192   // The script will be force deferred (https://crbug.com/976061).
193   bool force_deferred_;
194 
195   // A PendingScript is first created in PrepareScript() and stored in
196   // |prepared_pending_script_|.
197   // Later, TakePendingScript() is called, and its caller holds a reference
198   // to the PendingScript instead and |prepared_pending_script_| is cleared.
199   Member<PendingScript> prepared_pending_script_;
200 
201   // If the script is controlled by ScriptRunner, then
202   // ScriptLoader::pending_script_ holds a reference to the PendingScript and
203   // ScriptLoader is its client.
204   // Otherwise, HTMLParserScriptRunner or XMLParserScriptRunner holds the
205   // reference and |pending_script_| here is null.
206   Member<PendingScript> pending_script_;
207 
208   // This is used only to keep the ScriptResource of a classic script alive
209   // and thus to keep it on MemoryCache, even after script execution, as long
210   // as ScriptLoader is alive. crbug.com/778799
211   Member<Resource> resource_keep_alive_;
212 };
213 
214 }  // namespace blink
215 
216 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_LOADER_H_
217