OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/loader/modulescript/ModuleScriptLoader.h" | 5 #include "core/loader/modulescript/ModuleScriptLoader.h" |
6 | 6 |
7 #include "core/dom/ExecutionContext.h" | 7 #include "core/dom/ExecutionContext.h" |
8 #include "core/dom/Modulator.h" | 8 #include "core/dom/Modulator.h" |
9 #include "core/dom/ModuleScript.h" | 9 #include "core/dom/ModuleScript.h" |
10 #include "core/inspector/ConsoleMessage.h" | 10 #include "core/inspector/ConsoleMessage.h" |
11 #include "core/loader/modulescript/ModuleScriptLoaderClient.h" | 11 #include "core/loader/modulescript/ModuleScriptLoaderClient.h" |
12 #include "core/loader/modulescript/ModuleScriptLoaderRegistry.h" | 12 #include "core/loader/modulescript/ModuleScriptLoaderRegistry.h" |
13 #include "platform/loader/fetch/FetchUtils.h" | 13 #include "core/loader/modulescript/WorkletModuleScriptFetcher.h" |
14 #include "platform/loader/fetch/ResourceFetcher.h" | 14 #include "core/workers/MainThreadWorkletGlobalScope.h" |
| 15 #include "platform/loader/fetch/Resource.h" |
15 #include "platform/loader/fetch/ResourceLoaderOptions.h" | 16 #include "platform/loader/fetch/ResourceLoaderOptions.h" |
16 #include "platform/loader/fetch/ResourceLoadingLog.h" | 17 #include "platform/loader/fetch/ResourceLoadingLog.h" |
17 #include "platform/network/mime/MIMETypeRegistry.h" | |
18 #include "platform/weborigin/SecurityPolicy.h" | 18 #include "platform/weborigin/SecurityPolicy.h" |
19 #include "platform/wtf/text/AtomicString.h" | 19 #include "platform/wtf/text/AtomicString.h" |
20 | 20 |
21 namespace blink { | 21 namespace blink { |
22 | 22 |
23 ModuleScriptLoader::ModuleScriptLoader(Modulator* modulator, | 23 ModuleScriptLoader::ModuleScriptLoader(Modulator* modulator, |
24 ModuleScriptLoaderRegistry* registry, | 24 ModuleScriptLoaderRegistry* registry, |
25 ModuleScriptLoaderClient* client) | 25 ModuleScriptLoaderClient* client) |
26 : modulator_(modulator), registry_(registry), client_(client) { | 26 : modulator_(modulator), registry_(registry), client_(client) { |
27 DCHECK(modulator); | 27 DCHECK(modulator); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 #if DCHECK_IS_ON() | 62 #if DCHECK_IS_ON() |
63 RESOURCE_LOADING_DVLOG(1) | 63 RESOURCE_LOADING_DVLOG(1) |
64 << "ModuleLoader[" << url_.GetString() << "]::advanceState(" | 64 << "ModuleLoader[" << url_.GetString() << "]::advanceState(" |
65 << StateToString(state_) << " -> " << StateToString(new_state) << ")"; | 65 << StateToString(state_) << " -> " << StateToString(new_state) << ")"; |
66 #endif | 66 #endif |
67 state_ = new_state; | 67 state_ = new_state; |
68 | 68 |
69 if (state_ == State::kFinished) { | 69 if (state_ == State::kFinished) { |
70 registry_->ReleaseFinishedLoader(this); | 70 registry_->ReleaseFinishedLoader(this); |
71 client_->NotifyNewSingleModuleFinished(module_script_); | 71 client_->NotifyNewSingleModuleFinished(module_script_); |
72 SetResource(nullptr); | |
73 } | 72 } |
74 } | 73 } |
75 | 74 |
76 void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request, | 75 void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request, |
77 ResourceFetcher* fetcher, | 76 ResourceFetcher* fetcher, |
78 ModuleGraphLevel level) { | 77 ModuleGraphLevel level) { |
79 // https://html.spec.whatwg.org/#fetch-a-single-module-script | 78 // https://html.spec.whatwg.org/#fetch-a-single-module-script |
80 | 79 |
81 // Step 4. Set moduleMap[url] to "fetching". | 80 // Step 4. Set moduleMap[url] to "fetching". |
82 AdvanceState(State::kFetching); | 81 AdvanceState(State::kFetching); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 module_request.CredentialsMode()); | 126 module_request.CredentialsMode()); |
128 | 127 |
129 // Module scripts are always async. | 128 // Module scripts are always async. |
130 fetch_params.SetDefer(FetchParameters::kLazyLoad); | 129 fetch_params.SetDefer(FetchParameters::kLazyLoad); |
131 | 130 |
132 // Use UTF-8, according to Step 8: | 131 // Use UTF-8, according to Step 8: |
133 // "Let source text be the result of UTF-8 decoding response's body." | 132 // "Let source text be the result of UTF-8 decoding response's body." |
134 fetch_params.SetDecoderOptions( | 133 fetch_params.SetDecoderOptions( |
135 TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText()); | 134 TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText()); |
136 | 135 |
| 136 nonce_ = module_request.Nonce(); |
| 137 parser_state_ = module_request.ParserState(); |
| 138 |
137 // Step 6. If the caller specified custom steps to perform the fetch, | 139 // Step 6. If the caller specified custom steps to perform the fetch, |
138 // perform them on request, setting the is top-level flag if the top-level | 140 // perform them on request, setting the is top-level flag if the top-level |
139 // module fetch flag is set. Return from this algorithm, and when the custom | 141 // module fetch flag is set. Return from this algorithm, and when the custom |
140 // perform the fetch steps complete with response response, run the remaining | 142 // perform the fetch steps complete with response response, run the remaining |
141 // steps. | 143 // steps. |
142 // Otherwise, fetch request. Return from this algorithm, and run the remaining | 144 // Otherwise, fetch request. Return from this algorithm, and run the remaining |
143 // steps as part of the fetch's process response for the response response. | 145 // steps as part of the fetch's process response for the response response. |
144 // TODO(ServiceWorker team): Perform the "custom steps" for module usage | 146 ExecutionContext* execution_context = |
145 // inside service worker. | 147 ExecutionContext::From(modulator_->GetScriptState()); |
146 nonce_ = module_request.Nonce(); | 148 if (execution_context->IsMainThreadWorkletGlobalScope()) { |
147 parser_state_ = module_request.ParserState(); | 149 MainThreadWorkletGlobalScope* global_scope = |
148 | 150 ToMainThreadWorkletGlobalScope(execution_context); |
149 ScriptResource* resource = ScriptResource::Fetch(fetch_params, fetcher); | 151 module_fetcher_ = new WorkletModuleScriptFetcher( |
150 if (state_ == State::kFinished) { | 152 fetch_params, fetcher, modulator_, |
151 // ScriptResource::fetch() has succeeded synchronously, | 153 global_scope->GetModuleResponsesMapProxy()); |
152 // ::notifyFinished() already took care of the |resource|. | 154 } else { |
153 return; | 155 module_fetcher_ = |
| 156 new ModuleScriptFetcher(fetch_params, fetcher, modulator_); |
154 } | 157 } |
155 | 158 module_fetcher_->Fetch(this); |
156 if (!resource) { | |
157 // ScriptResource::fetch() has failed synchronously. | |
158 AdvanceState(State::kFinished); | |
159 return; | |
160 } | |
161 | |
162 // ScriptResource::fetch() is processed asynchronously. | |
163 SetResource(resource); | |
164 } | 159 } |
165 | 160 |
166 namespace { | 161 void ModuleScriptLoader::NotifyFetchFinished( |
167 | 162 WTF::Optional<ModuleScriptCreationParams> params) { |
168 bool WasModuleLoadSuccessful(Resource* resource, | |
169 ConsoleMessage** error_message = nullptr) { | |
170 // Implements conditions in Step 7 of | |
171 // https://html.spec.whatwg.org/#fetch-a-single-module-script | |
172 | |
173 // - response's type is "error" | |
174 if (resource->ErrorOccurred()) { | |
175 return false; | |
176 } | |
177 | |
178 const auto& response = resource->GetResponse(); | |
179 // - response's status is not an ok status | |
180 if (response.IsHTTP() && !FetchUtils::IsOkStatus(response.HttpStatusCode())) { | |
181 return false; | |
182 } | |
183 | |
184 // The result of extracting a MIME type from response's header list | |
185 // (ignoring parameters) is not a JavaScript MIME type | |
186 // Note: For historical reasons, fetching a classic script does not include | |
187 // MIME type checking. In contrast, module scripts will fail to load if they | |
188 // are not of a correct MIME type. | |
189 // We use ResourceResponse::httpContentType() instead of mimeType(), as | |
190 // mimeType() may be rewritten by mime sniffer. | |
191 if (!MIMETypeRegistry::IsSupportedJavaScriptMIMEType( | |
192 response.HttpContentType())) { | |
193 if (error_message) { | |
194 String message = | |
195 "Failed to load module script: The server responded with a " | |
196 "non-JavaScript MIME type of \"" + | |
197 response.HttpContentType() + | |
198 "\". Strict MIME type checking is enforced for module scripts per " | |
199 "HTML spec."; | |
200 *error_message = ConsoleMessage::CreateForRequest( | |
201 kJSMessageSource, kErrorMessageLevel, message, | |
202 response.Url().GetString(), resource->Identifier()); | |
203 } | |
204 return false; | |
205 } | |
206 | |
207 return true; | |
208 } | |
209 | |
210 } // namespace | |
211 | |
212 // ScriptResourceClient callback handler | |
213 void ModuleScriptLoader::NotifyFinished(Resource*) { | |
214 // Note: "conditions" referred in Step 7 is implemented in | 163 // Note: "conditions" referred in Step 7 is implemented in |
215 // wasModuleLoadSuccessful(). | 164 // wasModuleLoadSuccessful(). |
216 // Step 7. If any of the following conditions are met, set moduleMap[url] to | 165 // Step 7. If any of the following conditions are met, set moduleMap[url] to |
217 // null, asynchronously complete this algorithm with null, and abort these | 166 // null, asynchronously complete this algorithm with null, and abort these |
218 // steps. | 167 // steps. |
219 ConsoleMessage* error_message = nullptr; | 168 if (!params.has_value()) { |
220 if (!WasModuleLoadSuccessful(GetResource(), &error_message)) { | |
221 if (error_message) { | |
222 ExecutionContext::From(modulator_->GetScriptState()) | |
223 ->AddConsoleMessage(error_message); | |
224 } | |
225 | |
226 AdvanceState(State::kFinished); | 169 AdvanceState(State::kFinished); |
227 return; | 170 return; |
228 } | 171 } |
229 | 172 |
230 // Step 8. Let source text be the result of UTF-8 decoding response's body. | 173 // Step 8. Let source text be the result of UTF-8 decoding response's body. |
231 String source_text = GetResource()->SourceText(); | |
232 | |
233 AccessControlStatus access_control_status = | |
234 GetResource()->CalculateAccessControlStatus(); | |
235 | |
236 // Step 9. Let module script be the result of creating a module script given | 174 // Step 9. Let module script be the result of creating a module script given |
237 // source text, module map settings object, response's url, cryptographic | 175 // source text, module map settings object, response's url, cryptographic |
238 // nonce, parser state, and credentials mode. | 176 // nonce, parser state, and credentials mode. |
239 module_script_ = ModuleScript::Create( | 177 module_script_ = ModuleScript::Create( |
240 source_text, modulator_, GetResource()->GetResponse().Url(), nonce_, | 178 params->GetSourceText(), modulator_, params->GetResponseUrl(), nonce_, |
241 parser_state_, | 179 parser_state_, params->GetFetchCredentialsMode(), |
242 GetResource()->GetResourceRequest().GetFetchCredentialsMode(), | 180 params->GetAccessControlStatus()); |
243 access_control_status); | |
244 | 181 |
245 AdvanceState(State::kFinished); | 182 AdvanceState(State::kFinished); |
246 } | 183 } |
247 | 184 |
248 DEFINE_TRACE(ModuleScriptLoader) { | 185 DEFINE_TRACE(ModuleScriptLoader) { |
249 visitor->Trace(modulator_); | 186 visitor->Trace(modulator_); |
250 visitor->Trace(module_script_); | 187 visitor->Trace(module_script_); |
251 visitor->Trace(registry_); | 188 visitor->Trace(registry_); |
252 visitor->Trace(client_); | 189 visitor->Trace(client_); |
253 ResourceOwner<ScriptResource>::Trace(visitor); | 190 visitor->Trace(module_fetcher_); |
254 } | 191 } |
255 | 192 |
256 } // namespace blink | 193 } // namespace blink |
OLD | NEW |