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 reserv ed. | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserv ed. |
6 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> | 6 * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org> |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 17 matching lines...) Expand all Loading... | |
28 #include "SVGNames.h" | 28 #include "SVGNames.h" |
29 #include "bindings/v8/ScriptController.h" | 29 #include "bindings/v8/ScriptController.h" |
30 #include "bindings/v8/ScriptSourceCode.h" | 30 #include "bindings/v8/ScriptSourceCode.h" |
31 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
32 #include "core/dom/Event.h" | 32 #include "core/dom/Event.h" |
33 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" | 33 #include "core/dom/IgnoreDestructiveWriteCountIncrementer.h" |
34 #include "core/dom/ScriptLoaderClient.h" | 34 #include "core/dom/ScriptLoaderClient.h" |
35 #include "core/dom/ScriptRunner.h" | 35 #include "core/dom/ScriptRunner.h" |
36 #include "core/dom/ScriptableDocumentParser.h" | 36 #include "core/dom/ScriptableDocumentParser.h" |
37 #include "core/dom/Text.h" | 37 #include "core/dom/Text.h" |
38 #include "core/html/HTMLImportsController.h" | |
38 #include "core/html/HTMLScriptElement.h" | 39 #include "core/html/HTMLScriptElement.h" |
39 #include "core/html/parser/HTMLParserIdioms.h" | 40 #include "core/html/parser/HTMLParserIdioms.h" |
40 #include "core/loader/cache/CachedResourceLoader.h" | 41 #include "core/loader/cache/CachedResourceLoader.h" |
41 #include "core/loader/cache/CachedResourceRequest.h" | 42 #include "core/loader/cache/CachedResourceRequest.h" |
42 #include "core/loader/cache/CachedScript.h" | 43 #include "core/loader/cache/CachedScript.h" |
43 #include "core/page/ContentSecurityPolicy.h" | 44 #include "core/page/ContentSecurityPolicy.h" |
44 #include "core/page/Frame.h" | 45 #include "core/page/Frame.h" |
45 #include "core/platform/MIMETypeRegistry.h" | 46 #include "core/platform/MIMETypeRegistry.h" |
46 #include "core/svg/SVGScriptElement.h" | 47 #include "core/svg/SVGScriptElement.h" |
47 #include "weborigin/SecurityOrigin.h" | 48 #include "weborigin/SecurityOrigin.h" |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
158 type = "text/" + language.lower(); | 159 type = "text/" + language.lower(); |
159 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type) || isLegacySup portedJavaScriptLanguage(language)) | 160 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type) || isLegacySup portedJavaScriptLanguage(language)) |
160 return true; | 161 return true; |
161 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSp ace().lower()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLeg acySupportedJavaScriptLanguage(type))) { | 162 } else if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(type.stripWhiteSp ace().lower()) || (supportLegacyTypes == AllowLegacyTypeInTypeAttribute && isLeg acySupportedJavaScriptLanguage(type))) { |
162 return true; | 163 return true; |
163 } | 164 } |
164 | 165 |
165 return false; | 166 return false; |
166 } | 167 } |
167 | 168 |
169 Document* ScriptLoader::executingDocument() const | |
170 { | |
171 Document* document = m_element->document(); | |
172 if (!document->import()) | |
173 return document; | |
174 return document->import()->master(); | |
175 } | |
176 | |
168 // http://dev.w3.org/html5/spec/Overview.html#prepare-a-script | 177 // http://dev.w3.org/html5/spec/Overview.html#prepare-a-script |
169 bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy TypeSupport supportLegacyTypes) | 178 bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition, Legacy TypeSupport supportLegacyTypes) |
170 { | 179 { |
171 if (m_alreadyStarted) | 180 if (m_alreadyStarted) |
172 return false; | 181 return false; |
173 | 182 |
174 ScriptLoaderClient* client = this->client(); | 183 ScriptLoaderClient* client = this->client(); |
175 | 184 |
176 bool wasParserInserted; | 185 bool wasParserInserted; |
177 if (m_parserInserted) { | 186 if (m_parserInserted) { |
(...skipping 17 matching lines...) Expand all Loading... | |
195 return false; | 204 return false; |
196 | 205 |
197 if (wasParserInserted) { | 206 if (wasParserInserted) { |
198 m_parserInserted = true; | 207 m_parserInserted = true; |
199 m_forceAsync = false; | 208 m_forceAsync = false; |
200 } | 209 } |
201 | 210 |
202 m_alreadyStarted = true; | 211 m_alreadyStarted = true; |
203 | 212 |
204 // FIXME: If script is parser inserted, verify it's still in the original do cument. | 213 // FIXME: If script is parser inserted, verify it's still in the original do cument. |
205 Document* document = m_element->document(); | 214 Document* executingDocument = this->executingDocument(); |
215 Document* elementDocument = m_element->document(); | |
206 | 216 |
207 // FIXME: Eventually we'd like to evaluate scripts which are inserted into a | 217 // FIXME: Eventually we'd like to evaluate scripts which are inserted into a |
208 // viewless document but this'll do for now. | 218 // viewless document but this'll do for now. |
209 // See http://bugs.webkit.org/show_bug.cgi?id=5727 | 219 // See http://bugs.webkit.org/show_bug.cgi?id=5727 |
210 if (!document->frame()) | 220 if (!executingDocument->frame()) |
211 return false; | 221 return false; |
212 | 222 |
213 if (!document->frame()->script()->canExecuteScripts(AboutToExecuteScript)) | 223 if (!executingDocument->frame()->script()->canExecuteScripts(AboutToExecuteS cript)) |
214 return false; | 224 return false; |
215 | 225 |
216 if (!isScriptForEventSupported()) | 226 if (!isScriptForEventSupported()) |
217 return false; | 227 return false; |
218 | 228 |
219 if (!client->charsetAttributeValue().isEmpty()) | 229 if (!client->charsetAttributeValue().isEmpty()) |
220 m_characterEncoding = client->charsetAttributeValue(); | 230 m_characterEncoding = client->charsetAttributeValue(); |
221 else | 231 else |
222 m_characterEncoding = document->charset(); | 232 m_characterEncoding = elementDocument->charset(); |
223 | 233 |
224 if (client->hasSourceAttribute()) { | 234 if (client->hasSourceAttribute()) { |
225 if (!requestScript(client->sourceAttributeValue())) | 235 if (!requestScript(client->sourceAttributeValue())) |
226 return false; | 236 return false; |
227 } | 237 } |
228 | 238 |
229 if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parse rInserted && !client->asyncAttributeValue()) { | 239 if (client->hasSourceAttribute() && client->deferAttributeValue() && m_parse rInserted && !client->asyncAttributeValue()) { |
230 m_willExecuteWhenDocumentFinishedParsing = true; | 240 m_willExecuteWhenDocumentFinishedParsing = true; |
231 m_willBeParserExecuted = true; | 241 m_willBeParserExecuted = true; |
232 } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyn cAttributeValue()) { | 242 } else if (client->hasSourceAttribute() && m_parserInserted && !client->asyn cAttributeValue()) { |
233 m_willBeParserExecuted = true; | 243 m_willBeParserExecuted = true; |
234 } else if (!client->hasSourceAttribute() && m_parserInserted && !document->h aveStylesheetsAndImportsLoaded()) { | 244 } else if (!client->hasSourceAttribute() && m_parserInserted && !elementDocu ment->haveStylesheetsAndImportsLoaded()) { |
235 m_willBeParserExecuted = true; | 245 m_willBeParserExecuted = true; |
236 m_readyToBeParserExecuted = true; | 246 m_readyToBeParserExecuted = true; |
237 } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) { | 247 } else if (client->hasSourceAttribute() && !client->asyncAttributeValue() && !m_forceAsync) { |
238 m_willExecuteInOrder = true; | 248 m_willExecuteInOrder = true; |
239 document->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::IN_ORDER_EXECUTION); | 249 executingDocument->scriptRunner()->queueScriptForExecution(this, m_cache dScript, ScriptRunner::IN_ORDER_EXECUTION); |
240 m_cachedScript->addClient(this); | 250 m_cachedScript->addClient(this); |
241 } else if (client->hasSourceAttribute()) { | 251 } else if (client->hasSourceAttribute()) { |
242 document->scriptRunner()->queueScriptForExecution(this, m_cachedScript, ScriptRunner::ASYNC_EXECUTION); | 252 executingDocument->scriptRunner()->queueScriptForExecution(this, m_cache dScript, ScriptRunner::ASYNC_EXECUTION); |
243 m_cachedScript->addClient(this); | 253 m_cachedScript->addClient(this); |
244 } else { | 254 } else { |
245 // Reset line numbering for nested writes. | 255 // Reset line numbering for nested writes. |
246 TextPosition position = document->isInDocumentWrite() ? TextPosition() : scriptStartPosition; | 256 TextPosition position = elementDocument->isInDocumentWrite() ? TextPosit ion() : scriptStartPosition; |
247 KURL scriptURL = (!document->isInDocumentWrite() && m_parserInserted) ? document->url() : KURL(); | 257 KURL scriptURL = (!elementDocument->isInDocumentWrite() && m_parserInser ted) ? elementDocument->url() : KURL(); |
248 executeScript(ScriptSourceCode(scriptContent(), scriptURL, position)); | 258 executeScript(ScriptSourceCode(scriptContent(), scriptURL, position)); |
249 } | 259 } |
250 | 260 |
251 return true; | 261 return true; |
252 } | 262 } |
253 | 263 |
254 bool ScriptLoader::requestScript(const String& sourceUrl) | 264 bool ScriptLoader::requestScript(const String& sourceUrl) |
255 { | 265 { |
256 ASSERT(m_element); | 266 ASSERT(m_element); |
257 | 267 |
258 RefPtr<Document> originalDocument = m_element->document(); | 268 RefPtr<Document> elementDocument = m_element->document(); |
259 if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) | 269 if (!m_element->dispatchBeforeLoadEvent(sourceUrl)) |
260 return false; | 270 return false; |
261 if (!m_element->inDocument() || m_element->document() != originalDocument) | 271 if (!m_element->inDocument() || m_element->document() != elementDocument) |
262 return false; | 272 return false; |
263 | 273 |
264 ASSERT(!m_cachedScript); | 274 ASSERT(!m_cachedScript); |
265 if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { | 275 if (!stripLeadingAndTrailingHTMLSpaces(sourceUrl).isEmpty()) { |
266 CachedResourceRequest request(ResourceRequest(m_element->document()->com pleteURL(sourceUrl)), m_element->localName()); | 276 CachedResourceRequest request(ResourceRequest(elementDocument->completeU RL(sourceUrl)), m_element->localName()); |
267 | 277 |
268 String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossori ginAttr); | 278 String crossOriginMode = m_element->fastGetAttribute(HTMLNames::crossori ginAttr); |
269 if (!crossOriginMode.isNull()) { | 279 if (!crossOriginMode.isNull()) { |
270 StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMo de, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; | 280 StoredCredentials allowCredentials = equalIgnoringCase(crossOriginMo de, "use-credentials") ? AllowStoredCredentials : DoNotAllowStoredCredentials; |
271 request.setPotentiallyCrossOriginEnabled(m_element->document()->secu rityOrigin(), allowCredentials); | 281 request.setPotentiallyCrossOriginEnabled(elementDocument->securityOr igin(), allowCredentials); |
272 } | 282 } |
273 request.setCharset(scriptCharset()); | 283 request.setCharset(scriptCharset()); |
274 | 284 |
275 bool isValidScriptNonce = m_element->document()->contentSecurityPolicy() ->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)); | 285 bool isValidScriptNonce = elementDocument->contentSecurityPolicy()->allo wScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)); |
276 if (isValidScriptNonce) | 286 if (isValidScriptNonce) |
277 request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy); | 287 request.setContentSecurityCheck(DoNotCheckContentSecurityPolicy); |
278 | 288 |
279 m_cachedScript = m_element->document()->cachedResourceLoader()->requestS cript(request); | 289 m_cachedScript = elementDocument->cachedResourceLoader()->requestScript( request); |
280 m_isExternalScript = true; | 290 m_isExternalScript = true; |
281 } | 291 } |
282 | 292 |
283 if (m_cachedScript) { | 293 if (m_cachedScript) { |
284 return true; | 294 return true; |
285 } | 295 } |
286 | 296 |
287 dispatchErrorEvent(); | 297 dispatchErrorEvent(); |
288 return false; | 298 return false; |
289 } | 299 } |
290 | 300 |
291 bool isHTMLScriptLoader(Element* element) | 301 bool isHTMLScriptLoader(Element* element) |
292 { | 302 { |
293 return element->hasTagName(HTMLNames::scriptTag); | 303 return element->hasTagName(HTMLNames::scriptTag); |
294 } | 304 } |
295 | 305 |
296 bool isSVGScriptLoader(Element* element) | 306 bool isSVGScriptLoader(Element* element) |
297 { | 307 { |
298 return element->hasTagName(SVGNames::scriptTag); | 308 return element->hasTagName(SVGNames::scriptTag); |
299 } | 309 } |
300 | 310 |
301 void ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) | 311 void ScriptLoader::executeScript(const ScriptSourceCode& sourceCode) |
302 { | 312 { |
303 ASSERT(m_alreadyStarted); | 313 ASSERT(m_alreadyStarted); |
304 | 314 |
305 if (sourceCode.isEmpty()) | 315 if (sourceCode.isEmpty()) |
306 return; | 316 return; |
307 | 317 |
308 RefPtr<Document> document = m_element->document(); | 318 RefPtr<Document> executingDocument = this->executingDocument(); |
309 Frame* frame = document->frame(); | 319 RefPtr<Document> elementDocument = m_element->document(); |
320 Frame* frame = executingDocument->frame(); | |
310 | 321 |
311 bool shouldBypassMainWorldContentSecurityPolicy = (frame && frame->script()- >shouldBypassMainWorldContentSecurityPolicy()) || document->contentSecurityPolic y()->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr)); | 322 bool shouldBypassMainWorldContentSecurityPolicy = (frame && frame->script()- >shouldBypassMainWorldContentSecurityPolicy()) || executingDocument->contentSecu rityPolicy()->allowScriptNonce(m_element->fastGetAttribute(HTMLNames::nonceAttr) ); |
312 | 323 |
313 if (!m_isExternalScript && (!shouldBypassMainWorldContentSecurityPolicy && ! document->contentSecurityPolicy()->allowInlineScript(document->url(), m_startLin eNumber))) | 324 if (!m_isExternalScript && (!shouldBypassMainWorldContentSecurityPolicy && ! executingDocument->contentSecurityPolicy()->allowInlineScript(elementDocument->u rl(), m_startLineNumber))) |
314 return; | 325 return; |
abarth-chromium
2013/07/19 07:55:55
I'm not sure whether this check is right. I think
| |
315 | 326 |
316 if (m_isExternalScript && m_cachedScript && !m_cachedScript->mimeTypeAllowed ByNosniff()) { | 327 if (m_isExternalScript && m_cachedScript && !m_cachedScript->mimeTypeAllowed ByNosniff()) { |
317 document->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "R efused to execute script from '" + m_cachedScript->url().elidedString() + "' bec ause its MIME type ('" + m_cachedScript->mimeType() + "') is not executable, and strict MIME type checking is enabled."); | 328 executingDocument->addConsoleMessage(SecurityMessageSource, ErrorMessage Level, "Refused to execute script from '" + m_cachedScript->url().elidedString() + "' because its MIME type ('" + m_cachedScript->mimeType() + "') is not execut able, and strict MIME type checking is enabled."); |
abarth-chromium
2013/07/19 07:55:55
Please add a test for this case as well.
| |
318 return; | 329 return; |
319 } | 330 } |
320 | 331 |
321 if (frame) { | 332 if (frame) { |
322 IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncre menter(m_isExternalScript ? document.get() : 0); | 333 IgnoreDestructiveWriteCountIncrementer ignoreDesctructiveWriteCountIncre menter(m_isExternalScript ? executingDocument.get() : 0); |
323 | 334 |
324 if (isHTMLScriptLoader(m_element)) | 335 if (isHTMLScriptLoader(m_element)) |
325 document->pushCurrentScript(toHTMLScriptElement(m_element)); | 336 executingDocument->pushCurrentScript(toHTMLScriptElement(m_element)) ; |
326 | 337 |
327 // Create a script from the script element node, using the script | 338 // Create a script from the script element node, using the script |
328 // block's source and the script block's type. | 339 // block's source and the script block's type. |
329 // Note: This is where the script is compiled and actually executed. | 340 // Note: This is where the script is compiled and actually executed. |
330 frame->script()->executeScriptInMainWorld(sourceCode); | 341 frame->script()->executeScriptInMainWorld(sourceCode); |
331 | 342 |
332 if (isHTMLScriptLoader(m_element)) { | 343 if (isHTMLScriptLoader(m_element)) { |
333 ASSERT(document->currentScript() == m_element); | 344 ASSERT(executingDocument->currentScript() == m_element); |
334 document->popCurrentScript(); | 345 executingDocument->popCurrentScript(); |
335 } | 346 } |
336 } | 347 } |
337 } | 348 } |
338 | 349 |
339 void ScriptLoader::stopLoadRequest() | 350 void ScriptLoader::stopLoadRequest() |
340 { | 351 { |
341 if (m_cachedScript) { | 352 if (m_cachedScript) { |
342 if (!m_willBeParserExecuted) | 353 if (!m_willBeParserExecuted) |
343 m_cachedScript->removeClient(this); | 354 m_cachedScript->removeClient(this); |
344 m_cachedScript = 0; | 355 m_cachedScript = 0; |
(...skipping 10 matching lines...) Expand all Loading... | |
355 executeScript(ScriptSourceCode(cachedScript)); | 366 executeScript(ScriptSourceCode(cachedScript)); |
356 dispatchLoadEvent(); | 367 dispatchLoadEvent(); |
357 } | 368 } |
358 cachedScript->removeClient(this); | 369 cachedScript->removeClient(this); |
359 } | 370 } |
360 | 371 |
361 void ScriptLoader::notifyFinished(CachedResource* resource) | 372 void ScriptLoader::notifyFinished(CachedResource* resource) |
362 { | 373 { |
363 ASSERT(!m_willBeParserExecuted); | 374 ASSERT(!m_willBeParserExecuted); |
364 | 375 |
376 RefPtr<Document> executingDocument = this->executingDocument(); | |
377 RefPtr<Document> elementDocument = m_element->document(); | |
378 | |
365 // CachedResource possibly invokes this notifyFinished() more than | 379 // CachedResource possibly invokes this notifyFinished() more than |
366 // once because ScriptLoader doesn't unsubscribe itself from | 380 // once because ScriptLoader doesn't unsubscribe itself from |
367 // CachedResource here and does it in execute() instead. | 381 // CachedResource here and does it in execute() instead. |
368 // We use m_cachedScript to check if this function is already called. | 382 // We use m_cachedScript to check if this function is already called. |
369 ASSERT_UNUSED(resource, resource == m_cachedScript); | 383 ASSERT_UNUSED(resource, resource == m_cachedScript); |
370 if (!m_cachedScript) | 384 if (!m_cachedScript) |
371 return; | 385 return; |
372 if (!m_element->document()->cachedResourceLoader()->canAccess(m_cachedScript .get())) { | 386 if (!elementDocument->cachedResourceLoader()->canAccess(m_cachedScript.get() )) { |
373 dispatchErrorEvent(); | 387 dispatchErrorEvent(); |
374 return; | 388 return; |
375 } | 389 } |
376 | 390 |
377 if (m_willExecuteInOrder) | 391 if (m_willExecuteInOrder) |
378 m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRun ner::IN_ORDER_EXECUTION); | 392 executingDocument->scriptRunner()->notifyScriptReady(this, ScriptRunner: :IN_ORDER_EXECUTION); |
379 else | 393 else |
380 m_element->document()->scriptRunner()->notifyScriptReady(this, ScriptRun ner::ASYNC_EXECUTION); | 394 executingDocument->scriptRunner()->notifyScriptReady(this, ScriptRunner: :ASYNC_EXECUTION); |
381 | 395 |
382 m_cachedScript = 0; | 396 m_cachedScript = 0; |
383 } | 397 } |
384 | 398 |
385 bool ScriptLoader::ignoresLoadRequest() const | 399 bool ScriptLoader::ignoresLoadRequest() const |
386 { | 400 { |
387 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen t() || !element()->inDocument(); | 401 return m_alreadyStarted || m_isExternalScript || m_parserInserted || !elemen t() || !element()->inDocument(); |
388 } | 402 } |
389 | 403 |
390 bool ScriptLoader::isScriptForEventSupported() const | 404 bool ScriptLoader::isScriptForEventSupported() const |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 if (isHTMLScriptLoader(element)) | 439 if (isHTMLScriptLoader(element)) |
426 return toHTMLScriptElement(element)->loader(); | 440 return toHTMLScriptElement(element)->loader(); |
427 | 441 |
428 if (isSVGScriptLoader(element)) | 442 if (isSVGScriptLoader(element)) |
429 return toSVGScriptElement(element)->loader(); | 443 return toSVGScriptElement(element)->loader(); |
430 | 444 |
431 return 0; | 445 return 0; |
432 } | 446 } |
433 | 447 |
434 } | 448 } |
OLD | NEW |