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(); |