| 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 bf589315c35aac506df393c99fd852b9994c0ea3..c8b7fdb4c17312eb50c0c3da5754aaee7f29b7ed 100644
|
| --- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
|
| +++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
|
| @@ -29,9 +29,11 @@
|
| #include "bindings/core/v8/V8Binding.h"
|
| #include "core/HTMLNames.h"
|
| #include "core/SVGNames.h"
|
| +#include "core/dom/ClassicScript.h"
|
| #include "core/dom/Document.h"
|
| #include "core/dom/DocumentParserTiming.h"
|
| #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h"
|
| +#include "core/dom/Script.h"
|
| #include "core/dom/ScriptElementBase.h"
|
| #include "core/dom/ScriptRunner.h"
|
| #include "core/dom/ScriptableDocumentParser.h"
|
| @@ -39,12 +41,10 @@
|
| #include "core/events/Event.h"
|
| #include "core/frame/LocalFrame.h"
|
| #include "core/frame/SubresourceIntegrity.h"
|
| -#include "core/frame/UseCounter.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/inspector/ConsoleMessage.h"
|
| #include "platform/WebFrameScheduler.h"
|
| #include "platform/loader/fetch/AccessControlStatus.h"
|
| #include "platform/loader/fetch/FetchRequest.h"
|
| @@ -147,31 +147,6 @@ void ScriptLoader::detachPendingScript() {
|
| m_pendingScript = nullptr;
|
| }
|
|
|
| -static bool isLegacySupportedJavaScriptLanguage(const String& language) {
|
| - // Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only
|
| - // javascript1.1 - javascript1.3.
|
| - // Mozilla 1.8 and WinIE 7 both accept javascript and livescript.
|
| - // WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't.
|
| - // Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace.
|
| - // We want to accept all the values that either of these browsers accept, but
|
| - // not other values.
|
| -
|
| - // FIXME: This function is not HTML5 compliant. These belong in the MIME
|
| - // registry as "text/javascript<version>" entries.
|
| - return equalIgnoringASCIICase(language, "javascript") ||
|
| - equalIgnoringASCIICase(language, "javascript1.0") ||
|
| - equalIgnoringASCIICase(language, "javascript1.1") ||
|
| - equalIgnoringASCIICase(language, "javascript1.2") ||
|
| - equalIgnoringASCIICase(language, "javascript1.3") ||
|
| - equalIgnoringASCIICase(language, "javascript1.4") ||
|
| - equalIgnoringASCIICase(language, "javascript1.5") ||
|
| - equalIgnoringASCIICase(language, "javascript1.6") ||
|
| - equalIgnoringASCIICase(language, "javascript1.7") ||
|
| - equalIgnoringASCIICase(language, "livescript") ||
|
| - equalIgnoringASCIICase(language, "ecmascript") ||
|
| - equalIgnoringASCIICase(language, "jscript");
|
| -}
|
| -
|
| void ScriptLoader::dispatchErrorEvent() {
|
| m_element->dispatchErrorEvent();
|
| }
|
| @@ -196,14 +171,14 @@ bool ScriptLoader::isValidScriptTypeAndLanguage(
|
| return language.isEmpty() || // assume text/javascript.
|
| MIMETypeRegistry::isSupportedJavaScriptMIMEType("text/" +
|
| language) ||
|
| - isLegacySupportedJavaScriptLanguage(language);
|
| + MIMETypeRegistry::isLegacySupportedJavaScriptLanguage(language);
|
| } else if (RuntimeEnabledFeatures::moduleScriptsEnabled() &&
|
| type == "module") {
|
| return true;
|
| } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(
|
| type.stripWhiteSpace()) ||
|
| (supportLegacyTypes == AllowLegacyTypeInTypeAttribute &&
|
| - isLegacySupportedJavaScriptLanguage(type))) {
|
| + MIMETypeRegistry::isLegacySupportedJavaScriptLanguage(type))) {
|
| return true;
|
| }
|
|
|
| @@ -498,7 +473,8 @@ bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
|
| ? elementDocument.url()
|
| : KURL();
|
|
|
| - if (!executeScript(ScriptSourceCode(scriptContent(), scriptURL, position))) {
|
| + if (!executeScript(ClassicScript::create(
|
| + ScriptSourceCode(scriptContent(), scriptURL, position)))) {
|
| dispatchErrorEvent();
|
| return false;
|
| }
|
| @@ -619,34 +595,9 @@ bool ScriptLoader::fetchScript(const String& sourceUrl,
|
| return true;
|
| }
|
|
|
| -void ScriptLoader::logScriptMIMEType(LocalFrame* frame,
|
| - ScriptResource* resource,
|
| - const String& mimeType) {
|
| - if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType))
|
| - return;
|
| - bool isText = mimeType.startsWith("text/", TextCaseASCIIInsensitive);
|
| - if (isText && isLegacySupportedJavaScriptLanguage(mimeType.substring(5)))
|
| - return;
|
| - bool isSameOrigin =
|
| - m_element->document().getSecurityOrigin()->canRequest(resource->url());
|
| - bool isApplication =
|
| - !isText && mimeType.startsWith("application/", TextCaseASCIIInsensitive);
|
| -
|
| - UseCounter::Feature feature =
|
| - isSameOrigin
|
| - ? (isText ? UseCounter::SameOriginTextScript
|
| - : isApplication ? UseCounter::SameOriginApplicationScript
|
| - : UseCounter::SameOriginOtherScript)
|
| - : (isText ? UseCounter::CrossOriginTextScript
|
| - : isApplication ? UseCounter::CrossOriginApplicationScript
|
| - : UseCounter::CrossOriginOtherScript);
|
| -
|
| - UseCounter::count(frame, feature);
|
| -}
|
| -
|
| -bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) {
|
| +bool ScriptLoader::executeScript(const Script* script) {
|
| double scriptExecStartTime = monotonicallyIncreasingTime();
|
| - bool result = doExecuteScript(sourceCode);
|
| + bool result = doExecuteScript(script);
|
|
|
| // NOTE: we do not check m_willBeParserExecuted here, since
|
| // m_willBeParserExecuted is false for inline scripts, and we want to
|
| @@ -666,10 +617,10 @@ bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) {
|
| // i.e. load/error events are dispatched by the caller.
|
| // Steps 3--7 are implemented here in doExecuteScript().
|
| // TODO(hiroshige): Move event dispatching code to doExecuteScript().
|
| -bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
|
| +bool ScriptLoader::doExecuteScript(const Script* script) {
|
| DCHECK(m_alreadyStarted);
|
|
|
| - if (sourceCode.isEmpty())
|
| + if (script->isEmpty())
|
| return true;
|
|
|
| Document* elementDocument = &(m_element->document());
|
| @@ -681,64 +632,27 @@ bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
|
| if (!frame)
|
| return true;
|
|
|
| - const ContentSecurityPolicy* csp = elementDocument->contentSecurityPolicy();
|
| - bool shouldBypassMainWorldCSP =
|
| - (frame->script().shouldBypassMainWorldCSP()) ||
|
| - csp->allowScriptWithHash(sourceCode.source(),
|
| - ContentSecurityPolicy::InlineType::Block);
|
| -
|
| - AtomicString nonce =
|
| - m_element->isNonceableElement() ? m_element->nonce() : nullAtom;
|
| - if (!m_isExternalScript && !shouldBypassMainWorldCSP &&
|
| - !m_element->allowInlineScriptForCSP(nonce, m_startLineNumber,
|
| - sourceCode.source())) {
|
| - return false;
|
| - }
|
| -
|
| - if (m_isExternalScript) {
|
| - ScriptResource* resource = sourceCode.resource();
|
| - CHECK_EQ(resource, m_resource);
|
| - CHECK(resource);
|
| - if (!ScriptResource::mimeTypeAllowedByNosniff(resource->response())) {
|
| - contextDocument->addConsoleMessage(ConsoleMessage::create(
|
| - SecurityMessageSource, ErrorMessageLevel,
|
| - "Refused to execute script from '" + resource->url().elidedString() +
|
| - "' because its MIME type ('" + resource->httpContentType() +
|
| - "') is not executable, and "
|
| - "strict MIME type checking is "
|
| - "enabled."));
|
| - return false;
|
| - }
|
| -
|
| - String mimeType = resource->httpContentType();
|
| - if (mimeType.startsWith("image/") || mimeType == "text/csv" ||
|
| - mimeType.startsWith("audio/") || mimeType.startsWith("video/")) {
|
| - contextDocument->addConsoleMessage(ConsoleMessage::create(
|
| - SecurityMessageSource, ErrorMessageLevel,
|
| - "Refused to execute script from '" + resource->url().elidedString() +
|
| - "' because its MIME type ('" + mimeType +
|
| - "') is not executable."));
|
| - if (mimeType.startsWith("image/"))
|
| - UseCounter::count(frame, UseCounter::BlockedSniffingImageToScript);
|
| - else if (mimeType.startsWith("audio/"))
|
| - UseCounter::count(frame, UseCounter::BlockedSniffingAudioToScript);
|
| - else if (mimeType.startsWith("video/"))
|
| - UseCounter::count(frame, UseCounter::BlockedSniffingVideoToScript);
|
| - else if (mimeType == "text/csv")
|
| - UseCounter::count(frame, UseCounter::BlockedSniffingCSVToScript);
|
| + if (!m_isExternalScript) {
|
| + const ContentSecurityPolicy* csp = elementDocument->contentSecurityPolicy();
|
| + bool shouldBypassMainWorldCSP =
|
| + frame->script().shouldBypassMainWorldCSP() ||
|
| + csp->allowScriptWithHash(script->inlineSourceTextForCSP(),
|
| + ContentSecurityPolicy::InlineType::Block);
|
| +
|
| + AtomicString nonce =
|
| + m_element->isNonceableElement() ? m_element->nonce() : nullAtom;
|
| +
|
| + if (!shouldBypassMainWorldCSP &&
|
| + !m_element->allowInlineScriptForCSP(nonce, m_startLineNumber,
|
| + script->inlineSourceTextForCSP())) {
|
| return false;
|
| }
|
| -
|
| - logScriptMIMEType(frame, resource, mimeType);
|
| }
|
|
|
| - AccessControlStatus accessControlStatus = NotSharableCrossOrigin;
|
| - if (!m_isExternalScript) {
|
| - accessControlStatus = SharableCrossOrigin;
|
| - } else {
|
| - CHECK(sourceCode.resource());
|
| - accessControlStatus = sourceCode.resource()->calculateAccessControlStatus(
|
| - m_element->document().getSecurityOrigin());
|
| + if (m_isExternalScript) {
|
| + if (!script->checkMIMETypeBeforeRunScript(
|
| + contextDocument, m_element->document().getSecurityOrigin()))
|
| + return false;
|
| }
|
|
|
| const bool isImportedScript = contextDocument != elementDocument;
|
| @@ -764,7 +678,7 @@ bool ScriptLoader::doExecuteScript(const ScriptSourceCode& sourceCode) {
|
|
|
| // 2. "Run the classic script given by the script's script."
|
| // Note: This is where the script is compiled and actually executed.
|
| - frame->script().executeScriptInMainWorld(sourceCode, accessControlStatus);
|
| + script->runScript(frame, m_element->document().getSecurityOrigin());
|
|
|
| // - "module":
|
| // TODO(hiroshige): Implement this.
|
| @@ -785,12 +699,12 @@ void ScriptLoader::execute() {
|
| DCHECK(m_asyncExecType != ScriptRunner::None);
|
| DCHECK(m_pendingScript->resource());
|
| bool errorOccurred = false;
|
| - ScriptSourceCode source = m_pendingScript->getSource(KURL(), errorOccurred);
|
| + Script* script = m_pendingScript->getSource(KURL(), errorOccurred);
|
| detachPendingScript();
|
| if (errorOccurred) {
|
| dispatchErrorEvent();
|
| } else if (!m_resource->wasCanceled()) {
|
| - if (executeScript(source))
|
| + if (executeScript(script))
|
| dispatchLoadEvent();
|
| else
|
| dispatchErrorEvent();
|
|
|