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 |