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 11 matching lines...) Expand all Loading... |
22 * Boston, MA 02110-1301, USA. | 22 * Boston, MA 02110-1301, USA. |
23 */ | 23 */ |
24 | 24 |
25 #include "core/dom/ScriptLoader.h" | 25 #include "core/dom/ScriptLoader.h" |
26 | 26 |
27 #include "bindings/core/v8/ScriptController.h" | 27 #include "bindings/core/v8/ScriptController.h" |
28 #include "bindings/core/v8/ScriptSourceCode.h" | 28 #include "bindings/core/v8/ScriptSourceCode.h" |
29 #include "bindings/core/v8/V8Binding.h" | 29 #include "bindings/core/v8/V8Binding.h" |
30 #include "core/HTMLNames.h" | 30 #include "core/HTMLNames.h" |
31 #include "core/SVGNames.h" | 31 #include "core/SVGNames.h" |
| 32 #include "core/dom/ClassicScript.h" |
32 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
33 #include "core/dom/DocumentParserTiming.h" | 34 #include "core/dom/DocumentParserTiming.h" |
34 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" | 35 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" |
| 36 #include "core/dom/Script.h" |
35 #include "core/dom/ScriptElementBase.h" | 37 #include "core/dom/ScriptElementBase.h" |
36 #include "core/dom/ScriptRunner.h" | 38 #include "core/dom/ScriptRunner.h" |
37 #include "core/dom/ScriptableDocumentParser.h" | 39 #include "core/dom/ScriptableDocumentParser.h" |
38 #include "core/dom/Text.h" | 40 #include "core/dom/Text.h" |
39 #include "core/events/Event.h" | 41 #include "core/events/Event.h" |
40 #include "core/frame/LocalFrame.h" | 42 #include "core/frame/LocalFrame.h" |
41 #include "core/frame/SubresourceIntegrity.h" | 43 #include "core/frame/SubresourceIntegrity.h" |
42 #include "core/frame/UseCounter.h" | |
43 #include "core/frame/csp/ContentSecurityPolicy.h" | 44 #include "core/frame/csp/ContentSecurityPolicy.h" |
44 #include "core/html/CrossOriginAttribute.h" | 45 #include "core/html/CrossOriginAttribute.h" |
45 #include "core/html/imports/HTMLImport.h" | 46 #include "core/html/imports/HTMLImport.h" |
46 #include "core/html/parser/HTMLParserIdioms.h" | 47 #include "core/html/parser/HTMLParserIdioms.h" |
47 #include "core/inspector/ConsoleMessage.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 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 // and the element doesn't have a src attribute. | 461 // and the element doesn't have a src attribute. |
462 | 462 |
463 // Reset line numbering for nested writes. | 463 // Reset line numbering for nested writes. |
464 TextPosition position = element_document.IsInDocumentWrite() | 464 TextPosition position = element_document.IsInDocumentWrite() |
465 ? TextPosition() | 465 ? TextPosition() |
466 : script_start_position; | 466 : script_start_position; |
467 KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_) | 467 KURL script_url = (!element_document.IsInDocumentWrite() && parser_inserted_) |
468 ? element_document.Url() | 468 ? element_document.Url() |
469 : KURL(); | 469 : KURL(); |
470 | 470 |
471 if (!ExecuteScript(ScriptSourceCode(ScriptContent(), script_url, position))) { | 471 if (!ExecuteScript(ClassicScript::Create( |
| 472 ScriptSourceCode(ScriptContent(), script_url, position)))) { |
472 DispatchErrorEvent(); | 473 DispatchErrorEvent(); |
473 return false; | 474 return false; |
474 } | 475 } |
475 | 476 |
476 return true; | 477 return true; |
477 } | 478 } |
478 | 479 |
479 // Steps 15--21 of https://html.spec.whatwg.org/#prepare-a-script | 480 // Steps 15--21 of https://html.spec.whatwg.org/#prepare-a-script |
480 bool ScriptLoader::FetchScript(const String& source_url, | 481 bool ScriptLoader::FetchScript(const String& source_url, |
481 const String& encoding, | 482 const String& encoding, |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 } | 589 } |
589 | 590 |
590 return true; | 591 return true; |
591 } | 592 } |
592 | 593 |
593 PendingScript* ScriptLoader::CreatePendingScript() { | 594 PendingScript* ScriptLoader::CreatePendingScript() { |
594 CHECK(resource_); | 595 CHECK(resource_); |
595 return PendingScript::Create(element_, resource_); | 596 return PendingScript::Create(element_, resource_); |
596 } | 597 } |
597 | 598 |
598 void ScriptLoader::LogScriptMIMEType(LocalFrame* frame, | 599 bool ScriptLoader::ExecuteScript(const Script* script) { |
599 ScriptResource* resource, | |
600 const String& mime_type) { | |
601 if (MIMETypeRegistry::IsSupportedJavaScriptMIMEType(mime_type)) | |
602 return; | |
603 bool is_text = mime_type.StartsWith("text/", kTextCaseASCIIInsensitive); | |
604 if (is_text && MIMETypeRegistry::IsLegacySupportedJavaScriptLanguage( | |
605 mime_type.Substring(5))) | |
606 return; | |
607 bool is_same_origin = | |
608 element_->GetDocument().GetSecurityOrigin()->CanRequest(resource->Url()); | |
609 bool is_application = | |
610 !is_text && | |
611 mime_type.StartsWith("application/", kTextCaseASCIIInsensitive); | |
612 | |
613 UseCounter::Feature feature = | |
614 is_same_origin | |
615 ? (is_text ? UseCounter::kSameOriginTextScript | |
616 : is_application ? UseCounter::kSameOriginApplicationScript | |
617 : UseCounter::kSameOriginOtherScript) | |
618 : (is_text | |
619 ? UseCounter::kCrossOriginTextScript | |
620 : is_application ? UseCounter::kCrossOriginApplicationScript | |
621 : UseCounter::kCrossOriginOtherScript); | |
622 | |
623 UseCounter::Count(frame, feature); | |
624 } | |
625 | |
626 bool ScriptLoader::ExecuteScript(const ScriptSourceCode& source_code) { | |
627 double script_exec_start_time = MonotonicallyIncreasingTime(); | 600 double script_exec_start_time = MonotonicallyIncreasingTime(); |
628 bool result = DoExecuteScript(source_code); | 601 bool result = DoExecuteScript(script); |
629 | 602 |
630 // NOTE: we do not check m_willBeParserExecuted here, since | 603 // NOTE: we do not check m_willBeParserExecuted here, since |
631 // m_willBeParserExecuted is false for inline scripts, and we want to | 604 // m_willBeParserExecuted is false for inline scripts, and we want to |
632 // include inline script execution time as part of parser blocked script | 605 // include inline script execution time as part of parser blocked script |
633 // execution time. | 606 // execution time. |
634 if (async_exec_type_ == ScriptRunner::kNone) | 607 if (async_exec_type_ == ScriptRunner::kNone) |
635 DocumentParserTiming::From(element_->GetDocument()) | 608 DocumentParserTiming::From(element_->GetDocument()) |
636 .RecordParserBlockedOnScriptExecutionDuration( | 609 .RecordParserBlockedOnScriptExecutionDuration( |
637 MonotonicallyIncreasingTime() - script_exec_start_time, | 610 MonotonicallyIncreasingTime() - script_exec_start_time, |
638 WasCreatedDuringDocumentWrite()); | 611 WasCreatedDuringDocumentWrite()); |
639 return result; | 612 return result; |
640 } | 613 } |
641 | 614 |
642 // https://html.spec.whatwg.org/#execute-the-script-block | 615 // https://html.spec.whatwg.org/#execute-the-script-block |
643 // with additional support for HTML imports. | 616 // with additional support for HTML imports. |
644 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(), | 617 // Note that Steps 2 and 8 must be handled by the caller of doExecuteScript(), |
645 // i.e. load/error events are dispatched by the caller. | 618 // i.e. load/error events are dispatched by the caller. |
646 // Steps 3--7 are implemented here in doExecuteScript(). | 619 // Steps 3--7 are implemented here in doExecuteScript(). |
647 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). | 620 // TODO(hiroshige): Move event dispatching code to doExecuteScript(). |
648 bool ScriptLoader::DoExecuteScript(const ScriptSourceCode& source_code) { | 621 bool ScriptLoader::DoExecuteScript(const Script* script) { |
649 DCHECK(already_started_); | 622 DCHECK(already_started_); |
650 | 623 |
651 if (source_code.IsEmpty()) | 624 if (script->IsEmpty()) |
652 return true; | 625 return true; |
653 | 626 |
654 Document* element_document = &(element_->GetDocument()); | 627 Document* element_document = &(element_->GetDocument()); |
655 Document* context_document = element_document->ContextDocument(); | 628 Document* context_document = element_document->ContextDocument(); |
656 if (!context_document) | 629 if (!context_document) |
657 return true; | 630 return true; |
658 | 631 |
659 LocalFrame* frame = context_document->GetFrame(); | 632 LocalFrame* frame = context_document->GetFrame(); |
660 if (!frame) | 633 if (!frame) |
661 return true; | 634 return true; |
662 | 635 |
663 const ContentSecurityPolicy* csp = | 636 if (!is_external_script_) { |
664 element_document->GetContentSecurityPolicy(); | 637 const ContentSecurityPolicy* csp = |
665 bool should_bypass_main_world_csp = | 638 element_document->GetContentSecurityPolicy(); |
666 (frame->GetScriptController().ShouldBypassMainWorldCSP()) || | 639 bool should_bypass_main_world_csp = |
667 csp->AllowScriptWithHash(source_code.Source(), | 640 (frame->GetScriptController().ShouldBypassMainWorldCSP()) || |
668 ContentSecurityPolicy::InlineType::kBlock); | 641 csp->AllowScriptWithHash(script->InlineSourceTextForCSP(), |
| 642 ContentSecurityPolicy::InlineType::kBlock); |
669 | 643 |
670 AtomicString nonce = | 644 AtomicString nonce = |
671 element_->IsNonceableElement() ? element_->nonce() : g_null_atom; | 645 element_->IsNonceableElement() ? element_->nonce() : g_null_atom; |
672 if (!is_external_script_ && !should_bypass_main_world_csp && | 646 if (!should_bypass_main_world_csp && |
673 !element_->AllowInlineScriptForCSP(nonce, start_line_number_, | 647 !element_->AllowInlineScriptForCSP(nonce, start_line_number_, |
674 source_code.Source())) { | 648 script->InlineSourceTextForCSP())) { |
675 return false; | 649 return false; |
| 650 } |
676 } | 651 } |
677 | 652 |
678 if (is_external_script_) { | 653 if (is_external_script_) { |
679 ScriptResource* resource = source_code.GetResource(); | 654 if (!script->CheckMIMETypeBeforeRunScript( |
680 CHECK_EQ(resource, resource_); | 655 context_document, element_->GetDocument().GetSecurityOrigin())) |
681 CHECK(resource); | |
682 if (!ScriptResource::MimeTypeAllowedByNosniff(resource->GetResponse())) { | |
683 context_document->AddConsoleMessage(ConsoleMessage::Create( | |
684 kSecurityMessageSource, kErrorMessageLevel, | |
685 "Refused to execute script from '" + resource->Url().ElidedString() + | |
686 "' because its MIME type ('" + resource->HttpContentType() + | |
687 "') is not executable, and " | |
688 "strict MIME type checking is " | |
689 "enabled.")); | |
690 return false; | 656 return false; |
691 } | |
692 | |
693 String mime_type = resource->HttpContentType(); | |
694 if (mime_type.StartsWith("image/") || mime_type == "text/csv" || | |
695 mime_type.StartsWith("audio/") || mime_type.StartsWith("video/")) { | |
696 context_document->AddConsoleMessage(ConsoleMessage::Create( | |
697 kSecurityMessageSource, kErrorMessageLevel, | |
698 "Refused to execute script from '" + resource->Url().ElidedString() + | |
699 "' because its MIME type ('" + mime_type + | |
700 "') is not executable.")); | |
701 if (mime_type.StartsWith("image/")) | |
702 UseCounter::Count(frame, UseCounter::kBlockedSniffingImageToScript); | |
703 else if (mime_type.StartsWith("audio/")) | |
704 UseCounter::Count(frame, UseCounter::kBlockedSniffingAudioToScript); | |
705 else if (mime_type.StartsWith("video/")) | |
706 UseCounter::Count(frame, UseCounter::kBlockedSniffingVideoToScript); | |
707 else if (mime_type == "text/csv") | |
708 UseCounter::Count(frame, UseCounter::kBlockedSniffingCSVToScript); | |
709 return false; | |
710 } | |
711 | |
712 LogScriptMIMEType(frame, resource, mime_type); | |
713 } | |
714 | |
715 AccessControlStatus access_control_status = kNotSharableCrossOrigin; | |
716 if (!is_external_script_) { | |
717 access_control_status = kSharableCrossOrigin; | |
718 } else { | |
719 CHECK(source_code.GetResource()); | |
720 access_control_status = | |
721 source_code.GetResource()->CalculateAccessControlStatus( | |
722 element_->GetDocument().GetSecurityOrigin()); | |
723 } | 657 } |
724 | 658 |
725 const bool is_imported_script = context_document != element_document; | 659 const bool is_imported_script = context_document != element_document; |
726 | 660 |
727 // 3. "If the script is from an external file, | 661 // 3. "If the script is from an external file, |
728 // or the script's type is module", | 662 // or the script's type is module", |
729 // then increment the ignore-destructive-writes counter of the | 663 // then increment the ignore-destructive-writes counter of the |
730 // script element's node document. Let neutralized doc be that Document." | 664 // script element's node document. Let neutralized doc be that Document." |
731 // TODO(hiroshige): Implement "module" case. | 665 // TODO(hiroshige): Implement "module" case. |
732 IgnoreDestructiveWriteCountIncrementer | 666 IgnoreDestructiveWriteCountIncrementer |
733 ignore_destructive_write_count_incrementer( | 667 ignore_destructive_write_count_incrementer( |
734 is_external_script_ || is_imported_script ? context_document : 0); | 668 is_external_script_ || is_imported_script ? context_document : 0); |
735 | 669 |
736 // 4. "Let old script element be the value to which the script element's | 670 // 4. "Let old script element be the value to which the script element's |
737 // node document's currentScript object was most recently set." | 671 // node document's currentScript object was most recently set." |
738 // This is implemented as push/popCurrentScript(). | 672 // This is implemented as push/popCurrentScript(). |
739 | 673 |
740 // 5. "Switch on the script's type:" | 674 // 5. "Switch on the script's type:" |
741 // - "classic": | 675 // - "classic": |
742 // 1. "If the script element's root is not a shadow root, | 676 // 1. "If the script element's root is not a shadow root, |
743 // then set the script element's node document's currentScript | 677 // then set the script element's node document's currentScript |
744 // attribute to the script element. Otherwise, set it to null." | 678 // attribute to the script element. Otherwise, set it to null." |
745 context_document->PushCurrentScript(element_.Get()); | 679 context_document->PushCurrentScript(element_.Get()); |
746 | 680 |
747 // 2. "Run the classic script given by the script's script." | 681 // 2. "Run the classic script given by the script's script." |
748 // Note: This is where the script is compiled and actually executed. | 682 // Note: This is where the script is compiled and actually executed. |
749 frame->GetScriptController().ExecuteScriptInMainWorld(source_code, | 683 script->RunScript(frame, element_->GetDocument().GetSecurityOrigin()); |
750 access_control_status); | |
751 | 684 |
752 // - "module": | 685 // - "module": |
753 // TODO(hiroshige): Implement this. | 686 // TODO(hiroshige): Implement this. |
754 | 687 |
755 // 6. "Set the script element's node document's currentScript attribute | 688 // 6. "Set the script element's node document's currentScript attribute |
756 // to old script element." | 689 // to old script element." |
757 context_document->PopCurrentScript(element_.Get()); | 690 context_document->PopCurrentScript(element_.Get()); |
758 | 691 |
759 return true; | 692 return true; |
760 | 693 |
761 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, | 694 // 7. "Decrement the ignore-destructive-writes counter of neutralized doc, |
762 // if it was incremented in the earlier step." | 695 // if it was incremented in the earlier step." |
763 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. | 696 // Implemented as the scope out of IgnoreDestructiveWriteCountIncrementer. |
764 } | 697 } |
765 | 698 |
766 void ScriptLoader::Execute() { | 699 void ScriptLoader::Execute() { |
767 DCHECK(!will_be_parser_executed_); | 700 DCHECK(!will_be_parser_executed_); |
768 DCHECK(async_exec_type_ != ScriptRunner::kNone); | 701 DCHECK(async_exec_type_ != ScriptRunner::kNone); |
769 DCHECK(pending_script_->GetResource()); | 702 DCHECK(pending_script_->GetResource()); |
770 bool error_occurred = false; | 703 bool error_occurred = false; |
771 ScriptSourceCode source = pending_script_->GetSource(KURL(), error_occurred); | 704 Script* script = pending_script_->GetSource(KURL(), error_occurred); |
772 DetachPendingScript(); | 705 DetachPendingScript(); |
773 if (error_occurred) { | 706 if (error_occurred) { |
774 DispatchErrorEvent(); | 707 DispatchErrorEvent(); |
775 } else if (!resource_->WasCanceled()) { | 708 } else if (!resource_->WasCanceled()) { |
776 if (ExecuteScript(source)) | 709 if (ExecuteScript(script)) |
777 DispatchLoadEvent(); | 710 DispatchLoadEvent(); |
778 else | 711 else |
779 DispatchErrorEvent(); | 712 DispatchErrorEvent(); |
780 } | 713 } |
781 resource_ = nullptr; | 714 resource_ = nullptr; |
782 } | 715 } |
783 | 716 |
784 void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) { | 717 void ScriptLoader::PendingScriptFinished(PendingScript* pending_script) { |
785 DCHECK(!will_be_parser_executed_); | 718 DCHECK(!will_be_parser_executed_); |
786 DCHECK_EQ(pending_script_, pending_script); | 719 DCHECK_EQ(pending_script_, pending_script); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 // then abort these steps at this point. The script is not executed. | 781 // then abort these steps at this point. The script is not executed. |
849 return DeprecatedEqualIgnoringCase(event_attribute, "onload") || | 782 return DeprecatedEqualIgnoringCase(event_attribute, "onload") || |
850 DeprecatedEqualIgnoringCase(event_attribute, "onload()"); | 783 DeprecatedEqualIgnoringCase(event_attribute, "onload()"); |
851 } | 784 } |
852 | 785 |
853 String ScriptLoader::ScriptContent() const { | 786 String ScriptLoader::ScriptContent() const { |
854 return element_->TextFromChildren(); | 787 return element_->TextFromChildren(); |
855 } | 788 } |
856 | 789 |
857 } // namespace blink | 790 } // namespace blink |
OLD | NEW |