| 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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 m_forceAsync = false; | 122 m_forceAsync = false; |
| 123 } | 123 } |
| 124 | 124 |
| 125 void ScriptLoader::detach() { | 125 void ScriptLoader::detach() { |
| 126 if (!m_pendingScript) | 126 if (!m_pendingScript) |
| 127 return; | 127 return; |
| 128 m_pendingScript->dispose(); | 128 m_pendingScript->dispose(); |
| 129 m_pendingScript = nullptr; | 129 m_pendingScript = nullptr; |
| 130 } | 130 } |
| 131 | 131 |
| 132 // Helper function. Must take a lowercase language as input. | |
| 133 static bool isLegacySupportedJavaScriptLanguage(const String& language) { | 132 static bool isLegacySupportedJavaScriptLanguage(const String& language) { |
| 134 // Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only | 133 // Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only |
| 135 // javascript1.1 - javascript1.3. | 134 // javascript1.1 - javascript1.3. |
| 136 // Mozilla 1.8 and WinIE 7 both accept javascript and livescript. | 135 // Mozilla 1.8 and WinIE 7 both accept javascript and livescript. |
| 137 // WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't. | 136 // WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't. |
| 138 // Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace. | 137 // Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace. |
| 139 // We want to accept all the values that either of these browsers accept, but | 138 // We want to accept all the values that either of these browsers accept, but |
| 140 // not other values. | 139 // not other values. |
| 141 | 140 |
| 142 // FIXME: This function is not HTML5 compliant. These belong in the MIME | 141 // FIXME: This function is not HTML5 compliant. These belong in the MIME |
| 143 // registry as "text/javascript<version>" entries. | 142 // registry as "text/javascript<version>" entries. |
| 144 DCHECK_EQ(language, language.lower()); | 143 return equalIgnoringASCIICase(language, "javascript") || |
| 145 return language == "javascript" || language == "javascript1.0" || | 144 equalIgnoringASCIICase(language, "javascript1.0") || |
| 146 language == "javascript1.1" || language == "javascript1.2" || | 145 equalIgnoringASCIICase(language, "javascript1.1") || |
| 147 language == "javascript1.3" || language == "javascript1.4" || | 146 equalIgnoringASCIICase(language, "javascript1.2") || |
| 148 language == "javascript1.5" || language == "javascript1.6" || | 147 equalIgnoringASCIICase(language, "javascript1.3") || |
| 149 language == "javascript1.7" || language == "livescript" || | 148 equalIgnoringASCIICase(language, "javascript1.4") || |
| 150 language == "ecmascript" || language == "jscript"; | 149 equalIgnoringASCIICase(language, "javascript1.5") || |
| 150 equalIgnoringASCIICase(language, "javascript1.6") || |
| 151 equalIgnoringASCIICase(language, "javascript1.7") || |
| 152 equalIgnoringASCIICase(language, "livescript") || |
| 153 equalIgnoringASCIICase(language, "ecmascript") || |
| 154 equalIgnoringASCIICase(language, "jscript"); |
| 151 } | 155 } |
| 152 | 156 |
| 153 void ScriptLoader::dispatchErrorEvent() { | 157 void ScriptLoader::dispatchErrorEvent() { |
| 154 m_element->dispatchEvent(Event::create(EventTypeNames::error)); | 158 m_element->dispatchEvent(Event::create(EventTypeNames::error)); |
| 155 } | 159 } |
| 156 | 160 |
| 157 void ScriptLoader::dispatchLoadEvent() { | 161 void ScriptLoader::dispatchLoadEvent() { |
| 158 if (ScriptLoaderClient* client = this->client()) | 162 if (ScriptLoaderClient* client = this->client()) |
| 159 client->dispatchLoadEvent(); | 163 client->dispatchLoadEvent(); |
| 160 setHaveFiredLoadEvent(true); | 164 setHaveFiredLoadEvent(true); |
| 161 } | 165 } |
| 162 | 166 |
| 163 bool ScriptLoader::isValidScriptTypeAndLanguage( | 167 bool ScriptLoader::isValidScriptTypeAndLanguage( |
| 164 const String& type, | 168 const String& type, |
| 165 const String& language, | 169 const String& language, |
| 166 LegacyTypeSupport supportLegacyTypes) { | 170 LegacyTypeSupport supportLegacyTypes) { |
| 167 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used | 171 // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used |
| 168 // here to maintain backwards compatibility with existing layout tests. The | 172 // here to maintain backwards compatibility with existing layout tests. The |
| 169 // specific violations are: | 173 // specific violations are: |
| 170 // - Allowing type=javascript. type= should only support MIME types, such as | 174 // - Allowing type=javascript. type= should only support MIME types, such as |
| 171 // text/javascript. | 175 // text/javascript. |
| 172 // - Allowing a different set of languages for language= and type=. language= | 176 // - Allowing a different set of languages for language= and type=. language= |
| 173 // supports Javascript 1.1 and 1.4-1.6, but type= does not. | 177 // supports Javascript 1.1 and 1.4-1.6, but type= does not. |
| 174 if (type.isEmpty()) { | 178 if (type.isEmpty()) { |
| 175 String lowerLanguage = language.lower(); | 179 return language.isEmpty() || // assume text/javascript. |
| 176 return language.isEmpty() // assume text/javascript. | 180 MIMETypeRegistry::isSupportedJavaScriptMIMEType("text/" + |
| 177 || MIMETypeRegistry::isSupportedJavaScriptMIMEType("text/" + | 181 language) || |
| 178 lowerLanguage) || | 182 isLegacySupportedJavaScriptLanguage(language); |
| 179 isLegacySupportedJavaScriptLanguage(lowerLanguage); | |
| 180 } else if (RuntimeEnabledFeatures::moduleScriptsEnabled() && | 183 } else if (RuntimeEnabledFeatures::moduleScriptsEnabled() && |
| 181 type == "module") { | 184 type == "module") { |
| 182 return true; | 185 return true; |
| 183 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType( | 186 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType( |
| 184 type.stripWhiteSpace()) || | 187 type.stripWhiteSpace()) || |
| 185 (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && | 188 (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && |
| 186 isLegacySupportedJavaScriptLanguage(type.lower()))) { | 189 isLegacySupportedJavaScriptLanguage(type))) { |
| 187 return true; | 190 return true; |
| 188 } | 191 } |
| 189 | 192 |
| 190 return false; | 193 return false; |
| 191 } | 194 } |
| 192 | 195 |
| 193 bool ScriptLoader::isScriptTypeSupported( | 196 bool ScriptLoader::isScriptTypeSupported( |
| 194 LegacyTypeSupport supportLegacyTypes) const { | 197 LegacyTypeSupport supportLegacyTypes) const { |
| 195 return isValidScriptTypeAndLanguage(client()->typeAttributeValue(), | 198 return isValidScriptTypeAndLanguage(client()->typeAttributeValue(), |
| 196 client()->languageAttributeValue(), | 199 client()->languageAttributeValue(), |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 bool isHTMLScriptLoader(Element* element) { | 397 bool isHTMLScriptLoader(Element* element) { |
| 395 DCHECK(element); | 398 DCHECK(element); |
| 396 return isHTMLScriptElement(*element); | 399 return isHTMLScriptElement(*element); |
| 397 } | 400 } |
| 398 | 401 |
| 399 bool isSVGScriptLoader(Element* element) { | 402 bool isSVGScriptLoader(Element* element) { |
| 400 DCHECK(element); | 403 DCHECK(element); |
| 401 return isSVGScriptElement(*element); | 404 return isSVGScriptElement(*element); |
| 402 } | 405 } |
| 403 | 406 |
| 404 void ScriptLoader::logScriptMimetype(ScriptResource* resource, | 407 void ScriptLoader::logScriptMIMEType(LocalFrame* frame, |
| 405 LocalFrame* frame, | 408 ScriptResource* resource, |
| 406 String mimetype) { | 409 const String& mimeType) { |
| 407 String lowerMimetype = mimetype.lower(); | 410 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)) |
| 408 bool text = lowerMimetype.startsWith("text/"); | |
| 409 bool application = lowerMimetype.startsWith("application/"); | |
| 410 bool expectedJs = | |
| 411 MIMETypeRegistry::isSupportedJavaScriptMIMEType(lowerMimetype) || | |
| 412 (text && isLegacySupportedJavaScriptLanguage(lowerMimetype.substring(5))); | |
| 413 bool sameOrigin = | |
| 414 m_element->document().getSecurityOrigin()->canRequest(m_resource->url()); | |
| 415 if (expectedJs) { | |
| 416 return; | 411 return; |
| 417 } | 412 bool isText = mimeType.startsWith("text/", TextCaseASCIIInsensitive); |
| 413 if (isText && isLegacySupportedJavaScriptLanguage(mimeType.substring(5))) |
| 414 return; |
| 415 bool isSameOrigin = |
| 416 m_element->document().getSecurityOrigin()->canRequest(resource->url()); |
| 417 bool isApplication = |
| 418 !isText && mimeType.startsWith("application/", TextCaseASCIIInsensitive); |
| 419 |
| 418 UseCounter::Feature feature = | 420 UseCounter::Feature feature = |
| 419 sameOrigin | 421 isSameOrigin |
| 420 ? (text ? UseCounter::SameOriginTextScript | 422 ? (isText ? UseCounter::SameOriginTextScript |
| 421 : application ? UseCounter::SameOriginApplicationScript | 423 : isApplication ? UseCounter::SameOriginApplicationScript |
| 422 : UseCounter::SameOriginOtherScript) | 424 : UseCounter::SameOriginOtherScript) |
| 423 : (text ? UseCounter::CrossOriginTextScript | 425 : (isText ? UseCounter::CrossOriginTextScript |
| 424 : application ? UseCounter::CrossOriginApplicationScript | 426 : isApplication ? UseCounter::CrossOriginApplicationScript |
| 425 : UseCounter::CrossOriginOtherScript); | 427 : UseCounter::CrossOriginOtherScript); |
| 428 |
| 426 UseCounter::count(frame, feature); | 429 UseCounter::count(frame, feature); |
| 427 } | 430 } |
| 428 | 431 |
| 429 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) { | 432 bool ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) { |
| 430 double scriptExecStartTime = monotonicallyIncreasingTime(); | 433 double scriptExecStartTime = monotonicallyIncreasingTime(); |
| 431 bool result = doExecuteScript(sourceCode); | 434 bool result = doExecuteScript(sourceCode); |
| 432 | 435 |
| 433 // NOTE: we do not check m_willBeParserExecuted here, since | 436 // NOTE: we do not check m_willBeParserExecuted here, since |
| 434 // m_willBeParserExecuted is false for inline scripts, and we want to | 437 // m_willBeParserExecuted is false for inline scripts, and we want to |
| 435 // include inline script execution time as part of parser blocked script | 438 // include inline script execution time as part of parser blocked script |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 contextDocument->addConsoleMessage(ConsoleMessage::create( | 483 contextDocument->addConsoleMessage(ConsoleMessage::create( |
| 481 SecurityMessageSource, ErrorMessageLevel, | 484 SecurityMessageSource, ErrorMessageLevel, |
| 482 "Refused to execute script from '" + | 485 "Refused to execute script from '" + |
| 483 resource->url().elidedString() + "' because its MIME type ('" + | 486 resource->url().elidedString() + "' because its MIME type ('" + |
| 484 resource->httpContentType() + "') is not executable, and " | 487 resource->httpContentType() + "') is not executable, and " |
| 485 "strict MIME type checking is " | 488 "strict MIME type checking is " |
| 486 "enabled.")); | 489 "enabled.")); |
| 487 return false; | 490 return false; |
| 488 } | 491 } |
| 489 | 492 |
| 490 String mimetype = resource->httpContentType(); | 493 String mimeType = resource->httpContentType(); |
| 491 if (mimetype.startsWith("image/") || mimetype == "text/csv" || | 494 if (mimeType.startsWith("image/") || mimeType == "text/csv" || |
| 492 mimetype.startsWith("audio/") || mimetype.startsWith("video/")) { | 495 mimeType.startsWith("audio/") || mimeType.startsWith("video/")) { |
| 493 contextDocument->addConsoleMessage(ConsoleMessage::create( | 496 contextDocument->addConsoleMessage(ConsoleMessage::create( |
| 494 SecurityMessageSource, ErrorMessageLevel, | 497 SecurityMessageSource, ErrorMessageLevel, |
| 495 "Refused to execute script from '" + | 498 "Refused to execute script from '" + |
| 496 resource->url().elidedString() + "' because its MIME type ('" + | 499 resource->url().elidedString() + "' because its MIME type ('" + |
| 497 mimetype + "') is not executable.")); | 500 mimeType + "') is not executable.")); |
| 498 if (mimetype.startsWith("image/")) | 501 if (mimeType.startsWith("image/")) |
| 499 UseCounter::count(frame, UseCounter::BlockedSniffingImageToScript); | 502 UseCounter::count(frame, UseCounter::BlockedSniffingImageToScript); |
| 500 else if (mimetype.startsWith("audio/")) | 503 else if (mimeType.startsWith("audio/")) |
| 501 UseCounter::count(frame, UseCounter::BlockedSniffingAudioToScript); | 504 UseCounter::count(frame, UseCounter::BlockedSniffingAudioToScript); |
| 502 else if (mimetype.startsWith("video/")) | 505 else if (mimeType.startsWith("video/")) |
| 503 UseCounter::count(frame, UseCounter::BlockedSniffingVideoToScript); | 506 UseCounter::count(frame, UseCounter::BlockedSniffingVideoToScript); |
| 504 else if (mimetype == "text/csv") | 507 else if (mimeType == "text/csv") |
| 505 UseCounter::count(frame, UseCounter::BlockedSniffingCSVToScript); | 508 UseCounter::count(frame, UseCounter::BlockedSniffingCSVToScript); |
| 506 return false; | 509 return false; |
| 507 } | 510 } |
| 508 | 511 |
| 509 logScriptMimetype(resource, frame, mimetype); | 512 logScriptMIMEType(frame, resource, mimeType); |
| 510 } | 513 } |
| 511 } | 514 } |
| 512 | 515 |
| 513 // FIXME: Can this be moved earlier in the function? | 516 // FIXME: Can this be moved earlier in the function? |
| 514 // Why are we ever attempting to execute scripts without a frame? | 517 // Why are we ever attempting to execute scripts without a frame? |
| 515 if (!frame) | 518 if (!frame) |
| 516 return true; | 519 return true; |
| 517 | 520 |
| 518 AccessControlStatus accessControlStatus = NotSharableCrossOrigin; | 521 AccessControlStatus accessControlStatus = NotSharableCrossOrigin; |
| 519 if (!m_isExternalScript) { | 522 if (!m_isExternalScript) { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 if (isHTMLScriptLoader(element)) | 648 if (isHTMLScriptLoader(element)) |
| 646 return toHTMLScriptElement(element)->loader(); | 649 return toHTMLScriptElement(element)->loader(); |
| 647 | 650 |
| 648 if (isSVGScriptLoader(element)) | 651 if (isSVGScriptLoader(element)) |
| 649 return toSVGScriptElement(element)->loader(); | 652 return toSVGScriptElement(element)->loader(); |
| 650 | 653 |
| 651 return 0; | 654 return 0; |
| 652 } | 655 } |
| 653 | 656 |
| 654 } // namespace blink | 657 } // namespace blink |
| OLD | NEW |