Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(175)

Side by Side Diff: third_party/WebKit/Source/core/dom/ScriptLoader.cpp

Issue 2780463002: Introduce blink::Script (Closed)
Patch Set: Rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698