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