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