zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 | * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 | * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 | * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 6 | * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> |
| 7 | * |
| 8 | * This library is free software; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU Library General Public |
| 10 | * License as published by the Free Software Foundation; either |
| 11 | * version 2 of the License, or (at your option) any later version. |
| 12 | * |
| 13 | * This library is distributed in the hope that it will be useful, |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16 | * Library General Public License for more details. |
| 17 | * |
| 18 | * You should have received a copy of the GNU Library General Public License |
| 19 | * along with this library; see the file COPYING.LIB. If not, write to |
| 20 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 21 | * Boston, MA 02110-1301, USA. |
| 22 | */ |
| 23 | |
| 24 | #include "config.h" |
| 25 | #include "ScriptElement.h" |
| 26 | |
abarth@webkit.org | 17d66c6 | 2010-09-08 10:26:02 +0000 | [diff] [blame] | 27 | #include "CachedResourceLoader.h" |
commit-queue@webkit.org | 5e7ea1b | 2012-10-22 23:35:28 +0000 | [diff] [blame] | 28 | #include "CachedResourceRequest.h" |
joepeck@webkit.org | 1f45df9 | 2014-02-06 23:45:53 +0000 | [diff] [blame] | 29 | #include "CachedScript.h" |
abarth@webkit.org | f921dee | 2011-03-26 11:59:34 +0000 | [diff] [blame] | 30 | #include "ContentSecurityPolicy.h" |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 31 | #include "CrossOriginAccessControl.h" |
kangil.han@samsung.com | 6b8ffd8 | 2013-06-25 02:38:54 +0000 | [diff] [blame] | 32 | #include "CurrentScriptIncrementer.h" |
abarth@webkit.org | 401a379 | 2013-03-03 10:12:59 +0000 | [diff] [blame] | 33 | #include "Event.h" |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 34 | #include "Frame.h" |
| 35 | #include "FrameLoader.h" |
zimmermann@webkit.org | 67ac8f8 | 2009-01-21 19:49:37 +0000 | [diff] [blame] | 36 | #include "HTMLNames.h" |
japhet@chromium.org | 59e6e21 | 2011-08-31 19:01:08 +0000 | [diff] [blame] | 37 | #include "HTMLParserIdioms.h" |
tonyg@chromium.org | 8500eb8 | 2010-10-22 01:27:27 +0000 | [diff] [blame] | 38 | #include "IgnoreDestructiveWriteCountIncrementer.h" |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 39 | #include "MIMETypeRegistry.h" |
eric@webkit.org | ab9e738 | 2010-05-19 19:02:12 +0000 | [diff] [blame] | 40 | #include "Page.h" |
ossy@webkit.org | 66d8c0a | 2014-02-05 11:42:35 +0000 | [diff] [blame] | 41 | #include "SVGNames.h" |
| 42 | #include "SVGScriptElement.h" |
weinig@apple.com | 123e4aa | 2013-04-14 00:54:27 +0000 | [diff] [blame] | 43 | #include "ScriptController.h" |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 44 | #include "ScriptRunner.h" |
darin@chromium.org | 6b41247 | 2008-11-24 23:07:38 +0000 | [diff] [blame] | 45 | #include "ScriptSourceCode.h" |
commit-queue@webkit.org | fae2ea2 | 2012-05-25 23:29:45 +0000 | [diff] [blame] | 46 | #include "ScriptableDocumentParser.h" |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 47 | #include "SecurityOrigin.h" |
eric@webkit.org | ab9e738 | 2010-05-19 19:02:12 +0000 | [diff] [blame] | 48 | #include "Settings.h" |
antti@apple.com | adb7e12 | 2013-08-17 21:33:23 +0000 | [diff] [blame] | 49 | #include "TextNodeTraversal.h" |
joepeck@webkit.org | a319844 | 2013-12-11 22:40:23 +0000 | [diff] [blame] | 50 | #include <bindings/ScriptValue.h> |
joepeck@webkit.org | 1f45df9 | 2014-02-06 23:45:53 +0000 | [diff] [blame] | 51 | #include <inspector/ScriptCallStack.h> |
bolsinga@apple.com | 97e42c4 | 2008-11-15 04:47:20 +0000 | [diff] [blame] | 52 | #include <wtf/StdLibExtras.h> |
zimmermann@webkit.org | 64ca9f9 | 2011-05-16 10:20:34 +0000 | [diff] [blame] | 53 | #include <wtf/text/StringBuilder.h> |
barraclough@apple.com | bbb3cd4 | 2010-08-10 17:45:41 +0000 | [diff] [blame] | 54 | #include <wtf/text/StringHash.h> |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 55 | |
| 56 | namespace WebCore { |
| 57 | |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 58 | ScriptElement::ScriptElement(Element& element, bool parserInserted, bool alreadyStarted) |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 59 | : m_element(element) |
| 60 | , m_cachedScript(0) |
commit-queue@webkit.org | fae2ea2 | 2012-05-25 23:29:45 +0000 | [diff] [blame] | 61 | , m_startLineNumber(WTF::OrdinalNumber::beforeFirst()) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 62 | , m_parserInserted(parserInserted) |
rniwa@webkit.org | eb0ec5e | 2010-12-01 02:09:33 +0000 | [diff] [blame] | 63 | , m_isExternalScript(false) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 64 | , m_alreadyStarted(alreadyStarted) |
rniwa@webkit.org | eb0ec5e | 2010-12-01 02:09:33 +0000 | [diff] [blame] | 65 | , m_haveFiredLoad(false) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 66 | , m_willBeParserExecuted(false) |
| 67 | , m_readyToBeParserExecuted(false) |
| 68 | , m_willExecuteWhenDocumentFinishedParsing(false) |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 69 | , m_forceAsync(!parserInserted) |
| 70 | , m_willExecuteInOrder(false) |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 71 | , m_requestUsesAccessControl(false) |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 72 | { |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 73 | if (parserInserted && m_element.document().scriptableDocumentParser() && !m_element.document().isInDocumentWrite()) |
| 74 | m_startLineNumber = m_element.document().scriptableDocumentParser()->textPosition().m_line; |
rniwa@webkit.org | 1329a19 | 2010-11-16 05:23:34 +0000 | [diff] [blame] | 75 | } |
| 76 | |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 77 | ScriptElement::~ScriptElement() |
rniwa@webkit.org | 1329a19 | 2010-11-16 05:23:34 +0000 | [diff] [blame] | 78 | { |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 79 | stopLoadRequest(); |
rniwa@webkit.org | 1329a19 | 2010-11-16 05:23:34 +0000 | [diff] [blame] | 80 | } |
| 81 | |
aestes@apple.com | 8b7dab7 | 2015-06-21 21:14:51 +0000 | [diff] [blame] | 82 | bool ScriptElement::shouldCallFinishedInsertingSubtree(ContainerNode& insertionPoint) |
rniwa@webkit.org | 1329a19 | 2010-11-16 05:23:34 +0000 | [diff] [blame] | 83 | { |
aestes@apple.com | 74888f4 | 2015-06-19 21:55:55 +0000 | [diff] [blame] | 84 | return insertionPoint.inDocument() && !m_parserInserted; |
| 85 | } |
| 86 | |
aestes@apple.com | 8b7dab7 | 2015-06-21 21:14:51 +0000 | [diff] [blame] | 87 | void ScriptElement::finishedInsertingSubtree() |
aestes@apple.com | 74888f4 | 2015-06-19 21:55:55 +0000 | [diff] [blame] | 88 | { |
| 89 | ASSERT(!m_parserInserted); |
| 90 | prepareScript(); // FIXME: Provide a real starting line number here. |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 91 | } |
| 92 | |
rniwa@webkit.org | 1329a19 | 2010-11-16 05:23:34 +0000 | [diff] [blame] | 93 | void ScriptElement::childrenChanged() |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 94 | { |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 95 | if (!m_parserInserted && m_element.inDocument()) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 96 | prepareScript(); // FIXME: Provide a real starting line number here. |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 97 | } |
| 98 | |
rniwa@webkit.org | 1329a19 | 2010-11-16 05:23:34 +0000 | [diff] [blame] | 99 | void ScriptElement::handleSourceAttribute(const String& sourceUrl) |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 100 | { |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 101 | if (ignoresLoadRequest() || sourceUrl.isEmpty()) |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 102 | return; |
| 103 | |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 104 | prepareScript(); // FIXME: Provide a real starting line number here. |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 105 | } |
| 106 | |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 107 | void ScriptElement::handleAsyncAttribute() |
| 108 | { |
| 109 | m_forceAsync = false; |
| 110 | } |
| 111 | |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 112 | // Helper function |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 113 | static bool isLegacySupportedJavaScriptLanguage(const String& language) |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 114 | { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 115 | // Mozilla 1.8 accepts javascript1.0 - javascript1.7, but WinIE 7 accepts only javascript1.1 - javascript1.3. |
| 116 | // Mozilla 1.8 and WinIE 7 both accept javascript and livescript. |
| 117 | // WinIE 7 accepts ecmascript and jscript, but Mozilla 1.8 doesn't. |
| 118 | // Neither Mozilla 1.8 nor WinIE 7 accept leading or trailing whitespace. |
| 119 | // We want to accept all the values that either of these browsers accept, but not other values. |
| 120 | |
| 121 | // FIXME: This function is not HTML5 compliant. These belong in the MIME registry as "text/javascript<version>" entries. |
bolsinga@apple.com | 97e42c4 | 2008-11-15 04:47:20 +0000 | [diff] [blame] | 122 | typedef HashSet<String, CaseFoldingHash> LanguageSet; |
svillar@igalia.com | 5b31eef | 2014-03-14 08:30:55 +0000 | [diff] [blame] | 123 | DEPRECATED_DEFINE_STATIC_LOCAL(LanguageSet, languages, ()); |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 124 | if (languages.isEmpty()) { |
| 125 | languages.add("javascript"); |
| 126 | languages.add("javascript"); |
| 127 | languages.add("javascript1.0"); |
| 128 | languages.add("javascript1.1"); |
| 129 | languages.add("javascript1.2"); |
| 130 | languages.add("javascript1.3"); |
| 131 | languages.add("javascript1.4"); |
| 132 | languages.add("javascript1.5"); |
| 133 | languages.add("javascript1.6"); |
| 134 | languages.add("javascript1.7"); |
| 135 | languages.add("livescript"); |
| 136 | languages.add("ecmascript"); |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 137 | languages.add("jscript"); |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | return languages.contains(language); |
| 141 | } |
| 142 | |
yurys@chromium.org | fb5a0d8 | 2011-04-20 11:52:04 +0000 | [diff] [blame] | 143 | void ScriptElement::dispatchErrorEvent() |
| 144 | { |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 145 | m_element.dispatchEvent(Event::create(eventNames().errorEvent, false, false)); |
yurys@chromium.org | fb5a0d8 | 2011-04-20 11:52:04 +0000 | [diff] [blame] | 146 | } |
| 147 | |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 148 | bool ScriptElement::isScriptTypeSupported(LegacyTypeSupport supportLegacyTypes) const |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 149 | { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 150 | // FIXME: isLegacySupportedJavaScriptLanguage() is not valid HTML5. It is used here to maintain backwards compatibility with existing layout tests. The specific violations are: |
| 151 | // - Allowing type=javascript. type= should only support MIME types, such as text/javascript. |
| 152 | // - Allowing a different set of languages for language= and type=. language= supports Javascript 1.1 and 1.4-1.6, but type= does not. |
| 153 | |
| 154 | String type = typeAttributeValue(); |
| 155 | String language = languageAttributeValue(); |
| 156 | if (type.isEmpty() && language.isEmpty()) |
| 157 | return true; // Assume text/javascript. |
| 158 | if (type.isEmpty()) { |
| 159 | type = "text/" + language.lower(); |
| 160 | if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type) || isLegacySupportedJavaScriptLanguage(language)) |
| 161 | return true; |
| 162 | } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSpace().lower()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLegacySupportedJavaScriptLanguage(type))) |
| 163 | return true; |
| 164 | return false; |
| 165 | } |
| 166 | |
| 167 | // http://dev.w3.org/html5/spec/Overview.html#prepare-a-script |
commit-queue@webkit.org | 9c6e4a3 | 2011-09-19 18:45:47 +0000 | [diff] [blame] | 168 | bool ScriptElement::prepareScript(const TextPosition& scriptStartPosition, LegacyTypeSupport supportLegacyTypes) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 169 | { |
| 170 | if (m_alreadyStarted) |
| 171 | return false; |
| 172 | |
| 173 | bool wasParserInserted; |
| 174 | if (m_parserInserted) { |
| 175 | wasParserInserted = true; |
| 176 | m_parserInserted = false; |
| 177 | } else |
| 178 | wasParserInserted = false; |
| 179 | |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 180 | if (wasParserInserted && !asyncAttributeValue()) |
| 181 | m_forceAsync = true; |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 182 | |
| 183 | // FIXME: HTML5 spec says we should check that all children are either comments or empty text nodes. |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 184 | if (!hasSourceAttribute() && !m_element.firstChild()) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 185 | return false; |
| 186 | |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 187 | if (!m_element.inDocument()) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 188 | return false; |
| 189 | |
| 190 | if (!isScriptTypeSupported(supportLegacyTypes)) |
| 191 | return false; |
| 192 | |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 193 | if (wasParserInserted) { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 194 | m_parserInserted = true; |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 195 | m_forceAsync = false; |
| 196 | } |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 197 | |
| 198 | m_alreadyStarted = true; |
| 199 | |
| 200 | // FIXME: If script is parser inserted, verify it's still in the original document. |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 201 | Document& document = m_element.document(); |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 202 | |
| 203 | // FIXME: Eventually we'd like to evaluate scripts which are inserted into a |
mrowe@apple.com | 5d92f2a | 2008-09-30 21:04:35 +0000 | [diff] [blame] | 204 | // viewless document but this'll do for now. |
| 205 | // See http://bugs.webkit.org/show_bug.cgi?id=5727 |
akling@apple.com | 622b1a4 | 2013-08-30 14:30:12 +0000 | [diff] [blame] | 206 | if (!document.frame()) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 207 | return false; |
| 208 | |
akling@apple.com | 622b1a4 | 2013-08-30 14:30:12 +0000 | [diff] [blame] | 209 | if (!document.frame()->script().canExecuteScripts(AboutToExecuteScript)) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 210 | return false; |
| 211 | |
| 212 | if (!isScriptForEventSupported()) |
| 213 | return false; |
| 214 | |
| 215 | if (!charsetAttributeValue().isEmpty()) |
| 216 | m_characterEncoding = charsetAttributeValue(); |
| 217 | else |
akling@apple.com | 622b1a4 | 2013-08-30 14:30:12 +0000 | [diff] [blame] | 218 | m_characterEncoding = document.charset(); |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 219 | |
| 220 | if (hasSourceAttribute()) |
| 221 | if (!requestScript(sourceAttributeValue())) |
| 222 | return false; |
| 223 | |
| 224 | if (hasSourceAttribute() && deferAttributeValue() && m_parserInserted && !asyncAttributeValue()) { |
| 225 | m_willExecuteWhenDocumentFinishedParsing = true; |
| 226 | m_willBeParserExecuted = true; |
| 227 | } else if (hasSourceAttribute() && m_parserInserted && !asyncAttributeValue()) |
| 228 | m_willBeParserExecuted = true; |
akling@apple.com | 622b1a4 | 2013-08-30 14:30:12 +0000 | [diff] [blame] | 229 | else if (!hasSourceAttribute() && m_parserInserted && !document.haveStylesheetsLoaded()) { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 230 | m_willBeParserExecuted = true; |
| 231 | m_readyToBeParserExecuted = true; |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 232 | } else if (hasSourceAttribute() && !asyncAttributeValue() && !m_forceAsync) { |
| 233 | m_willExecuteInOrder = true; |
akling@apple.com | 622b1a4 | 2013-08-30 14:30:12 +0000 | [diff] [blame] | 234 | document.scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::IN_ORDER_EXECUTION); |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 235 | m_cachedScript->addClient(this); |
jochen@chromium.org | 2093573 | 2012-01-16 09:37:03 +0000 | [diff] [blame] | 236 | } else if (hasSourceAttribute()) { |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 237 | m_element.document().scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::ASYNC_EXECUTION); |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 238 | m_cachedScript->addClient(this); |
jochen@chromium.org | 2093573 | 2012-01-16 09:37:03 +0000 | [diff] [blame] | 239 | } else { |
pfeldman@chromium.org | 2679eaf | 2011-10-28 13:27:32 +0000 | [diff] [blame] | 240 | // Reset line numbering for nested writes. |
akling@apple.com | 622b1a4 | 2013-08-30 14:30:12 +0000 | [diff] [blame] | 241 | TextPosition position = document.isInDocumentWrite() ? TextPosition() : scriptStartPosition; |
| 242 | executeScript(ScriptSourceCode(scriptContent(), document.url(), position)); |
pfeldman@chromium.org | 2679eaf | 2011-10-28 13:27:32 +0000 | [diff] [blame] | 243 | } |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 244 | |
| 245 | return true; |
| 246 | } |
| 247 | |
| 248 | bool ScriptElement::requestScript(const String& sourceUrl) |
| 249 | { |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 250 | Ref<Document> originalDocument(m_element.document()); |
| 251 | if (!m_element.dispatchBeforeLoadEvent(sourceUrl)) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 252 | return false; |
cdumez@apple.com | 7814173 | 2014-11-04 23:00:48 +0000 | [diff] [blame] | 253 | if (!m_element.inDocument() || &m_element.document() != originalDocument.ptr()) |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 254 | return false; |
hyatt@apple.com | ad45b61 | 2009-10-06 17:37:48 +0000 | [diff] [blame] | 255 | |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 256 | ASSERT(!m_cachedScript); |
japhet@chromium.org | 59e6e21 | 2011-08-31 19:01:08 +0000 | [diff] [blame] | 257 | if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { |
dbates@webkit.org | 264add7 | 2015-07-07 00:42:50 +0000 | [diff] [blame] | 258 | ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions(); |
| 259 | options.setContentSecurityPolicyImposition(m_element.isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck); |
| 260 | |
| 261 | CachedResourceRequest request(ResourceRequest(m_element.document().completeURL(sourceUrl)), options); |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 262 | |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 263 | String crossOriginMode = m_element.fastGetAttribute(HTMLNames::crossoriginAttr); |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 264 | if (!crossOriginMode.isNull()) { |
| 265 | m_requestUsesAccessControl = true; |
| 266 | StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMode, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 267 | updateRequestForAccessControl(request.mutableResourceRequest(), m_element.document().securityOrigin(), allowCredentials); |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 268 | } |
commit-queue@webkit.org | 5e7ea1b | 2012-10-22 23:35:28 +0000 | [diff] [blame] | 269 | request.setCharset(scriptCharset()); |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 270 | request.setInitiator(&element()); |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 271 | |
cdumez@apple.com | 0bb03ec | 2015-01-28 05:53:53 +0000 | [diff] [blame] | 272 | m_cachedScript = m_element.document().cachedResourceLoader().requestScript(request); |
japhet@chromium.org | 59e6e21 | 2011-08-31 19:01:08 +0000 | [diff] [blame] | 273 | m_isExternalScript = true; |
| 274 | } |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 275 | |
gavinp@chromium.org | 22aaf03 | 2011-08-26 13:15:00 +0000 | [diff] [blame] | 276 | if (m_cachedScript) { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 277 | return true; |
gavinp@chromium.org | 22aaf03 | 2011-08-26 13:15:00 +0000 | [diff] [blame] | 278 | } |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 279 | |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 280 | dispatchErrorEvent(); |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 281 | return false; |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 282 | } |
| 283 | |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 284 | void ScriptElement::executeScript(const ScriptSourceCode& sourceCode) |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 285 | { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 286 | ASSERT(m_alreadyStarted); |
| 287 | |
| 288 | if (sourceCode.isEmpty()) |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 289 | return; |
| 290 | |
dbates@webkit.org | 264add7 | 2015-07-07 00:42:50 +0000 | [diff] [blame] | 291 | if (!m_isExternalScript && !m_element.document().contentSecurityPolicy()->allowInlineScript(m_element.document().url(), m_startLineNumber, m_element.isInUserAgentShadowTree())) |
abarth@webkit.org | 3285b43b | 2011-04-07 10:04:22 +0000 | [diff] [blame] | 292 | return; |
| 293 | |
mkwst@chromium.org | 43e54ba | 2013-02-12 23:44:51 +0000 | [diff] [blame] | 294 | #if ENABLE(NOSNIFF) |
| 295 | if (m_isExternalScript && m_cachedScript && !m_cachedScript->mimeTypeAllowedByNosniff()) { |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 296 | m_element.document().addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Refused to execute script from '" + m_cachedScript->url().stringCenterEllipsizedToLength() + "' because its MIME type ('" + m_cachedScript->mimeType() + "') is not executable, and strict MIME type checking is enabled."); |
mkwst@chromium.org | 43e54ba | 2013-02-12 23:44:51 +0000 | [diff] [blame] | 297 | return; |
| 298 | } |
| 299 | #endif |
| 300 | |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 301 | Ref<Document> document(m_element.document()); |
tonyg@chromium.org | 8500eb8 | 2010-10-22 01:27:27 +0000 | [diff] [blame] | 302 | if (Frame* frame = document->frame()) { |
cdumez@apple.com | 7814173 | 2014-11-04 23:00:48 +0000 | [diff] [blame] | 303 | IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncrementer(m_isExternalScript ? document.ptr() : nullptr); |
| 304 | CurrentScriptIncrementer currentScriptIncrementer(document, &m_element); |
kangil.han@samsung.com | 6b8ffd8 | 2013-06-25 02:38:54 +0000 | [diff] [blame] | 305 | |
akling@apple.com | 622b1a4 | 2013-08-30 14:30:12 +0000 | [diff] [blame] | 306 | // Create a script from the script element node, using the script |
| 307 | // block's source and the script block's type. |
| 308 | // Note: This is where the script is compiled and actually executed. |
| 309 | frame->script().evaluate(sourceCode); |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 310 | } |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 311 | } |
| 312 | |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 313 | void ScriptElement::stopLoadRequest() |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 314 | { |
| 315 | if (m_cachedScript) { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 316 | if (!m_willBeParserExecuted) |
| 317 | m_cachedScript->removeClient(this); |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 318 | m_cachedScript = 0; |
| 319 | } |
| 320 | } |
| 321 | |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 322 | void ScriptElement::execute(CachedScript* cachedScript) |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 323 | { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 324 | ASSERT(!m_willBeParserExecuted); |
mitz@apple.com | 73169a1 | 2009-04-20 04:20:08 +0000 | [diff] [blame] | 325 | ASSERT(cachedScript); |
| 326 | if (cachedScript->errorOccurred()) |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 327 | dispatchErrorEvent(); |
ap@apple.com | ab624d54 | 2011-05-29 01:37:59 +0000 | [diff] [blame] | 328 | else if (!cachedScript->wasCanceled()) { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 329 | executeScript(ScriptSourceCode(cachedScript)); |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 330 | dispatchLoadEvent(); |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 331 | } |
mitz@apple.com | af63be9 | 2009-06-10 20:37:47 +0000 | [diff] [blame] | 332 | cachedScript->removeClient(this); |
mitz@apple.com | 73169a1 | 2009-04-20 04:20:08 +0000 | [diff] [blame] | 333 | } |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 334 | |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 335 | void ScriptElement::notifyFinished(CachedResource* resource) |
mitz@apple.com | 73169a1 | 2009-04-20 04:20:08 +0000 | [diff] [blame] | 336 | { |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 337 | ASSERT(!m_willBeParserExecuted); |
morrita@google.com | bec5819 | 2013-01-17 01:38:20 +0000 | [diff] [blame] | 338 | |
| 339 | // CachedResource possibly invokes this notifyFinished() more than |
| 340 | // once because ScriptElement doesn't unsubscribe itself from |
| 341 | // CachedResource here and does it in execute() instead. |
| 342 | // We use m_cachedScript to check if this function is already called. |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 343 | ASSERT_UNUSED(resource, resource == m_cachedScript); |
morrita@google.com | bec5819 | 2013-01-17 01:38:20 +0000 | [diff] [blame] | 344 | if (!m_cachedScript) |
| 345 | return; |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 346 | |
antti@apple.com | 5c3e664 | 2015-05-16 13:53:21 +0000 | [diff] [blame] | 347 | if (m_requestUsesAccessControl && !m_cachedScript->passesSameOriginPolicyCheck(*m_element.document().securityOrigin())) { |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 348 | dispatchErrorEvent(); |
svillar@igalia.com | 5b31eef | 2014-03-14 08:30:55 +0000 | [diff] [blame] | 349 | DEPRECATED_DEFINE_STATIC_LOCAL(String, consoleMessage, (ASCIILiteral("Cross-origin script load denied by Cross-Origin Resource Sharing policy."))); |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 350 | m_element.document().addConsoleMessage(MessageSource::JS, MessageLevel::Error, consoleMessage); |
commit-queue@webkit.org | a42d1f6 | 2012-03-20 05:29:11 +0000 | [diff] [blame] | 351 | return; |
| 352 | } |
| 353 | |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 354 | if (m_willExecuteInOrder) |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 355 | m_element.document().scriptRunner()->notifyScriptReady(this, ScriptRunner::IN_ORDER_EXECUTION); |
simonjam@chromium.org | 5871a05 | 2011-03-16 00:00:09 +0000 | [diff] [blame] | 356 | else |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 357 | m_element.document().scriptRunner()->notifyScriptReady(this, ScriptRunner::ASYNC_EXECUTION); |
gavinp@chromium.org | 22aaf03 | 2011-08-26 13:15:00 +0000 | [diff] [blame] | 358 | |
mitz@apple.com | af63be9 | 2009-06-10 20:37:47 +0000 | [diff] [blame] | 359 | m_cachedScript = 0; |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 360 | } |
| 361 | |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 362 | bool ScriptElement::ignoresLoadRequest() const |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 363 | { |
akling@apple.com | a564ed6 | 2014-07-04 19:54:43 +0000 | [diff] [blame] | 364 | return m_alreadyStarted || m_isExternalScript || m_parserInserted || !m_element.inDocument(); |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 365 | } |
| 366 | |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 367 | bool ScriptElement::isScriptForEventSupported() const |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 368 | { |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 369 | String eventAttribute = eventAttributeValue(); |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 370 | String forAttribute = forAttributeValue(); |
| 371 | if (!eventAttribute.isEmpty() && !forAttribute.isEmpty()) { |
tonyg@chromium.org | bd35ae2 | 2010-09-10 22:38:40 +0000 | [diff] [blame] | 372 | forAttribute = forAttribute.stripWhiteSpace(); |
| 373 | if (!equalIgnoringCase(forAttribute, "window")) |
| 374 | return false; |
simonjam@chromium.org | 4879ffa | 2011-02-19 09:39:06 +0000 | [diff] [blame] | 375 | |
tonyg@chromium.org | bd35ae2 | 2010-09-10 22:38:40 +0000 | [diff] [blame] | 376 | eventAttribute = eventAttribute.stripWhiteSpace(); |
| 377 | if (!equalIgnoringCase(eventAttribute, "onload") && !equalIgnoringCase(eventAttribute, "onload()")) |
| 378 | return false; |
| 379 | } |
tonyg@chromium.org | bd35ae2 | 2010-09-10 22:38:40 +0000 | [diff] [blame] | 380 | return true; |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 381 | } |
| 382 | |
rniwa@webkit.org | f827848 | 2010-11-17 18:56:45 +0000 | [diff] [blame] | 383 | String ScriptElement::scriptContent() const |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 384 | { |
cdumez@apple.com | b7f4850 | 2015-01-26 22:36:36 +0000 | [diff] [blame] | 385 | return TextNodeTraversal::contentsAsString(m_element); |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 386 | } |
| 387 | |
pdr@google.com | b38b6ff | 2013-03-28 05:04:38 +0000 | [diff] [blame] | 388 | ScriptElement* toScriptElementIfPossible(Element* element) |
zimmermann@webkit.org | 67ac8f8 | 2009-01-21 19:49:37 +0000 | [diff] [blame] | 389 | { |
cdumez@apple.com | a9c60c9 | 2014-10-02 19:39:41 +0000 | [diff] [blame] | 390 | if (is<HTMLScriptElement>(*element)) |
cdumez@apple.com | 72754ba | 2014-09-23 22:03:15 +0000 | [diff] [blame] | 391 | return downcast<HTMLScriptElement>(element); |
zimmermann@webkit.org | 67ac8f8 | 2009-01-21 19:49:37 +0000 | [diff] [blame] | 392 | |
cdumez@apple.com | a9c60c9 | 2014-10-02 19:39:41 +0000 | [diff] [blame] | 393 | if (is<SVGScriptElement>(*element)) |
cdumez@apple.com | 7487b35 | 2014-09-23 00:55:05 +0000 | [diff] [blame] | 394 | return downcast<SVGScriptElement>(element); |
zimmermann@webkit.org | 67ac8f8 | 2009-01-21 19:49:37 +0000 | [diff] [blame] | 395 | |
cdumez@apple.com | 7487b35 | 2014-09-23 00:55:05 +0000 | [diff] [blame] | 396 | return nullptr; |
zimmermann@webkit.org | 67ac8f8 | 2009-01-21 19:49:37 +0000 | [diff] [blame] | 397 | } |
| 398 | |
zimmermann@webkit.org | 9ae47e9 | 2008-08-14 02:22:35 +0000 | [diff] [blame] | 399 | } |