OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights |
6 * reserved. | 6 * reserved. |
7 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> | 7 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Library General Public | 10 * modify it under the terms of the GNU Library General Public |
(...skipping 24 matching lines...) Expand all Loading... |
35 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" | 35 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" |
36 #include "core/dom/Script.h" | 36 #include "core/dom/Script.h" |
37 #include "core/dom/ScriptElementBase.h" | 37 #include "core/dom/ScriptElementBase.h" |
38 #include "core/dom/ScriptRunner.h" | 38 #include "core/dom/ScriptRunner.h" |
39 #include "core/dom/ScriptableDocumentParser.h" | 39 #include "core/dom/ScriptableDocumentParser.h" |
40 #include "core/dom/Text.h" | 40 #include "core/dom/Text.h" |
41 #include "core/events/Event.h" | 41 #include "core/events/Event.h" |
42 #include "core/frame/LocalFrame.h" | 42 #include "core/frame/LocalFrame.h" |
43 #include "core/frame/SubresourceIntegrity.h" | 43 #include "core/frame/SubresourceIntegrity.h" |
44 #include "core/frame/csp/ContentSecurityPolicy.h" | 44 #include "core/frame/csp/ContentSecurityPolicy.h" |
45 #include "core/html/CrossOriginAttribute.h" | |
46 #include "core/html/imports/HTMLImport.h" | 45 #include "core/html/imports/HTMLImport.h" |
47 #include "core/html/parser/HTMLParserIdioms.h" | 46 #include "core/html/parser/HTMLParserIdioms.h" |
| 47 #include "core/loader/resource/ScriptResource.h" |
48 #include "platform/WebFrameScheduler.h" | 48 #include "platform/WebFrameScheduler.h" |
49 #include "platform/loader/fetch/AccessControlStatus.h" | 49 #include "platform/loader/fetch/AccessControlStatus.h" |
50 #include "platform/loader/fetch/FetchParameters.h" | 50 #include "platform/loader/fetch/FetchParameters.h" |
51 #include "platform/loader/fetch/MemoryCache.h" | 51 #include "platform/loader/fetch/MemoryCache.h" |
52 #include "platform/loader/fetch/ResourceFetcher.h" | 52 #include "platform/loader/fetch/ResourceFetcher.h" |
53 #include "platform/network/mime/MIMETypeRegistry.h" | 53 #include "platform/network/mime/MIMETypeRegistry.h" |
54 #include "platform/weborigin/SecurityOrigin.h" | 54 #include "platform/weborigin/SecurityOrigin.h" |
55 #include "platform/wtf/StdLibExtras.h" | 55 #include "platform/wtf/StdLibExtras.h" |
56 #include "platform/wtf/text/StringBuilder.h" | 56 #include "platform/wtf/text/StringBuilder.h" |
57 #include "platform/wtf/text/StringHash.h" | 57 #include "platform/wtf/text/StringHash.h" |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 | 295 |
296 // 11. "If the script element has a nomodule content attribute | 296 // 11. "If the script element has a nomodule content attribute |
297 // and the script's type is "classic", then abort these steps. | 297 // and the script's type is "classic", then abort these steps. |
298 // The script is not executed." | 298 // The script is not executed." |
299 // TODO(japhet): Implement this step. | 299 // TODO(japhet): Implement this step. |
300 | 300 |
301 // 13. | 301 // 13. |
302 if (!IsScriptForEventSupported()) | 302 if (!IsScriptForEventSupported()) |
303 return false; | 303 return false; |
304 | 304 |
305 // 14. "If the script element has a charset attribute, | 305 // 14. is handled below. |
306 // then let encoding be the result of | |
307 // getting an encoding from the value of the charset attribute." | |
308 // "If the script element does not have a charset attribute, | |
309 // or if getting an encoding failed, let encoding | |
310 // be the same as the encoding of the script element's node document." | |
311 // TODO(hiroshige): Should we handle failure in getting an encoding? | |
312 String encoding; | |
313 if (!element_->CharsetAttributeValue().IsEmpty()) | |
314 encoding = element_->CharsetAttributeValue(); | |
315 else | |
316 encoding = element_document.characterSet(); | |
317 | 306 |
318 // Steps 15--20 are handled in fetchScript(). | 307 // 15. "Let CORS setting be the current state of the element's |
| 308 // crossorigin content attribute." |
| 309 CrossOriginAttributeValue cross_origin = |
| 310 GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); |
| 311 |
| 312 // 16. will be handled below once module script support is implemented. |
| 313 |
| 314 // 17. "If the script element has a nonce attribute, |
| 315 // then let cryptographic nonce be that attribute's value. |
| 316 // Otherwise, let cryptographic nonce be the empty string." |
| 317 String nonce; |
| 318 if (element_->IsNonceableElement()) |
| 319 nonce = element_->nonce(); |
| 320 |
| 321 // 18. is handled below. |
| 322 |
| 323 // 19. "Let parser state be "parser-inserted" |
| 324 // if the script element has been flagged as "parser-inserted", |
| 325 // and "not parser-inserted" otherwise." |
| 326 ParserDisposition parser_state = |
| 327 IsParserInserted() ? kParserInserted : kNotParserInserted; |
319 | 328 |
320 // 21. "If the element has a src content attribute, run these substeps:" | 329 // 21. "If the element has a src content attribute, run these substeps:" |
321 if (element_->HasSourceAttribute()) { | 330 if (element_->HasSourceAttribute()) { |
322 FetchParameters::DeferOption defer = FetchParameters::kNoDefer; | 331 // 21.1. Let src be the value of the element's src attribute. |
323 if (!parser_inserted_ || element_->AsyncAttributeValue() || | 332 String src = |
324 element_->DeferAttributeValue()) | 333 StripLeadingAndTrailingHTMLSpaces(element_->SourceAttributeValue()); |
325 defer = FetchParameters::kLazyLoad; | 334 |
326 if (document_write_intervention_ == | 335 // 21.2. "If src is the empty string, queue a task to |
327 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) | 336 // fire an event named error at the element, and abort these steps." |
328 defer = FetchParameters::kIdleLoad; | 337 if (src.IsEmpty()) { |
329 if (!FetchScript(element_->SourceAttributeValue(), encoding, defer)) | 338 // TODO(hiroshige): Make this asynchronous. Currently we fire the error |
| 339 // event synchronously to keep the existing behavior. |
| 340 DispatchErrorEvent(); |
330 return false; | 341 return false; |
| 342 } |
| 343 |
| 344 // 21.3. "Set the element's from an external file flag." |
| 345 is_external_script_ = true; |
| 346 |
| 347 // 21.4. "Parse src relative to the element's node document." |
| 348 // TODO(hiroshige): Use CompleteURL(src) instead. |
| 349 KURL url = element_document.CompleteURL(element_->SourceAttributeValue()); |
| 350 |
| 351 // 21.5. "If the previous step failed, queue a task to |
| 352 // fire an event named error at the element, and abort these steps." |
| 353 if (!url.IsValid()) { |
| 354 // TODO(hiroshige): Make this asynchronous. Currently we fire the error |
| 355 // event synchronously to keep the existing behavior. |
| 356 DispatchErrorEvent(); |
| 357 return false; |
| 358 } |
| 359 |
| 360 DCHECK(!resource_); |
| 361 |
| 362 // 21.6. "Switch on the script's type:" |
| 363 // - "classic": |
| 364 |
| 365 // 14. "If the script element has a charset attribute, |
| 366 // then let encoding be the result of |
| 367 // getting an encoding from the value of the charset attribute." |
| 368 // "If the script element does not have a charset attribute, |
| 369 // or if getting an encoding failed, let encoding |
| 370 // be the same as the encoding of the script element's node |
| 371 // document." |
| 372 // TODO(hiroshige): Should we handle failure in getting an encoding? |
| 373 String encoding; |
| 374 if (!element_->CharsetAttributeValue().IsEmpty()) |
| 375 encoding = element_->CharsetAttributeValue(); |
| 376 else |
| 377 encoding = element_document.characterSet(); |
| 378 |
| 379 // Step 16 is skipped because "module script credentials" is not used |
| 380 // for classic scripts. |
| 381 |
| 382 // 18. "If the script element has an integrity attribute, |
| 383 // then let integrity metadata be that attribute's value. |
| 384 // Otherwise, let integrity metadata be the empty string." |
| 385 String integrity_attr = element_->IntegrityAttributeValue(); |
| 386 IntegrityMetadataSet integrity_metadata; |
| 387 if (!integrity_attr.IsEmpty()) { |
| 388 SubresourceIntegrity::ParseIntegrityAttribute( |
| 389 integrity_attr, integrity_metadata, &element_document); |
| 390 } |
| 391 |
| 392 if (!FetchClassicScript(url, element_document.Fetcher(), nonce, |
| 393 integrity_metadata, parser_state, cross_origin, |
| 394 element_document.GetSecurityOrigin(), encoding)) { |
| 395 // TODO(hiroshige): Make this asynchronous. Currently we fire the error |
| 396 // event synchronously to keep the existing behavior. |
| 397 DispatchErrorEvent(); |
| 398 return false; |
| 399 } |
| 400 |
| 401 DCHECK(resource_); |
| 402 |
| 403 // - "module": |
| 404 // TODO(hiroshige): Implement this. |
| 405 |
| 406 // "When the chosen algorithm asynchronously completes, set |
| 407 // the script's script to the result. At that time, the script is ready." |
| 408 // When the script is ready, PendingScriptClient::pendingScriptFinished() |
| 409 // is used as the notification, and the action to take when |
| 410 // the script is ready is specified later, in |
| 411 // - ScriptLoader::PrepareScript(), or |
| 412 // - HTMLParserScriptRunner, |
| 413 // depending on the conditions in Step 23 of "prepare a script". |
331 } | 414 } |
332 | 415 |
333 // 22. "If the element does not have a src content attribute, | 416 // 22. "If the element does not have a src content attribute, |
334 // run these substeps:" | 417 // run these substeps:" |
335 | 418 |
336 // 22.1. "Let source text be the value of the text IDL attribute." | 419 // 22.1. "Let source text be the value of the text IDL attribute." |
337 // This step is done later: | 420 // This step is done later: |
338 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause), | 421 // - in ScriptLoader::pendingScript() (Step 23, 6th Clause), |
339 // as Element::textFromChildren() in ScriptLoader::scriptContent(), | 422 // as Element::textFromChildren() in ScriptLoader::scriptContent(), |
340 // - in HTMLParserScriptRunner::processScriptElementInternal() | 423 // - in HTMLParserScriptRunner::processScriptElementInternal() |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 | 587 |
505 if (!ExecuteScript(ClassicScript::Create( | 588 if (!ExecuteScript(ClassicScript::Create( |
506 ScriptSourceCode(ScriptContent(), script_url, position)))) { | 589 ScriptSourceCode(ScriptContent(), script_url, position)))) { |
507 DispatchErrorEvent(); | 590 DispatchErrorEvent(); |
508 return false; | 591 return false; |
509 } | 592 } |
510 | 593 |
511 return true; | 594 return true; |
512 } | 595 } |
513 | 596 |
514 // Steps 15--21 of https://html.spec.whatwg.org/#prepare-a-script | 597 bool ScriptLoader::FetchClassicScript( |
515 bool ScriptLoader::FetchScript(const String& source_url, | 598 const KURL& url, |
516 const String& encoding, | 599 ResourceFetcher* fetcher, |
517 FetchParameters::DeferOption defer) { | 600 const String& nonce, |
518 Document* element_document = &(element_->GetDocument()); | 601 const IntegrityMetadataSet& integrity_metadata, |
519 if (!element_->IsConnected() || element_->GetDocument() != element_document) | 602 ParserDisposition parser_state, |
520 return false; | 603 CrossOriginAttributeValue cross_origin, |
| 604 SecurityOrigin* security_origin, |
| 605 const String& encoding) { |
| 606 // https://html.spec.whatwg.org/#prepare-a-script |
| 607 // 21.6, "classic": |
| 608 // "Fetch a classic script given url, settings, ..." |
| 609 ResourceRequest resource_request(url); |
521 | 610 |
522 DCHECK(!resource_); | 611 // [Intervention] |
523 // 21. "If the element has a src content attribute, run these substeps:" | 612 if (document_write_intervention_ == |
524 if (!StripLeadingAndTrailingHTMLSpaces(source_url).IsEmpty()) { | 613 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { |
525 // 21.4. "Parse src relative to the element's node document." | 614 resource_request.SetHTTPHeaderField( |
526 ResourceRequest resource_request(element_document->CompleteURL(source_url)); | 615 "Intervention", |
527 | 616 "<https://www.chromestatus.com/feature/5718547946799104>"); |
528 // [Intervention] | |
529 if (document_write_intervention_ == | |
530 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) { | |
531 resource_request.SetHTTPHeaderField( | |
532 "Intervention", | |
533 "<https://www.chromestatus.com/feature/5718547946799104>"); | |
534 } | |
535 | |
536 FetchParameters params(resource_request, element_->InitiatorName()); | |
537 | |
538 // 15. "Let CORS setting be the current state of the element's | |
539 // crossorigin content attribute." | |
540 CrossOriginAttributeValue cross_origin = | |
541 GetCrossOriginAttributeValue(element_->CrossOriginAttributeValue()); | |
542 | |
543 // 16. "Let module script credentials mode be determined by switching | |
544 // on CORS setting:" | |
545 // TODO(hiroshige): Implement this step for "module". | |
546 | |
547 // 21.6, "classic": "Fetch a classic script given ... CORS setting | |
548 // ... and encoding." | |
549 if (cross_origin != kCrossOriginAttributeNotSet) { | |
550 params.SetCrossOriginAccessControl(element_document->GetSecurityOrigin(), | |
551 cross_origin); | |
552 } | |
553 | |
554 params.SetCharset(encoding); | |
555 | |
556 // 17. "If the script element has a nonce attribute, | |
557 // then let cryptographic nonce be that attribute's value. | |
558 // Otherwise, let cryptographic nonce be the empty string." | |
559 if (element_->IsNonceableElement()) | |
560 params.SetContentSecurityPolicyNonce(element_->nonce()); | |
561 | |
562 // 19. "Let parser state be "parser-inserted" | |
563 // if the script element has been flagged as "parser-inserted", | |
564 // and "not parser-inserted" otherwise." | |
565 params.SetParserDisposition(IsParserInserted() ? kParserInserted | |
566 : kNotParserInserted); | |
567 | |
568 params.SetDefer(defer); | |
569 | |
570 // 18. "If the script element has an integrity attribute, | |
571 // then let integrity metadata be that attribute's value. | |
572 // Otherwise, let integrity metadata be the empty string." | |
573 String integrity_attr = element_->IntegrityAttributeValue(); | |
574 if (!integrity_attr.IsEmpty()) { | |
575 IntegrityMetadataSet metadata_set; | |
576 SubresourceIntegrity::ParseIntegrityAttribute( | |
577 integrity_attr, metadata_set, element_document); | |
578 params.SetIntegrityMetadata(metadata_set); | |
579 } | |
580 | |
581 // 21.6. "Switch on the script's type:" | |
582 | |
583 // - "classic": | |
584 // "Fetch a classic script given url, settings, cryptographic nonce, | |
585 // integrity metadata, parser state, CORS setting, and encoding." | |
586 resource_ = ScriptResource::Fetch(params, element_document->Fetcher()); | |
587 | |
588 // - "module": | |
589 // "Fetch a module script graph given url, settings, "script", | |
590 // cryptographic nonce, parser state, and | |
591 // module script credentials mode." | |
592 // TODO(kouhei, hiroshige): Implement this. | |
593 | |
594 // "When the chosen algorithm asynchronously completes, set | |
595 // the script's script to the result. At that time, the script is ready." | |
596 // When the script is ready, PendingScriptClient::pendingScriptFinished() | |
597 // is used as the notification, and the action to take when | |
598 // the script is ready is specified later, in | |
599 // - ScriptLoader::prepareScript(), or | |
600 // - HTMLParserScriptRunner, | |
601 // depending on the conditions in Step 23 of "prepare a script". | |
602 | |
603 // 21.3. "Set the element's from an external file flag." | |
604 is_external_script_ = true; | |
605 } | 617 } |
606 | 618 |
607 if (!resource_) { | 619 FetchParameters params(resource_request, element_->InitiatorName()); |
608 // 21.2. "If src is the empty string, queue a task to | 620 |
609 // fire an event named error at the element, and abort these steps." | 621 // "... cryptographic nonce, ..." |
610 // 21.5. "If the previous step failed, queue a task to | 622 params.SetContentSecurityPolicyNonce(nonce); |
611 // fire an event named error at the element, and abort these steps." | 623 |
612 // TODO(hiroshige): Make this asynchronous. | 624 // "... integrity metadata, ..." |
613 DispatchErrorEvent(); | 625 params.SetIntegrityMetadata(integrity_metadata); |
| 626 |
| 627 // "... parser state, ..." |
| 628 params.SetParserDisposition(parser_state); |
| 629 |
| 630 // "... CORS setting, ..." |
| 631 if (cross_origin != kCrossOriginAttributeNotSet) { |
| 632 params.SetCrossOriginAccessControl(security_origin, cross_origin); |
| 633 } |
| 634 |
| 635 // "... and encoding." |
| 636 params.SetCharset(encoding); |
| 637 |
| 638 // This DeferOption logic is only for classic scripts, as we always set |
| 639 // |kLazyLoad| for module scripts in ModuleScriptLoader. |
| 640 FetchParameters::DeferOption defer = FetchParameters::kNoDefer; |
| 641 if (!parser_inserted_ || element_->AsyncAttributeValue() || |
| 642 element_->DeferAttributeValue()) |
| 643 defer = FetchParameters::kLazyLoad; |
| 644 if (document_write_intervention_ == |
| 645 DocumentWriteIntervention::kFetchDocWrittenScriptDeferIdle) |
| 646 defer = FetchParameters::kIdleLoad; |
| 647 params.SetDefer(defer); |
| 648 |
| 649 resource_ = ScriptResource::Fetch(params, fetcher); |
| 650 |
| 651 if (!resource_) |
614 return false; | 652 return false; |
615 } | |
616 | 653 |
617 // [Intervention] | 654 // [Intervention] |
618 if (created_during_document_write_ && | 655 if (created_during_document_write_ && |
619 resource_->GetResourceRequest().GetCachePolicy() == | 656 resource_->GetResourceRequest().GetCachePolicy() == |
620 WebCachePolicy::kReturnCacheDataDontLoad) { | 657 WebCachePolicy::kReturnCacheDataDontLoad) { |
621 document_write_intervention_ = | 658 document_write_intervention_ = |
622 DocumentWriteIntervention::kDoNotFetchDocWrittenScript; | 659 DocumentWriteIntervention::kDoNotFetchDocWrittenScript; |
623 } | 660 } |
624 | 661 |
625 return true; | 662 return true; |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 // then abort these steps at this point. The script is not executed. | 852 // then abort these steps at this point. The script is not executed. |
816 return DeprecatedEqualIgnoringCase(event_attribute, "onload") || | 853 return DeprecatedEqualIgnoringCase(event_attribute, "onload") || |
817 DeprecatedEqualIgnoringCase(event_attribute, "onload()"); | 854 DeprecatedEqualIgnoringCase(event_attribute, "onload()"); |
818 } | 855 } |
819 | 856 |
820 String ScriptLoader::ScriptContent() const { | 857 String ScriptLoader::ScriptContent() const { |
821 return element_->TextFromChildren(); | 858 return element_->TextFromChildren(); |
822 } | 859 } |
823 | 860 |
824 } // namespace blink | 861 } // namespace blink |
OLD | NEW |