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

Side by Side Diff: third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp

Issue 1772853002: Block the HTML parser on external stylesheets (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Simplified parser blocking logic Created 4 years, 9 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 13 matching lines...) Expand all
24 */ 24 */
25 25
26 #include "core/html/parser/HTMLDocumentParser.h" 26 #include "core/html/parser/HTMLDocumentParser.h"
27 27
28 #include "core/HTMLNames.h" 28 #include "core/HTMLNames.h"
29 #include "core/css/MediaValuesCached.h" 29 #include "core/css/MediaValuesCached.h"
30 #include "core/css/resolver/StyleResolver.h" 30 #include "core/css/resolver/StyleResolver.h"
31 #include "core/dom/DocumentFragment.h" 31 #include "core/dom/DocumentFragment.h"
32 #include "core/dom/DocumentLifecycleObserver.h" 32 #include "core/dom/DocumentLifecycleObserver.h"
33 #include "core/dom/Element.h" 33 #include "core/dom/Element.h"
34 #include "core/dom/StyleEngine.h"
34 #include "core/frame/LocalFrame.h" 35 #include "core/frame/LocalFrame.h"
35 #include "core/frame/Settings.h" 36 #include "core/frame/Settings.h"
36 #include "core/html/HTMLDocument.h" 37 #include "core/html/HTMLDocument.h"
37 #include "core/html/parser/AtomicHTMLToken.h" 38 #include "core/html/parser/AtomicHTMLToken.h"
38 #include "core/html/parser/BackgroundHTMLParser.h" 39 #include "core/html/parser/BackgroundHTMLParser.h"
39 #include "core/html/parser/HTMLParserScheduler.h" 40 #include "core/html/parser/HTMLParserScheduler.h"
40 #include "core/html/parser/HTMLParserThread.h" 41 #include "core/html/parser/HTMLParserThread.h"
41 #include "core/html/parser/HTMLScriptRunner.h" 42 #include "core/html/parser/HTMLScriptRunner.h"
42 #include "core/html/parser/HTMLTreeBuilder.h" 43 #include "core/html/parser/HTMLTreeBuilder.h"
43 #include "core/inspector/InspectorInstrumentation.h" 44 #include "core/inspector/InspectorInstrumentation.h"
44 #include "core/inspector/InspectorTraceEvents.h" 45 #include "core/inspector/InspectorTraceEvents.h"
45 #include "core/loader/DocumentLoader.h" 46 #include "core/loader/DocumentLoader.h"
46 #include "core/loader/NavigationScheduler.h" 47 #include "core/loader/NavigationScheduler.h"
48 #include "platform/RuntimeEnabledFeatures.h"
47 #include "platform/SharedBuffer.h" 49 #include "platform/SharedBuffer.h"
48 #include "platform/ThreadSafeFunctional.h" 50 #include "platform/ThreadSafeFunctional.h"
49 #include "platform/TraceEvent.h" 51 #include "platform/TraceEvent.h"
50 #include "platform/heap/Handle.h" 52 #include "platform/heap/Handle.h"
51 #include "public/platform/Platform.h" 53 #include "public/platform/Platform.h"
52 #include "public/platform/WebFrameScheduler.h" 54 #include "public/platform/WebFrameScheduler.h"
53 #include "public/platform/WebScheduler.h" 55 #include "public/platform/WebScheduler.h"
54 #include "public/platform/WebThread.h" 56 #include "public/platform/WebThread.h"
55 #include "wtf/RefCounted.h" 57 #include "wtf/RefCounted.h"
56 #include "wtf/TemporaryChange.h" 58 #include "wtf/TemporaryChange.h"
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 return m_treeBuilder->isParsingFragment(); 261 return m_treeBuilder->isParsingFragment();
260 } 262 }
261 263
262 bool HTMLDocumentParser::processingData() const 264 bool HTMLDocumentParser::processingData() const
263 { 265 {
264 return isScheduledForResume() || inPumpSession() || m_haveBackgroundParser; 266 return isScheduledForResume() || inPumpSession() || m_haveBackgroundParser;
265 } 267 }
266 268
267 void HTMLDocumentParser::pumpTokenizerIfPossible() 269 void HTMLDocumentParser::pumpTokenizerIfPossible()
268 { 270 {
269 if (isStopped() || isWaitingForScripts()) 271 if (isStopped() || isWaitingForBlockingResource())
270 return; 272 return;
271 273
272 pumpTokenizer(); 274 pumpTokenizer();
273 } 275 }
274 276
275 bool HTMLDocumentParser::isScheduledForResume() const 277 bool HTMLDocumentParser::isScheduledForResume() const
276 { 278 {
277 return m_parserScheduler && m_parserScheduler->isScheduledForResume(); 279 return m_parserScheduler && m_parserScheduler->isScheduledForResume();
278 } 280 }
279 281
(...skipping 27 matching lines...) Expand all
307 309
308 if (isWaitingForScripts()) { 310 if (isWaitingForScripts()) {
309 // If we're paused waiting for a script, we try to execute scripts befor e continuing. 311 // If we're paused waiting for a script, we try to execute scripts befor e continuing.
310 runScriptsForPausedTreeBuilder(); 312 runScriptsForPausedTreeBuilder();
311 if (isStopped()) 313 if (isStopped())
312 return false; 314 return false;
313 if (isWaitingForScripts()) 315 if (isWaitingForScripts())
314 return false; 316 return false;
315 } 317 }
316 318
319 if (isWaitingForStyles() || isWaitingForImports())
320 return false;
321
317 // FIXME: It's wrong for the HTMLDocumentParser to reach back to the 322 // FIXME: It's wrong for the HTMLDocumentParser to reach back to the
318 // LocalFrame, but this approach is how the old parser handled 323 // LocalFrame, but this approach is how the old parser handled
319 // stopping when the page assigns window.location. What really 324 // stopping when the page assigns window.location. What really
320 // should happen is that assigning window.location causes the 325 // should happen is that assigning window.location causes the
321 // parser to stop parsing cleanly. The problem is we're not 326 // parser to stop parsing cleanly. The problem is we're not
322 // perpared to do that at every point where we run JavaScript. 327 // perpared to do that at every point where we run JavaScript.
323 if (!isParsingFragment() 328 if (!isParsingFragment()
324 && document()->frame() && document()->frame()->navigationScheduler().loc ationChangePending()) 329 && document()->frame() && document()->frame()->navigationScheduler().loc ationChangePending())
325 return false; 330 return false;
326 331
(...skipping 24 matching lines...) Expand all
351 // the document element is available, as we empty the queue immediately 356 // the document element is available, as we empty the queue immediately
352 // after the document element is created in pumpPendingSpeculations(). 357 // after the document element is created in pumpPendingSpeculations().
353 ASSERT(m_queuedPreloads.isEmpty()); 358 ASSERT(m_queuedPreloads.isEmpty());
354 for (auto& chunk : pendingChunks) 359 for (auto& chunk : pendingChunks)
355 m_preloader->takeAndPreload(chunk->preloads); 360 m_preloader->takeAndPreload(chunk->preloads);
356 } 361 }
357 362
358 for (auto& chunk : pendingChunks) 363 for (auto& chunk : pendingChunks)
359 m_speculations.append(chunk.release()); 364 m_speculations.append(chunk.release());
360 365
361 if (!isWaitingForScripts() && !isScheduledForResume()) { 366 if (!isWaitingForBlockingResource() && !isScheduledForResume()) {
362 if (m_tasksWereSuspended) 367 if (m_tasksWereSuspended)
363 m_parserScheduler->forceResumeAfterYield(); 368 m_parserScheduler->forceResumeAfterYield();
364 else 369 else
365 m_parserScheduler->scheduleForResume(); 370 m_parserScheduler->scheduleForResume();
366 } 371 }
367 } 372 }
368 373
369 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume ntEncodingData& data) 374 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume ntEncodingData& data)
370 { 375 {
371 document()->setEncodingData(data); 376 document()->setEncodingData(data);
372 } 377 }
373 378
374 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk) 379 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk)
375 { 380 {
376 ASSERT(chunk); 381 ASSERT(chunk);
377 if (isWaitingForScripts()) { 382 if (isWaitingForBlockingResource()) {
378 // We're waiting on a network script, just save the chunk, we'll get 383 // We're waiting on a blocking resource, just save the chunk, we'll get
379 // a second validateSpeculations call after the script completes. 384 // a second validateSpeculations call after the resource completes.
380 // This call should have been made immediately after runScriptsForPaused TreeBuilder 385 // This call should have been made immediately after runScriptsForPaused TreeBuilder
381 // which may have started a network load and left us waiting. 386 // in the case of a script which may have started a network load and lef t us waiting.
382 ASSERT(!m_lastChunkBeforeScript); 387 ASSERT(!m_lastChunkBeforeBlockingResource);
383 m_lastChunkBeforeScript = chunk; 388 m_lastChunkBeforeBlockingResource = chunk;
384 return; 389 return;
385 } 390 }
386 391
387 ASSERT(!m_lastChunkBeforeScript); 392 ASSERT(!m_lastChunkBeforeBlockingResource);
388 OwnPtr<HTMLTokenizer> tokenizer = m_tokenizer.release(); 393 OwnPtr<HTMLTokenizer> tokenizer = m_tokenizer.release();
389 OwnPtr<HTMLToken> token = m_token.release(); 394 OwnPtr<HTMLToken> token = m_token.release();
390 395
391 if (!tokenizer) { 396 if (!tokenizer) {
392 // There must not have been any changes to the HTMLTokenizer state on 397 // There must not have been any changes to the HTMLTokenizer state on
393 // the main thread, which means the speculation buffer is correct. 398 // the main thread, which means the speculation buffer is correct.
394 return; 399 return;
395 } 400 }
396 401
397 // Currently we're only smart enough to reuse the speculation buffer if the tokenizer 402 // Currently we're only smart enough to reuse the speculation buffer if the tokenizer
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
429 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::r esumeFrom, AllowCrossThreadAccess(m_backgroundParser), checkpoint.release())); 434 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::r esumeFrom, AllowCrossThreadAccess(m_backgroundParser), checkpoint.release()));
430 } 435 }
431 436
432 size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Par sedChunk> popChunk) 437 size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Par sedChunk> popChunk)
433 { 438 {
434 TRACE_EVENT0("blink", "HTMLDocumentParser::processParsedChunkFromBackgroundP arser"); 439 TRACE_EVENT0("blink", "HTMLDocumentParser::processParsedChunkFromBackgroundP arser");
435 TemporaryChange<bool> hasLineNumber(m_isParsingAtLineNumber, true); 440 TemporaryChange<bool> hasLineNumber(m_isParsingAtLineNumber, true);
436 441
437 ASSERT_WITH_SECURITY_IMPLICATION(document()->activeParserCount() == 1); 442 ASSERT_WITH_SECURITY_IMPLICATION(document()->activeParserCount() == 1);
438 ASSERT(!isParsingFragment()); 443 ASSERT(!isParsingFragment());
439 ASSERT(!isWaitingForScripts()); 444 ASSERT(!isWaitingForBlockingResource());
440 ASSERT(!isStopped()); 445 ASSERT(!isStopped());
441 #if !ENABLE(OILPAN) 446 #if !ENABLE(OILPAN)
442 // ASSERT that this object is both attached to the Document and protected. 447 // ASSERT that this object is both attached to the Document and protected.
443 ASSERT(refCount() >= 2); 448 ASSERT(refCount() >= 2);
444 #endif 449 #endif
445 ASSERT(shouldUseThreading()); 450 ASSERT(shouldUseThreading());
446 ASSERT(!m_tokenizer); 451 ASSERT(!m_tokenizer);
447 ASSERT(!m_token); 452 ASSERT(!m_token);
448 ASSERT(!m_lastChunkBeforeScript); 453 ASSERT(!m_lastChunkBeforeBlockingResource);
449 454
450 OwnPtr<ParsedChunk> chunk(popChunk); 455 OwnPtr<ParsedChunk> chunk(popChunk);
451 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); 456 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release();
452 size_t elementTokenCount = 0; 457 size_t elementTokenCount = 0;
453 458
454 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::s tartedChunkWithCheckpoint, AllowCrossThreadAccess(m_backgroundParser), chunk->in putCheckpoint)); 459 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::s tartedChunkWithCheckpoint, AllowCrossThreadAccess(m_backgroundParser), chunk->in putCheckpoint));
455 460
456 for (const auto& xssInfo : chunk->xssInfos) { 461 for (const auto& xssInfo : chunk->xssInfos) {
457 m_textPosition = xssInfo->m_textPosition; 462 m_textPosition = xssInfo->m_textPosition;
458 m_xssAuditorDelegate.didBlockScript(*xssInfo); 463 m_xssAuditorDelegate.didBlockScript(*xssInfo);
459 if (isStopped()) 464 if (isStopped())
460 break; 465 break;
461 } 466 }
462 // XSSAuditorDelegate can detach the parser if it decides to block the entir e current document. 467 // XSSAuditorDelegate can detach the parser if it decides to block the entir e current document.
463 if (isDetached()) 468 if (isDetached())
464 return elementTokenCount; 469 return elementTokenCount;
465 470
466 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != to kens->end(); ++it) { 471 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != to kens->end(); ++it) {
467 ASSERT(!isWaitingForScripts()); 472 ASSERT(!isWaitingForBlockingResource());
468 473
469 if (!chunk->startingScript && (it->type() == HTMLToken::StartTag || it-> type() == HTMLToken::EndTag)) 474 if (!chunk->startingScript && (it->type() == HTMLToken::StartTag || it-> type() == HTMLToken::EndTag))
470 elementTokenCount++; 475 elementTokenCount++;
471 476
472 if (document()->frame() && document()->frame()->navigationScheduler().lo cationChangePending()) { 477 if (document()->frame() && document()->frame()->navigationScheduler().lo cationChangePending()) {
473 478
474 // To match main-thread parser behavior (which never checks location ChangePending on the EOF path) 479 // To match main-thread parser behavior (which never checks location ChangePending on the EOF path)
475 // we peek to see if this chunk has an EOF and process it anyway. 480 // we peek to see if this chunk has an EOF and process it anyway.
476 if (tokens->last().type() == HTMLToken::EndOfFile) { 481 if (tokens->last().type() == HTMLToken::EndOfFile) {
477 ASSERT(m_speculations.isEmpty()); // There should never be any c hunks after the EOF. 482 ASSERT(m_speculations.isEmpty()); // There should never be any c hunks after the EOF.
(...skipping 12 matching lines...) Expand all
490 if (!m_queuedPreloads.isEmpty() && document()->documentElement()) 495 if (!m_queuedPreloads.isEmpty() && document()->documentElement())
491 m_preloader->takeAndPreload(m_queuedPreloads); 496 m_preloader->takeAndPreload(m_queuedPreloads);
492 497
493 if (isWaitingForScripts()) { 498 if (isWaitingForScripts()) {
494 ASSERT(it + 1 == tokens->end()); // The </script> is assumed to be t he last token of this bunch. 499 ASSERT(it + 1 == tokens->end()); // The </script> is assumed to be t he last token of this bunch.
495 runScriptsForPausedTreeBuilder(); 500 runScriptsForPausedTreeBuilder();
496 validateSpeculations(chunk.release()); 501 validateSpeculations(chunk.release());
497 break; 502 break;
498 } 503 }
499 504
505 if (isWaitingForStyles() || isWaitingForImports()) {
506 ASSERT(it + 1 == tokens->end()); // The token is assumed to be the l ast token of this bunch.
507 validateSpeculations(chunk.release());
508 break;
509 }
510
500 if (it->type() == HTMLToken::EndOfFile) { 511 if (it->type() == HTMLToken::EndOfFile) {
501 ASSERT(it + 1 == tokens->end()); // The EOF is assumed to be the las t token of this bunch. 512 ASSERT(it + 1 == tokens->end()); // The EOF is assumed to be the las t token of this bunch.
502 ASSERT(m_speculations.isEmpty()); // There should never be any chunk s after the EOF. 513 ASSERT(m_speculations.isEmpty()); // There should never be any chunk s after the EOF.
503 prepareToStopParsing(); 514 prepareToStopParsing();
504 break; 515 break;
505 } 516 }
506 517
507 ASSERT(!m_tokenizer); 518 ASSERT(!m_tokenizer);
508 ASSERT(!m_token); 519 ASSERT(!m_token);
509 } 520 }
(...skipping 11 matching lines...) Expand all
521 void HTMLDocumentParser::pumpPendingSpeculations() 532 void HTMLDocumentParser::pumpPendingSpeculations()
522 { 533 {
523 #if !ENABLE(OILPAN) 534 #if !ENABLE(OILPAN)
524 // ASSERT that this object is both attached to the Document and protected. 535 // ASSERT that this object is both attached to the Document and protected.
525 ASSERT(refCount() >= 2); 536 ASSERT(refCount() >= 2);
526 #endif 537 #endif
527 // If this assert fails, you need to call validateSpeculations to make sure 538 // If this assert fails, you need to call validateSpeculations to make sure
528 // m_tokenizer and m_token don't have state that invalidates m_speculations. 539 // m_tokenizer and m_token don't have state that invalidates m_speculations.
529 ASSERT(!m_tokenizer); 540 ASSERT(!m_tokenizer);
530 ASSERT(!m_token); 541 ASSERT(!m_token);
531 ASSERT(!m_lastChunkBeforeScript); 542 ASSERT(!m_lastChunkBeforeBlockingResource);
532 ASSERT(!isWaitingForScripts()); 543 ASSERT(!isWaitingForBlockingResource());
533 ASSERT(!isStopped()); 544 ASSERT(!isStopped());
534 ASSERT(!isScheduledForResume()); 545 ASSERT(!isScheduledForResume());
535 ASSERT(!inPumpSession()); 546 ASSERT(!inPumpSession());
536 547
537 // FIXME: Here should never be reached when there is a blocking script, 548 // FIXME: Here should never be reached when there is a blocking script,
538 // but it happens in unknown scenarios. See https://crbug.com/440901 549 // but it happens in unknown scenarios. See https://crbug.com/440901
539 if (isWaitingForScripts()) { 550 if (isWaitingForBlockingResource()) {
540 m_parserScheduler->scheduleForResume(); 551 m_parserScheduler->scheduleForResume();
541 return; 552 return;
542 } 553 }
543 554
544 // Do not allow pumping speculations in nested event loops. 555 // Do not allow pumping speculations in nested event loops.
545 if (m_pumpSpeculationsSessionNestingLevel) { 556 if (m_pumpSpeculationsSessionNestingLevel) {
546 m_parserScheduler->scheduleForResume(); 557 m_parserScheduler->scheduleForResume();
547 return; 558 return;
548 } 559 }
549 560
550 // FIXME: Pass in current input length. 561 // FIXME: Pass in current input length.
551 TRACE_EVENT_BEGIN1("devtools.timeline", "ParseHTML", "beginData", InspectorP arseHtmlEvent::beginData(document(), lineNumber().zeroBasedInt())); 562 TRACE_EVENT_BEGIN1("devtools.timeline", "ParseHTML", "beginData", InspectorP arseHtmlEvent::beginData(document(), lineNumber().zeroBasedInt()));
552 563
553 SpeculationsPumpSession session(m_pumpSpeculationsSessionNestingLevel, conte xtForParsingSession()); 564 SpeculationsPumpSession session(m_pumpSpeculationsSessionNestingLevel, conte xtForParsingSession());
554 while (!m_speculations.isEmpty()) { 565 while (!m_speculations.isEmpty()) {
555 ASSERT(!isScheduledForResume()); 566 ASSERT(!isScheduledForResume());
556 size_t elementTokenCount = processParsedChunkFromBackgroundParser(m_spec ulations.takeFirst().release()); 567 size_t elementTokenCount = processParsedChunkFromBackgroundParser(m_spec ulations.takeFirst().release());
557 session.addedElementTokens(elementTokenCount); 568 session.addedElementTokens(elementTokenCount);
558 569
559 // Always check isParsing first as m_document may be null. 570 // Always check isParsing first as m_document may be null.
560 // Surprisingly, isScheduledForResume() may be set here as a result of 571 // Surprisingly, isScheduledForResume() may be set here as a result of
561 // processParsedChunkFromBackgroundParser running arbitrary javascript 572 // processParsedChunkFromBackgroundParser running arbitrary javascript
562 // which invokes nested event loops. (e.g. inspector breakpoints) 573 // which invokes nested event loops. (e.g. inspector breakpoints)
563 if (!isParsing() || isWaitingForScripts() || isScheduledForResume()) 574 if (!isParsing() || isWaitingForBlockingResource() || isScheduledForResu me())
564 break; 575 break;
565 576
566 if (m_speculations.isEmpty() || m_parserScheduler->yieldIfNeeded(session , m_speculations.first()->startingScript)) 577 if (m_speculations.isEmpty() || m_parserScheduler->yieldIfNeeded(session , m_speculations.first()->startingScript))
567 break; 578 break;
568 } 579 }
569 580
570 TRACE_EVENT_END1("devtools.timeline", "ParseHTML", "endData", InspectorParse HtmlEvent::endData(lineNumber().zeroBasedInt() - 1)); 581 TRACE_EVENT_END1("devtools.timeline", "ParseHTML", "endData", InspectorParse HtmlEvent::endData(lineNumber().zeroBasedInt() - 1));
571 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Update Counters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data( )); 582 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Update Counters", TRACE_EVENT_SCOPE_THREAD, "data", InspectorUpdateCountersEvent::data( ));
572 } 583 }
573 584
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 #endif 653 #endif
643 654
644 if (isStopped()) 655 if (isStopped())
645 return; 656 return;
646 657
647 // There should only be PendingText left since the tree-builder always flush es 658 // There should only be PendingText left since the tree-builder always flush es
648 // the task queue before returning. In case that ever changes, crash. 659 // the task queue before returning. In case that ever changes, crash.
649 m_treeBuilder->flush(FlushAlways); 660 m_treeBuilder->flush(FlushAlways);
650 RELEASE_ASSERT(!isStopped()); 661 RELEASE_ASSERT(!isStopped());
651 662
652 if (isWaitingForScripts()) { 663 if (isWaitingForBlockingResource()) {
653 ASSERT(m_tokenizer->getState() == HTMLTokenizer::DataState); 664 ASSERT(m_tokenizer->getState() == HTMLTokenizer::DataState);
654 665
655 ASSERT(m_preloader); 666 ASSERT(m_preloader);
656 // TODO(kouhei): m_preloader should be always available for synchronous parsing case, 667 // TODO(kouhei): m_preloader should be always available for synchronous parsing case,
657 // adding paranoia if for speculative crash fix for crbug.com/465478 668 // adding paranoia if for speculative crash fix for crbug.com/465478
658 if (m_preloader) { 669 if (m_preloader) {
659 if (!m_preloadScanner) { 670 if (!m_preloadScanner) {
660 m_preloadScanner = HTMLPreloadScanner::create( 671 m_preloadScanner = HTMLPreloadScanner::create(
661 m_options, 672 m_options,
662 document()->url(), 673 document()->url(),
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 ASSERT(m_haveBackgroundParser || wasCreatedByScript()); 743 ASSERT(m_haveBackgroundParser || wasCreatedByScript());
733 m_token = adoptPtr(new HTMLToken); 744 m_token = adoptPtr(new HTMLToken);
734 m_tokenizer = HTMLTokenizer::create(m_options); 745 m_tokenizer = HTMLTokenizer::create(m_options);
735 } 746 }
736 747
737 SegmentedString excludedLineNumberSource(source); 748 SegmentedString excludedLineNumberSource(source);
738 excludedLineNumberSource.setExcludeLineNumbers(); 749 excludedLineNumberSource.setExcludeLineNumbers();
739 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); 750 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource);
740 pumpTokenizerIfPossible(); 751 pumpTokenizerIfPossible();
741 752
742 if (isWaitingForScripts()) { 753 if (isWaitingForBlockingResource()) {
743 // Check the document.write() output with a separate preload scanner as 754 // Check the document.write() output with a separate preload scanner as
744 // the main scanner can't deal with insertions. 755 // the main scanner can't deal with insertions.
745 if (!m_insertionPreloadScanner) { 756 if (!m_insertionPreloadScanner) {
746 m_insertionPreloadScanner = HTMLPreloadScanner::create( 757 m_insertionPreloadScanner = HTMLPreloadScanner::create(
747 m_options, 758 m_options,
748 document()->url(), 759 document()->url(),
749 CachedDocumentParameters::create(document()), 760 CachedDocumentParameters::create(document()),
750 MediaValuesCached::MediaValuesCachedData(*document())); 761 MediaValuesCached::MediaValuesCachedData(*document()));
751 } 762 }
752 763
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 // as appendBytes() will directly ship the data to the thread. 828 // as appendBytes() will directly ship the data to the thread.
818 ASSERT(!shouldUseThreading()); 829 ASSERT(!shouldUseThreading());
819 830
820 // pumpTokenizer can cause this parser to be detached from the Document, 831 // pumpTokenizer can cause this parser to be detached from the Document,
821 // but we need to ensure it isn't deleted yet. 832 // but we need to ensure it isn't deleted yet.
822 RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); 833 RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this);
823 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentParser:: append", "size", inputSource.length()); 834 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentParser:: append", "size", inputSource.length());
824 const SegmentedString source(inputSource); 835 const SegmentedString source(inputSource);
825 836
826 if (m_preloadScanner) { 837 if (m_preloadScanner) {
827 if (m_input.current().isEmpty() && !isWaitingForScripts()) { 838 if (m_input.current().isEmpty() && !isWaitingForBlockingResource()) {
828 // We have parsed until the end of the current input and so are now moving ahead of the preload scanner. 839 // We have parsed until the end of the current input and so are now moving ahead of the preload scanner.
829 // Clear the scanner so we know to scan starting from the current in put point if we block again. 840 // Clear the scanner so we know to scan starting from the current in put point if we block again.
830 m_preloadScanner.clear(); 841 m_preloadScanner.clear();
831 } else { 842 } else {
832 m_preloadScanner->appendToEnd(source); 843 m_preloadScanner->appendToEnd(source);
833 if (isWaitingForScripts()) 844 if (isWaitingForBlockingResource())
834 m_preloadScanner->scan(m_preloader.get(), document()->baseElemen tURL()); 845 m_preloadScanner->scan(m_preloader.get(), document()->baseElemen tURL());
835 } 846 }
836 } 847 }
837 848
838 m_input.appendToEnd(source); 849 m_input.appendToEnd(source);
839 850
840 if (inPumpSession()) { 851 if (inPumpSession()) {
841 // We've gotten data off the network in a nested write. 852 // We've gotten data off the network in a nested write.
842 // We don't want to consume any more of the input stream now. Do 853 // We don't want to consume any more of the input stream now. Do
843 // not worry. We'll consume this data in a less-nested write(). 854 // not worry. We'll consume this data in a less-nested write().
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 // run the preload scanner, as well as delay completion of parsing. 991 // run the preload scanner, as well as delay completion of parsing.
981 bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript() ; 992 bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript() ;
982 bool scriptRunnerHasBlockingScript = m_scriptRunner && m_scriptRunner->hasPa rserBlockingScript(); 993 bool scriptRunnerHasBlockingScript = m_scriptRunner && m_scriptRunner->hasPa rserBlockingScript();
983 // Since the parser is paused while a script runner has a blocking script, i t should 994 // Since the parser is paused while a script runner has a blocking script, i t should
984 // never be possible to end up with both objects holding a blocking script. 995 // never be possible to end up with both objects holding a blocking script.
985 ASSERT(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript)); 996 ASSERT(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript));
986 // If either object has a blocking script, the parser should be paused. 997 // If either object has a blocking script, the parser should be paused.
987 return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript; 998 return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript;
988 } 999 }
989 1000
990 void HTMLDocumentParser::resumeParsingAfterScriptExecution() 1001 bool HTMLDocumentParser::isWaitingForStyles() const
1002 {
1003 return RuntimeEnabledFeatures::htmlParserBlocksOnCSSEnabled() && document() && document()->styleEngine().hasPendingSheets();
1004 }
1005
1006 bool HTMLDocumentParser::isWaitingForImports() const
1007 {
1008 return RuntimeEnabledFeatures::htmlParserBlocksOnCSSEnabled() && document() && !document()->haveImportsLoaded();
1009 }
1010
1011 bool HTMLDocumentParser::isWaitingForBlockingResource() const
1012 {
1013 return isWaitingForScripts() || isWaitingForStyles() || isWaitingForImports( );
1014 }
1015
1016 void HTMLDocumentParser::resumeParsingAfterBlock()
991 { 1017 {
992 ASSERT(!isExecutingScript()); 1018 ASSERT(!isExecutingScript());
993 ASSERT(!isWaitingForScripts()); 1019 ASSERT(!isWaitingForBlockingResource());
994 1020
995 if (m_haveBackgroundParser) { 1021 if (m_haveBackgroundParser) {
996 validateSpeculations(m_lastChunkBeforeScript.release()); 1022 validateSpeculations(m_lastChunkBeforeBlockingResource.release());
997 ASSERT(!m_lastChunkBeforeScript); 1023 ASSERT(!m_lastChunkBeforeBlockingResource);
998 // processParsedChunkFromBackgroundParser can cause this parser to be de tached from the Document, 1024 // processParsedChunkFromBackgroundParser can cause this parser to be de tached from the Document,
999 // but we need to ensure it isn't deleted yet. 1025 // but we need to ensure it isn't deleted yet.
1000 RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); 1026 RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this);
1001 pumpPendingSpeculations(); 1027 pumpPendingSpeculations();
1002 return; 1028 return;
1003 } 1029 }
1004 1030
1005 m_insertionPreloadScanner.clear(); 1031 m_insertionPreloadScanner.clear();
1006 pumpTokenizerIfPossible(); 1032 pumpTokenizerIfPossible();
1007 endIfDelayed(); 1033 endIfDelayed();
(...skipping 18 matching lines...) Expand all
1026 if (isStopped()) { 1052 if (isStopped()) {
1027 return; 1053 return;
1028 } 1054 }
1029 1055
1030 if (isStopping()) { 1056 if (isStopping()) {
1031 attemptToRunDeferredScriptsAndEnd(); 1057 attemptToRunDeferredScriptsAndEnd();
1032 return; 1058 return;
1033 } 1059 }
1034 1060
1035 m_scriptRunner->executeScriptsWaitingForLoad(cachedResource); 1061 m_scriptRunner->executeScriptsWaitingForLoad(cachedResource);
1036 if (!isWaitingForScripts()) 1062 if (!isWaitingForBlockingResource())
1037 resumeParsingAfterScriptExecution(); 1063 resumeParsingAfterBlock();
1038 } 1064 }
1039 1065
1040 void HTMLDocumentParser::executeScriptsWaitingForResources() 1066 void HTMLDocumentParser::executeScriptsWaitingForResources()
1041 { 1067 {
1042 // Document only calls this when the Document owns the DocumentParser 1068 // Document only calls this when the Document owns the DocumentParser
1043 // so this will not be called in the DocumentFragment case. 1069 // so this will not be called in the DocumentFragment case.
1044 ASSERT(m_scriptRunner); 1070 ASSERT(m_scriptRunner);
1045 // Ignore calls unless we have a script blocking the parser waiting on a
1046 // stylesheet load. Otherwise we are currently parsing and this
1047 // is a re-entrant call from encountering a </ style> tag.
1048 if (!m_scriptRunner->hasScriptsWaitingForResources())
1049 return;
1050 1071
1051 // pumpTokenizer can cause this parser to be detached from the Document, 1072 if (m_scriptRunner->hasScriptsWaitingForResources()) {
1052 // but we need to ensure it isn't deleted yet. 1073 // pumpTokenizer can cause this parser to be detached from the Document,
1053 RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this); 1074 // but we need to ensure it isn't deleted yet.
1054 m_scriptRunner->executeScriptsWaitingForResources(); 1075 RefPtrWillBeRawPtr<HTMLDocumentParser> protect(this);
1055 if (!isWaitingForScripts()) 1076 m_scriptRunner->executeScriptsWaitingForResources();
1056 resumeParsingAfterScriptExecution(); 1077 if (!isWaitingForBlockingResource())
1078 resumeParsingAfterBlock();
1079 } else if (RuntimeEnabledFeatures::htmlParserBlocksOnCSSEnabled() && !inPump Session() && !isWaitingForBlockingResource()) {
1080 resumeParsingAfterBlock();
1081 }
1057 } 1082 }
1058 1083
1059 void HTMLDocumentParser::parseDocumentFragment(const String& source, DocumentFra gment* fragment, Element* contextElement, ParserContentPolicy parserContentPolic y) 1084 void HTMLDocumentParser::parseDocumentFragment(const String& source, DocumentFra gment* fragment, Element* contextElement, ParserContentPolicy parserContentPolic y)
1060 { 1085 {
1061 RefPtrWillBeRawPtr<HTMLDocumentParser> parser = HTMLDocumentParser::create(f ragment, contextElement, parserContentPolicy); 1086 RefPtrWillBeRawPtr<HTMLDocumentParser> parser = HTMLDocumentParser::create(f ragment, contextElement, parserContentPolicy);
1062 parser->append(source); 1087 parser->append(source);
1063 parser->finish(); 1088 parser->finish();
1064 ASSERT(!parser->processingData()); // Make sure we're done. <rdar://problem/ 3963151> 1089 ASSERT(!parser->processingData()); // Make sure we're done. <rdar://problem/ 3963151>
1065 parser->detach(); // Allows ~DocumentParser to assert it was detached before destruction. 1090 parser->detach(); // Allows ~DocumentParser to assert it was detached before destruction.
1066 } 1091 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder) 1152 void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder)
1128 { 1153 {
1129 ASSERT(decoder); 1154 ASSERT(decoder);
1130 DecodedDataDocumentParser::setDecoder(decoder); 1155 DecodedDataDocumentParser::setDecoder(decoder);
1131 1156
1132 if (m_haveBackgroundParser) 1157 if (m_haveBackgroundParser)
1133 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse r::setDecoder, AllowCrossThreadAccess(m_backgroundParser), takeDecoder())); 1158 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse r::setDecoder, AllowCrossThreadAccess(m_backgroundParser), takeDecoder()));
1134 } 1159 }
1135 1160
1136 } // namespace blink 1161 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698