| 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 | 
|---|