Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: Source/core/dom/ScriptLoader.cpp

Issue 19762002: [HTML Imports] Let script of imported document running. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Updated to ToT Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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/HTMLImport.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/CachedScript.h" 41 #include "core/loader/cache/CachedScript.h"
41 #include "core/loader/cache/FetchRequest.h" 42 #include "core/loader/cache/FetchRequest.h"
42 #include "core/loader/cache/ResourceFetcher.h" 43 #include "core/loader/cache/ResourceFetcher.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
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
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 FetchRequest request(ResourceRequest(m_element->document()->completeURL( sourceUrl)), m_element->localName()); 276 FetchRequest request(ResourceRequest(elementDocument->completeURL(source Url)), 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);
abarth-chromium 2013/07/26 17:17:34 This one is slightly tricky. I guess this is corr
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()->fetcher()->requestScript(request ); 289 m_cachedScript = elementDocument->fetcher()->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()) || elementDocument->contentSecuri tyPolicy()->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 && ! elementDocument->contentSecurityPolicy()->allowInlineScript(elementDocument->url (), m_startLineNumber)))
314 return; 325 return;
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.");
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
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()->fetcher()->canAccess(m_cachedScript.get())) { 386 if (!elementDocument->fetcher()->canAccess(m_cachedScript.get())) {
abarth-chromium 2013/07/26 17:17:34 This one is important to test too
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698