Chromium Code Reviews| Index: third_party/WebKit/Source/core/dom/ScriptLoader.cpp |
| diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp |
| index 77cc040f3400f0f5af8bc9f49e42ae0b41fe73e9..316051e3523c299f550f5ec3ded2c80df77478b4 100644 |
| --- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp |
| +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp |
| @@ -42,9 +42,9 @@ |
| #include "core/frame/LocalFrame.h" |
| #include "core/frame/SubresourceIntegrity.h" |
| #include "core/frame/csp/ContentSecurityPolicy.h" |
| -#include "core/html/CrossOriginAttribute.h" |
| #include "core/html/imports/HTMLImport.h" |
| #include "core/html/parser/HTMLParserIdioms.h" |
| +#include "core/loader/resource/ScriptResource.h" |
| #include "platform/WebFrameScheduler.h" |
| #include "platform/loader/fetch/AccessControlStatus.h" |
| #include "platform/loader/fetch/FetchParameters.h" |
| @@ -267,32 +267,108 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position, |
| if (!IsScriptForEventSupported()) |
| return false; |
| - // 14. "If the script element has a charset attribute, |
|
hiroshige
2017/04/14 00:13:29
Step 14 is moved below.
|
| - // then let encoding be the result of |
| - // getting an encoding from the value of the charset attribute." |
| - // "If the script element does not have a charset attribute, |
| - // or if getting an encoding failed, let encoding |
| - // be the same as the encoding of the script element's node document." |
| - // TODO(hiroshige): Should we handle failure in getting an encoding? |
| - String encoding; |
| - if (!element_->CharsetAttributeValue().IsEmpty()) |
| - encoding = element_->CharsetAttributeValue(); |
| - else |
| - encoding = element_document.characterSet(); |
| - |
| - // Steps 15--20 are handled in fetchScript(). |
| + // 14. is handled below. |
| + |
| + // 15. "Let CORS setting be the current state of the element's |
|
hiroshige
2017/04/14 00:13:29
Step 15 is moved from FetchScript().
|
| + // crossorigin content attribute." |
| + CrossOriginAttributeValue cross_origin = |
| + GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); |
| + |
| + // 16. will be handled below once module script support is implemented. |
| + |
| + // 17. "If the script element has a nonce attribute, |
|
hiroshige
2017/04/14 00:13:29
Step 17 is moved from FetchScript().
|
| + // then let cryptographic nonce be that attribute's value. |
| + // Otherwise, let cryptographic nonce be the empty string." |
| + String nonce; |
| + if (element_->IsNonceableElement()) |
| + nonce = element_->nonce(); |
| + |
| + // 18. is handled below. |
| + |
| + // 19. "Let parser state be "parser-inserted" |
|
hiroshige
2017/04/14 00:13:29
Step 19 is moved from FetchScript().
|
| + // if the script element has been flagged as "parser-inserted", |
| + // and "not parser-inserted" otherwise." |
| + ParserDisposition parser_state = |
| + IsParserInserted() ? kParserInserted : kNotParserInserted; |
| // 21. "If the element has a src content attribute, run these substeps:" |
| if (element_->HasSourceAttribute()) { |
| - FetchParameters::DeferOption defer = FetchParameters::kNoDefer; |
| - if (!parser_inserted_ || element_->AsyncAttributeValue() || |
| - element_->DeferAttributeValue()) |
| - defer = FetchParameters::kLazyLoad; |
| - if (document_write_intervention_ == |
| - DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) |
| - defer = FetchParameters::kIdleLoad; |
| - if (!FetchScript(element_->SourceAttributeValue(), encoding, defer)) |
| + // 21.1. Let src be the value of the element's src attribute. |
| + String src = |
| + StripLeadingAndTrailingHTMLSpaces(element_->SourceAttributeValue()); |
|
hiroshige
2017/04/14 00:13:29
Moved from Line 489.
|
| + |
| + // 21.2. "If src is the empty string, queue a task to |
|
hiroshige
2017/04/14 00:13:29
Moved from Line 579.
|
| + // fire an event named error at the element, and abort these steps." |
| + if (src.IsEmpty()) { |
| + // TODO(hiroshige): Make this asynchronous. Currently we fire the error |
| + // event synchronously to keep the existing behavior. |
| + DispatchErrorEvent(); |
| + return false; |
| + } |
| + |
| + // 21.3. "Set the element's from an external file flag." |
|
hiroshige
2017/04/14 00:13:29
21.3 is moved from FetchScript().
Actually in this
|
| + is_external_script_ = true; |
| + |
| + // 21.4. "Parse src relative to the element's node document." |
| + KURL url = element_document.CompleteURL(src); |
|
hiroshige
2017/04/14 00:13:29
This might cause slight behavior change: previousl
|
| + |
| + // 21.5. "If the previous step failed, queue a task to |
|
hiroshige
2017/04/14 00:13:29
Moved from Line 579.
|
| + // fire an event named error at the element, and abort these steps." |
| + if (!url.IsValid()) { |
| + // TODO(hiroshige): Make this asynchronous. Currently we fire the error |
| + // event synchronously to keep the existing behavior. |
| + DispatchErrorEvent(); |
| + return false; |
| + } |
| + |
| + DCHECK(!resource_); |
| + |
| + // 21.6. "Switch on the script's type:" |
| + // - "classic": |
| + |
| + // 14. "If the script element has a charset attribute, |
|
hiroshige
2017/04/14 00:13:29
Step 14 is moved from above.
|
| + // then let encoding be the result of |
| + // getting an encoding from the value of the charset attribute." |
| + // "If the script element does not have a charset attribute, |
| + // or if getting an encoding failed, let encoding |
| + // be the same as the encoding of the script element's node |
| + // document." |
| + // TODO(hiroshige): Should we handle failure in getting an encoding? |
| + String encoding; |
| + if (!element_->CharsetAttributeValue().IsEmpty()) |
| + encoding = element_->CharsetAttributeValue(); |
| + else |
| + encoding = element_document.characterSet(); |
| + |
| + // Step 16 is skipped because "module script credentials" is not used |
| + // for classic scripts. |
| + |
| + // 18. "If the script element has an integrity attribute, |
|
hiroshige
2017/04/14 00:13:29
Step 18 is moved from FetchScript().
|
| + // then let integrity metadata be that attribute's value. |
| + // Otherwise, let integrity metadata be the empty string." |
| + String integrity_attr = element_->IntegrityAttributeValue(); |
| + IntegrityMetadataSet integrity_metadata; |
| + if (!integrity_attr.IsEmpty()) { |
| + SubresourceIntegrity::ParseIntegrityAttribute( |
| + integrity_attr, integrity_metadata, &element_document); |
| + } |
| + |
| + if (!FetchClassicScript(url, element_document.Fetcher(), nonce, |
| + integrity_metadata, parser_state, cross_origin, |
| + element_document.GetSecurityOrigin(), encoding)) |
| return false; |
|
hiroshige
2017/04/14 00:13:29
Moved from Line 579.
Oh, I should call DispatchErr
|
| + |
| + // - "module": |
| + // TODO(hiroshige): Implement this. |
| + |
| + // "When the chosen algorithm asynchronously completes, set |
| + // the script's script to the result. At that time, the script is ready." |
| + // When the script is ready, PendingScriptClient::pendingScriptFinished() |
| + // is used as the notification, and the action to take when |
| + // the script is ready is specified later, in |
| + // - ScriptLoader::PrepareScript(), or |
| + // - HTMLParserScriptRunner, |
| + // depending on the conditions in Step 23 of "prepare a script". |
| } |
| // 22. "If the element does not have a src content attribute, |
| @@ -476,108 +552,62 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position, |
| return true; |
| } |
| -// Steps 15--21 of https://html.spec.whatwg.org/#prepare-a-script |
| -bool ScriptLoader::FetchScript(const String& source_url, |
| - const String& encoding, |
| - FetchParameters::DeferOption defer) { |
| - Document* element_document = &(element_->GetDocument()); |
| - if (!element_->IsConnected() || element_->GetDocument() != element_document) |
| - return false; |
| - |
| - DCHECK(!resource_); |
| - // 21. "If the element has a src content attribute, run these substeps:" |
| - if (!StripLeadingAndTrailingHTMLSpaces(source_url).IsEmpty()) { |
| - // 21.4. "Parse src relative to the element's node document." |
| - ResourceRequest resource_request(element_document->CompleteURL(source_url)); |
| - |
| - // [Intervention] |
| - if (document_write_intervention_ == |
| - DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { |
| - resource_request.SetHTTPHeaderField( |
| - "Intervention", |
| - "<https://www.chromestatus.com/feature/5718547946799104>"); |
| - } |
| - |
| - FetchParameters params(resource_request, element_->InitiatorName()); |
| +bool ScriptLoader::FetchClassicScript( |
| + const KURL& url, |
| + ResourceFetcher* fetcher, |
| + const String& nonce, |
| + const IntegrityMetadataSet& integrity_metadata, |
| + ParserDisposition parser_state, |
| + CrossOriginAttributeValue cross_origin, |
| + SecurityOrigin* security_origin, |
| + const String& encoding) { |
| + // https://html.spec.whatwg.org/#prepare-a-script |
| + // 21.6, "classic": |
| + // "Fetch a classic script given url, settings, ..." |
| + ResourceRequest resource_request(url); |
| - // 15. "Let CORS setting be the current state of the element's |
|
hiroshige
2017/04/14 00:13:29
Lines 503--544 (Steps 15, 17, 18, 19) are moved to
|
| - // crossorigin content attribute." |
| - CrossOriginAttributeValue cross_origin = |
| - GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); |
| - |
| - // 16. "Let module script credentials mode be determined by switching |
| - // on CORS setting:" |
| - // TODO(hiroshige): Implement this step for "module". |
| - |
| - // 21.6, "classic": "Fetch a classic script given ... CORS setting |
| - // ... and encoding." |
| - if (cross_origin != kCrossOriginAttributeNotSet) { |
| - params.SetCrossOriginAccessControl(element_document->GetSecurityOrigin(), |
| - cross_origin); |
| - } |
| - |
| - params.SetCharset(encoding); |
| - |
| - // 17. "If the script element has a nonce attribute, |
| - // then let cryptographic nonce be that attribute's value. |
| - // Otherwise, let cryptographic nonce be the empty string." |
| - if (element_->IsNonceableElement()) |
| - params.SetContentSecurityPolicyNonce(element_->nonce()); |
| + // [Intervention] |
| + if (document_write_intervention_ == |
| + DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { |
| + resource_request.SetHTTPHeaderField( |
| + "Intervention", |
| + "<https://www.chromestatus.com/feature/5718547946799104>"); |
| + } |
| - // 19. "Let parser state be "parser-inserted" |
| - // if the script element has been flagged as "parser-inserted", |
| - // and "not parser-inserted" otherwise." |
| - params.SetParserDisposition(IsParserInserted() ? kParserInserted |
| - : kNotParserInserted); |
| + FetchParameters params(resource_request, element_->InitiatorName()); |
| - params.SetDefer(defer); |
| + // "... cryptographic nonce, ..." |
| + params.SetContentSecurityPolicyNonce(nonce); |
| - // 18. "If the script element has an integrity attribute, |
| - // then let integrity metadata be that attribute's value. |
| - // Otherwise, let integrity metadata be the empty string." |
| - String integrity_attr = element_->IntegrityAttributeValue(); |
| - if (!integrity_attr.IsEmpty()) { |
| - IntegrityMetadataSet metadata_set; |
| - SubresourceIntegrity::ParseIntegrityAttribute( |
| - integrity_attr, metadata_set, element_document); |
| - params.SetIntegrityMetadata(metadata_set); |
| - } |
| + // "... integrity metadata, ..." |
| + params.SetIntegrityMetadata(integrity_metadata); |
| - // 21.6. "Switch on the script's type:" |
| + // "... parser state, ..." |
| + params.SetParserDisposition(parser_state); |
| - // - "classic": |
| - // "Fetch a classic script given url, settings, cryptographic nonce, |
| - // integrity metadata, parser state, CORS setting, and encoding." |
| - resource_ = ScriptResource::Fetch(params, element_document->Fetcher()); |
| + // "... CORS setting, ..." |
| + if (cross_origin != kCrossOriginAttributeNotSet) { |
| + params.SetCrossOriginAccessControl(security_origin, cross_origin); |
| + } |
| - // - "module": |
| - // "Fetch a module script graph given url, settings, "script", |
| - // cryptographic nonce, parser state, and |
| - // module script credentials mode." |
| - // TODO(kouhei, hiroshige): Implement this. |
| + // "... and encoding." |
| + params.SetCharset(encoding); |
| - // "When the chosen algorithm asynchronously completes, set |
| - // the script's script to the result. At that time, the script is ready." |
| - // When the script is ready, PendingScriptClient::pendingScriptFinished() |
| - // is used as the notification, and the action to take when |
| - // the script is ready is specified later, in |
| - // - ScriptLoader::prepareScript(), or |
| - // - HTMLParserScriptRunner, |
| - // depending on the conditions in Step 23 of "prepare a script". |
| + // This DeferOption logic is only for classic scripts, as we always set |
|
hiroshige
2017/04/14 00:13:29
This logic is moved from PrepareScript() to clarif
|
| + // |kLazyLoad| for module scripts in ModuleScriptLoader. |
| + FetchParameters::DeferOption defer = FetchParameters::kNoDefer; |
| + if (!parser_inserted_ || element_->AsyncAttributeValue() || |
| + element_->DeferAttributeValue()) |
| + defer = FetchParameters::kLazyLoad; |
| + if (document_write_intervention_ == |
| + DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) |
| + defer = FetchParameters::kIdleLoad; |
| + params.SetDefer(defer); |
| - // 21.3. "Set the element's from an external file flag." |
| - is_external_script_ = true; |
|
hiroshige
2017/04/14 00:13:29
Step 21.3 is moved to FetchScript().
|
| - } |
| + resource_ = ScriptResource::Fetch(params, fetcher); |
| - if (!resource_) { |
| - // 21.2. "If src is the empty string, queue a task to |
| - // fire an event named error at the element, and abort these steps." |
| - // 21.5. "If the previous step failed, queue a task to |
| - // fire an event named error at the element, and abort these steps." |
| - // TODO(hiroshige): Make this asynchronous. |
| - DispatchErrorEvent(); |
|
hiroshige
2017/04/14 00:13:29
This clause handles three different cases, and are
|
| + if (!resource_) |
| return false; |
| - } |
| // [Intervention] |
| if (created_during_document_write_ && |