Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 15 matching lines...) Expand all Loading... | |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "core/html/parser/HTMLDocumentParser.h" | 27 #include "core/html/parser/HTMLDocumentParser.h" |
| 28 | 28 |
| 29 #include "HTMLNames.h" | 29 #include "HTMLNames.h" |
| 30 #include "core/dom/DocumentFragment.h" | 30 #include "core/dom/DocumentFragment.h" |
| 31 #include "core/dom/Element.h" | 31 #include "core/dom/Element.h" |
| 32 #include "core/html/HTMLDocument.h" | 32 #include "core/html/HTMLDocument.h" |
| 33 #include "core/html/parser/AtomicHTMLToken.h" | 33 #include "core/html/parser/AtomicHTMLToken.h" |
| 34 #include "core/html/parser/BackgroundHTMLParser.h" | 34 #include "core/html/parser/BackgroundHTMLParser.h" |
| 35 #include "core/html/parser/HTMLParserScheduler.h" | 35 #include "core/html/parser/HTMLParserScheduler.h" |
| 36 #include "core/html/parser/HTMLParserThread.h" | |
| 37 #include "core/html/parser/HTMLScriptRunner.h" | 36 #include "core/html/parser/HTMLScriptRunner.h" |
| 38 #include "core/html/parser/HTMLTreeBuilder.h" | 37 #include "core/html/parser/HTMLTreeBuilder.h" |
| 39 #include "core/inspector/InspectorInstrumentation.h" | 38 #include "core/inspector/InspectorInstrumentation.h" |
| 40 #include "core/frame/Frame.h" | 39 #include "core/frame/Frame.h" |
| 40 #include "core/loader/DocumentLoader.h" | |
| 41 #include "platform/SharedBuffer.h" | 41 #include "platform/SharedBuffer.h" |
| 42 #include "platform/Task.h" | |
| 42 #include "platform/TraceEvent.h" | 43 #include "platform/TraceEvent.h" |
| 44 #include "public/platform/WebThread.h" | |
| 45 #include "public/platform/WebThreadedResourceProvider.h" | |
| 43 #include "wtf/Functional.h" | 46 #include "wtf/Functional.h" |
| 44 | 47 |
| 45 namespace WebCore { | 48 namespace WebCore { |
| 46 | 49 |
| 47 using namespace HTMLNames; | 50 using namespace HTMLNames; |
| 48 | 51 |
| 49 // This is a direct transcription of step 4 from: | 52 // This is a direct transcription of step 4 from: |
| 50 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag ment-case | 53 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag ment-case |
| 51 static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem ent, bool reportErrors, const HTMLParserOptions& options) | 54 static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem ent, bool reportErrors, const HTMLParserOptions& options) |
| 52 { | 55 { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 64 || (contextTag.matches(noscriptTag) && options.scriptEnabled) | 67 || (contextTag.matches(noscriptTag) && options.scriptEnabled) |
| 65 || contextTag.matches(noframesTag)) | 68 || contextTag.matches(noframesTag)) |
| 66 return reportErrors ? HTMLTokenizer::RAWTEXTState : HTMLTokenizer::PLAIN TEXTState; | 69 return reportErrors ? HTMLTokenizer::RAWTEXTState : HTMLTokenizer::PLAIN TEXTState; |
| 67 if (contextTag.matches(scriptTag)) | 70 if (contextTag.matches(scriptTag)) |
| 68 return reportErrors ? HTMLTokenizer::ScriptDataState : HTMLTokenizer::PL AINTEXTState; | 71 return reportErrors ? HTMLTokenizer::ScriptDataState : HTMLTokenizer::PL AINTEXTState; |
| 69 if (contextTag.matches(plaintextTag)) | 72 if (contextTag.matches(plaintextTag)) |
| 70 return HTMLTokenizer::PLAINTEXTState; | 73 return HTMLTokenizer::PLAINTEXTState; |
| 71 return HTMLTokenizer::DataState; | 74 return HTMLTokenizer::DataState; |
| 72 } | 75 } |
| 73 | 76 |
| 77 class ParserResourceForegroundClient : public blink::WebThreadedResourceForegrou ndClient { | |
| 78 public: | |
| 79 ParserResourceForegroundClient(WeakPtr<HTMLDocumentParser> parser) | |
| 80 : m_parser(parser) | |
| 81 { | |
| 82 } | |
| 83 | |
| 84 // WebThreadedResourceForegroundClient | |
| 85 virtual void didSwitchedToBackgroundClient() OVERRIDE FINAL { | |
|
darin (slow to review)
2014/02/16 07:12:27
nit: opening paren should be on the next line per
| |
| 86 if (m_parser.get()) | |
| 87 m_parser.get()->didSwitchedToBackgroundClient(); | |
|
darin (slow to review)
2014/02/16 07:12:27
nit: "didSwitched..." should be "didSwitch..."
| |
| 88 } | |
| 89 | |
| 90 private: | |
| 91 WeakPtr<HTMLDocumentParser> m_parser; | |
| 92 }; | |
| 93 | |
| 94 blink::WebThread* HTMLDocumentParser::s_parserThread = 0; | |
| 95 | |
| 74 HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors ) | 96 HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors ) |
| 75 : ScriptableDocumentParser(document) | 97 : ScriptableDocumentParser(document) |
| 76 , m_options(document) | 98 , m_options(document) |
| 77 , m_token(m_options.useThreading ? nullptr : adoptPtr(new HTMLToken)) | 99 , m_token(m_options.useThreading ? nullptr : adoptPtr(new HTMLToken)) |
| 78 , m_tokenizer(m_options.useThreading ? nullptr : HTMLTokenizer::create(m_opt ions)) | 100 , m_tokenizer(m_options.useThreading ? nullptr : HTMLTokenizer::create(m_opt ions)) |
| 79 , m_scriptRunner(HTMLScriptRunner::create(document, this)) | 101 , m_scriptRunner(HTMLScriptRunner::create(document, this)) |
| 80 , m_treeBuilder(HTMLTreeBuilder::create(this, document, parserContentPolicy( ), reportErrors, m_options)) | 102 , m_treeBuilder(HTMLTreeBuilder::create(this, document, parserContentPolicy( ), reportErrors, m_options)) |
| 81 , m_parserScheduler(HTMLParserScheduler::create(this)) | 103 , m_parserScheduler(HTMLParserScheduler::create(this)) |
| 82 , m_xssAuditorDelegate(document) | 104 , m_xssAuditorDelegate(document) |
| 83 , m_weakFactory(this) | 105 , m_weakFactory(this) |
| 84 , m_preloader(adoptPtr(new HTMLResourcePreloader(document))) | 106 , m_preloader(adoptPtr(new HTMLResourcePreloader(document))) |
| 85 , m_isPinnedToMainThread(false) | 107 , m_isPinnedToMainThread(false) |
| 86 , m_endWasDelayed(false) | 108 , m_endWasDelayed(false) |
| 87 , m_haveBackgroundParser(false) | 109 , m_haveBackgroundParser(false) |
| 88 , m_pumpSessionNestingLevel(0) | 110 , m_pumpSessionNestingLevel(0) |
| 111 , m_parserThreadIsStandalone(false) | |
| 89 { | 112 { |
| 90 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); | 113 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); |
| 91 } | 114 } |
| 92 | 115 |
| 93 // FIXME: Member variables should be grouped into self-initializing structs to | 116 // FIXME: Member variables should be grouped into self-initializing structs to |
| 94 // minimize code duplication between these constructors. | 117 // minimize code duplication between these constructors. |
| 95 HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont extElement, ParserContentPolicy parserContentPolicy) | 118 HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont extElement, ParserContentPolicy parserContentPolicy) |
| 96 : ScriptableDocumentParser(&fragment->document(), parserContentPolicy) | 119 : ScriptableDocumentParser(&fragment->document(), parserContentPolicy) |
| 97 , m_options(&fragment->document()) | 120 , m_options(&fragment->document()) |
| 98 , m_token(adoptPtr(new HTMLToken)) | 121 , m_token(adoptPtr(new HTMLToken)) |
| 99 , m_tokenizer(HTMLTokenizer::create(m_options)) | 122 , m_tokenizer(HTMLTokenizer::create(m_options)) |
| 100 , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, this ->parserContentPolicy(), m_options)) | 123 , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, this ->parserContentPolicy(), m_options)) |
| 101 , m_xssAuditorDelegate(&fragment->document()) | 124 , m_xssAuditorDelegate(&fragment->document()) |
| 102 , m_weakFactory(this) | 125 , m_weakFactory(this) |
| 103 , m_isPinnedToMainThread(true) | 126 , m_isPinnedToMainThread(true) |
| 104 , m_endWasDelayed(false) | 127 , m_endWasDelayed(false) |
| 105 , m_haveBackgroundParser(false) | 128 , m_haveBackgroundParser(false) |
| 106 , m_pumpSessionNestingLevel(0) | 129 , m_pumpSessionNestingLevel(0) |
| 130 , m_parserThreadIsStandalone(false) | |
| 107 { | 131 { |
| 108 ASSERT(!shouldUseThreading()); | 132 ASSERT(!shouldUseThreading()); |
| 109 bool reportErrors = false; // For now document fragment parsing never report s errors. | 133 bool reportErrors = false; // For now document fragment parsing never report s errors. |
| 110 m_tokenizer->setState(tokenizerStateForContextElement(contextElement, report Errors, m_options)); | 134 m_tokenizer->setState(tokenizerStateForContextElement(contextElement, report Errors, m_options)); |
| 111 m_xssAuditor.initForFragment(); | 135 m_xssAuditor.initForFragment(); |
| 112 } | 136 } |
| 113 | 137 |
| 114 HTMLDocumentParser::~HTMLDocumentParser() | 138 HTMLDocumentParser::~HTMLDocumentParser() |
| 115 { | 139 { |
| 116 ASSERT(!m_parserScheduler); | 140 ASSERT(!m_parserScheduler); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 chunk->preloads.clear(); // We don't need to preload because we're going to parse immediately. | 339 chunk->preloads.clear(); // We don't need to preload because we're going to parse immediately. |
| 316 m_speculations.append(chunk); | 340 m_speculations.append(chunk); |
| 317 pumpPendingSpeculations(); | 341 pumpPendingSpeculations(); |
| 318 } | 342 } |
| 319 | 343 |
| 320 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume ntEncodingData& data) | 344 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume ntEncodingData& data) |
| 321 { | 345 { |
| 322 document()->setEncodingData(data); | 346 document()->setEncodingData(data); |
| 323 } | 347 } |
| 324 | 348 |
| 349 void HTMLDocumentParser::destroyResourceProvider(PassOwnPtr<blink::WebThreadedRe sourceProvider> resourceProvider) | |
| 350 { | |
| 351 // Here to let the resource bridge be destructed on the main thread. | |
|
darin (slow to review)
2014/02/16 07:12:27
nit: I think this is a reference to ResourceLoader
| |
| 352 } | |
| 353 | |
| 325 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk) | 354 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk) |
| 326 { | 355 { |
| 327 ASSERT(chunk); | 356 ASSERT(chunk); |
| 328 if (isWaitingForScripts()) { | 357 if (isWaitingForScripts()) { |
| 329 // We're waiting on a network script, just save the chunk, we'll get | 358 // We're waiting on a network script, just save the chunk, we'll get |
| 330 // a second validateSpeculations call after the script completes. | 359 // a second validateSpeculations call after the script completes. |
| 331 // This call should have been made immediately after runScriptsForPaused TreeBuilder | 360 // This call should have been made immediately after runScriptsForPaused TreeBuilder |
| 332 // which may have started a network load and left us waiting. | 361 // which may have started a network load and left us waiting. |
| 333 ASSERT(!m_lastChunkBeforeScript); | 362 ASSERT(!m_lastChunkBeforeScript); |
| 334 m_lastChunkBeforeScript = chunk; | 363 m_lastChunkBeforeScript = chunk; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 checkpoint->parser = m_weakFactory.createWeakPtr(); | 399 checkpoint->parser = m_weakFactory.createWeakPtr(); |
| 371 checkpoint->token = token; | 400 checkpoint->token = token; |
| 372 checkpoint->tokenizer = tokenizer; | 401 checkpoint->tokenizer = tokenizer; |
| 373 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil der.get()); | 402 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil der.get()); |
| 374 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; | 403 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; |
| 375 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner Checkpoint; | 404 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner Checkpoint; |
| 376 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); | 405 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); |
| 377 m_input.current().clear(); // FIXME: This should be passed in instead of cle ared. | 406 m_input.current().clear(); // FIXME: This should be passed in instead of cle ared. |
| 378 | 407 |
| 379 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); | 408 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); |
| 380 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, checkpoint.release())); | 409 ASSERT(s_parserThread); |
| 410 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::resumeFrom, m_ backgroundParser, checkpoint.release()))); | |
| 381 } | 411 } |
| 382 | 412 |
| 383 void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse dChunk> popChunk) | 413 void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse dChunk> popChunk) |
| 384 { | 414 { |
| 385 TRACE_EVENT0("webkit", "HTMLDocumentParser::processParsedChunkFromBackground Parser"); | 415 TRACE_EVENT0("webkit", "HTMLDocumentParser::processParsedChunkFromBackground Parser"); |
| 386 | 416 |
| 387 ASSERT_WITH_SECURITY_IMPLICATION(!document()->activeParserCount()); | 417 ASSERT_WITH_SECURITY_IMPLICATION(!document()->activeParserCount()); |
| 388 ASSERT(!isParsingFragment()); | 418 ASSERT(!isParsingFragment()); |
| 389 ASSERT(!isWaitingForScripts()); | 419 ASSERT(!isWaitingForScripts()); |
| 390 ASSERT(!isStopped()); | 420 ASSERT(!isStopped()); |
| 391 // ASSERT that this object is both attached to the Document and protected. | 421 // ASSERT that this object is both attached to the Document and protected. |
| 392 ASSERT(refCount() >= 2); | 422 ASSERT(refCount() >= 2); |
| 393 ASSERT(shouldUseThreading()); | 423 ASSERT(shouldUseThreading()); |
| 394 ASSERT(!m_tokenizer); | 424 ASSERT(!m_tokenizer); |
| 395 ASSERT(!m_token); | 425 ASSERT(!m_token); |
| 396 ASSERT(!m_lastChunkBeforeScript); | 426 ASSERT(!m_lastChunkBeforeScript); |
| 427 ASSERT(s_parserThread); | |
| 397 | 428 |
| 398 ActiveParserSession session(contextForParsingSession()); | 429 ActiveParserSession session(contextForParsingSession()); |
| 399 | 430 |
| 400 OwnPtr<ParsedChunk> chunk(popChunk); | 431 OwnPtr<ParsedChunk> chunk(popChunk); |
| 401 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); | 432 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); |
| 402 | 433 |
| 403 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::startedChun kWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); | 434 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::startedChunkWi thCheckpoint, m_backgroundParser, chunk->inputCheckpoint))); |
| 404 | 435 |
| 405 for (XSSInfoStream::const_iterator it = chunk->xssInfos.begin(); it != chunk ->xssInfos.end(); ++it) { | 436 for (XSSInfoStream::const_iterator it = chunk->xssInfos.begin(); it != chunk ->xssInfos.end(); ++it) { |
| 406 m_textPosition = (*it)->m_textPosition; | 437 m_textPosition = (*it)->m_textPosition; |
| 407 m_xssAuditorDelegate.didBlockScript(**it); | 438 m_xssAuditorDelegate.didBlockScript(**it); |
| 408 if (isStopped()) | 439 if (isStopped()) |
| 409 break; | 440 break; |
| 410 } | 441 } |
| 411 | 442 |
| 412 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != to kens->end(); ++it) { | 443 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != to kens->end(); ++it) { |
| 413 ASSERT(!isWaitingForScripts()); | 444 ASSERT(!isWaitingForScripts()); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 484 m_parserScheduler->scheduleForResume(); | 515 m_parserScheduler->scheduleForResume(); |
| 485 break; | 516 break; |
| 486 } | 517 } |
| 487 } | 518 } |
| 488 | 519 |
| 489 InspectorInstrumentation::didWriteHTML(cookie, lineNumber().zeroBasedInt()); | 520 InspectorInstrumentation::didWriteHTML(cookie, lineNumber().zeroBasedInt()); |
| 490 } | 521 } |
| 491 | 522 |
| 492 void HTMLDocumentParser::forcePlaintextForTextDocument() | 523 void HTMLDocumentParser::forcePlaintextForTextDocument() |
| 493 { | 524 { |
| 494 if (shouldUseThreading()) { | 525 if (shouldUseThreading() && !m_haveBackgroundParser) |
| 495 // This method is called before any data is appended, so we have to star t | 526 startBackgroundParser(); |
| 496 // the background parser ourselves. | |
| 497 if (!m_haveBackgroundParser) | |
| 498 startBackgroundParser(); | |
| 499 | 527 |
| 500 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::forcePl aintextForTextDocument, m_backgroundParser)); | 528 if (m_haveBackgroundParser) |
| 501 } else | 529 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::forcePlain textForTextDocument, m_backgroundParser))); |
| 530 else | |
| 502 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); | 531 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); |
| 503 } | 532 } |
| 504 | 533 |
| 505 Document* HTMLDocumentParser::contextForParsingSession() | 534 Document* HTMLDocumentParser::contextForParsingSession() |
| 506 { | 535 { |
| 507 // The parsing session should interact with the document only when parsing | 536 // The parsing session should interact with the document only when parsing |
| 508 // non-fragments. Otherwise, we might delay the load event mistakenly. | 537 // non-fragments. Otherwise, we might delay the load event mistakenly. |
| 509 if (isParsingFragment()) | 538 if (isParsingFragment()) |
| 510 return 0; | 539 return 0; |
| 511 return document(); | 540 return document(); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 655 } | 684 } |
| 656 | 685 |
| 657 endIfDelayed(); | 686 endIfDelayed(); |
| 658 } | 687 } |
| 659 | 688 |
| 660 void HTMLDocumentParser::startBackgroundParser() | 689 void HTMLDocumentParser::startBackgroundParser() |
| 661 { | 690 { |
| 662 ASSERT(!isStopped()); | 691 ASSERT(!isStopped()); |
| 663 ASSERT(shouldUseThreading()); | 692 ASSERT(shouldUseThreading()); |
| 664 ASSERT(!m_haveBackgroundParser); | 693 ASSERT(!m_haveBackgroundParser); |
| 694 | |
| 695 OwnPtr<blink::WebThreadedResourceProvider> resourceProvider = document()->lo ader()->createThreadedResourceProvider(); | |
| 696 if (resourceProvider) { | |
| 697 // The resource provider is responsible for destroying the client we cre ate here. | |
| 698 resourceProvider->setForegroundClient(new ParserResourceForegroundClient (m_weakFactory.createWeakPtr())); | |
| 699 if (!s_parserThread) | |
| 700 s_parserThread = resourceProvider->resourceProviderThread(); | |
|
darin (slow to review)
2014/02/16 07:12:27
nit: perhaps it would be better to have Blink crea
| |
| 701 ASSERT(s_parserThread && s_parserThread == resourceProvider->resourcePro viderThread()); | |
| 702 } | |
| 703 | |
| 704 if (!s_parserThread) { | |
| 705 // If we don't have a thread object, we can't use threading and must | |
| 706 // fall back to singlethreaded mode by having our own tokenizer. | |
| 707 if (!m_token) | |
| 708 m_token = adoptPtr(new HTMLToken); | |
| 709 if (!m_tokenizer) | |
| 710 m_tokenizer = HTMLTokenizer::create(m_options); | |
| 711 return; | |
| 712 } | |
| 713 | |
| 665 m_haveBackgroundParser = true; | 714 m_haveBackgroundParser = true; |
| 666 | 715 |
| 667 RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<Backg roundHTMLParser>::createUnbound(); | 716 RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<Backg roundHTMLParser>::createUnbound(); |
| 668 m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference); | 717 m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference); |
| 669 | 718 |
| 670 OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new Background HTMLParser::Configuration); | 719 OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new Background HTMLParser::Configuration); |
| 671 config->options = m_options; | 720 config->options = m_options; |
| 672 config->parser = m_weakFactory.createWeakPtr(); | 721 config->parser = m_weakFactory.createWeakPtr(); |
| 673 config->xssAuditor = adoptPtr(new XSSAuditor); | 722 config->xssAuditor = adoptPtr(new XSSAuditor); |
| 674 config->xssAuditor->init(document(), &m_xssAuditorDelegate); | 723 config->xssAuditor->init(document(), &m_xssAuditorDelegate); |
| 675 config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url(). copy(), document()->devicePixelRatio())); | 724 config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url(). copy(), document()->devicePixelRatio())); |
| 676 config->decoder = takeDecoder(); | 725 config->decoder = takeDecoder(); |
| 726 config->resourceProvider = resourceProvider.release(); | |
| 677 | 727 |
| 678 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); | 728 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); |
| 679 ASSERT(config->preloadScanner->isSafeToSendToAnotherThread()); | 729 ASSERT(config->preloadScanner->isSafeToSendToAnotherThread()); |
| 680 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::start, refe rence.release(), config.release())); | 730 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::start, referen ce.release(), config.release()))); |
| 681 } | 731 } |
| 682 | 732 |
| 683 void HTMLDocumentParser::stopBackgroundParser() | 733 void HTMLDocumentParser::stopBackgroundParser() |
| 684 { | 734 { |
| 685 ASSERT(shouldUseThreading()); | 735 ASSERT(shouldUseThreading()); |
| 686 ASSERT(m_haveBackgroundParser); | 736 ASSERT(m_haveBackgroundParser); |
| 737 ASSERT(s_parserThread); | |
| 687 m_haveBackgroundParser = false; | 738 m_haveBackgroundParser = false; |
| 688 | 739 |
| 689 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::stop, m_bac kgroundParser)); | 740 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::stop, m_backgr oundParser))); |
| 690 m_weakFactory.revokeAll(); | 741 m_weakFactory.revokeAll(); |
| 691 } | 742 } |
| 692 | 743 |
| 693 void HTMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) | 744 void HTMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) |
| 694 { | 745 { |
| 695 if (isStopped()) | 746 if (isStopped()) |
| 696 return; | 747 return; |
| 697 | 748 |
| 698 // We should never reach this point if we're using a parser thread, | 749 // We should never reach this point if we're using a parser thread, |
| 699 // as appendBytes() will directly ship the data to the thread. | 750 // as appendBytes() will directly ship the data to the thread. |
| 700 ASSERT(!shouldUseThreading()); | 751 ASSERT(!m_haveBackgroundParser); |
| 701 | 752 |
| 702 // pumpTokenizer can cause this parser to be detached from the Document, | 753 // pumpTokenizer can cause this parser to be detached from the Document, |
| 703 // but we need to ensure it isn't deleted yet. | 754 // but we need to ensure it isn't deleted yet. |
| 704 RefPtr<HTMLDocumentParser> protect(this); | 755 RefPtr<HTMLDocumentParser> protect(this); |
| 705 TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->lengt h()); | 756 TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->lengt h()); |
| 706 String source(inputSource); | 757 String source(inputSource); |
| 707 | 758 |
| 708 if (m_preloadScanner) { | 759 if (m_preloadScanner) { |
| 709 if (m_input.current().isEmpty() && !isWaitingForScripts()) { | 760 if (m_input.current().isEmpty() && !isWaitingForScripts()) { |
| 710 // We have parsed until the end of the current input and so are now moving ahead of the preload scanner. | 761 // We have parsed until the end of the current input and so are now moving ahead of the preload scanner. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 792 // FIXME: We should ASSERT(!m_parserStopped) here, since it does not | 843 // FIXME: We should ASSERT(!m_parserStopped) here, since it does not |
| 793 // makes sense to call any methods on DocumentParser once it's been stopped. | 844 // makes sense to call any methods on DocumentParser once it's been stopped. |
| 794 // However, FrameLoader::stop calls DocumentParser::finish unconditionally. | 845 // However, FrameLoader::stop calls DocumentParser::finish unconditionally. |
| 795 | 846 |
| 796 // Empty documents never got an append() call, and thus have never started | 847 // Empty documents never got an append() call, and thus have never started |
| 797 // a background parser. In those cases, we ignore shouldUseThreading() | 848 // a background parser. In those cases, we ignore shouldUseThreading() |
| 798 // and fall through to the non-threading case. | 849 // and fall through to the non-threading case. |
| 799 if (m_haveBackgroundParser) { | 850 if (m_haveBackgroundParser) { |
| 800 if (!m_input.haveSeenEndOfFile()) | 851 if (!m_input.haveSeenEndOfFile()) |
| 801 m_input.closeWithoutMarkingEndOfFile(); | 852 m_input.closeWithoutMarkingEndOfFile(); |
| 802 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::finish, m_backgroundParser)); | 853 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::finish, m_ backgroundParser))); |
| 803 return; | 854 return; |
| 804 } | 855 } |
| 805 | 856 |
| 806 if (!m_tokenizer) { | 857 if (!m_tokenizer) { |
| 807 ASSERT(!m_token); | 858 ASSERT(!m_token); |
| 808 // We're finishing before receiving any data. Rather than booting up | 859 // We're finishing before receiving any data. Rather than booting up |
| 809 // the background parser just to spin it down, we finish parsing | 860 // the background parser just to spin it down, we finish parsing |
| 810 // synchronously. | 861 // synchronously. |
| 811 m_token = adoptPtr(new HTMLToken); | 862 m_token = adoptPtr(new HTMLToken); |
| 812 m_tokenizer = HTMLTokenizer::create(m_options); | 863 m_tokenizer = HTMLTokenizer::create(m_options); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 961 { | 1012 { |
| 962 if (m_parserScheduler) | 1013 if (m_parserScheduler) |
| 963 m_parserScheduler->resume(); | 1014 m_parserScheduler->resume(); |
| 964 } | 1015 } |
| 965 | 1016 |
| 966 void HTMLDocumentParser::appendBytes(const char* data, size_t length) | 1017 void HTMLDocumentParser::appendBytes(const char* data, size_t length) |
| 967 { | 1018 { |
| 968 if (!length || isStopped()) | 1019 if (!length || isStopped()) |
| 969 return; | 1020 return; |
| 970 | 1021 |
| 971 if (shouldUseThreading()) { | 1022 if (shouldUseThreading() && !m_haveBackgroundParser) |
| 972 if (!m_haveBackgroundParser) | 1023 startBackgroundParser(); |
| 973 startBackgroundParser(); | 1024 |
| 1025 if (m_haveBackgroundParser) { | |
| 1026 if (m_parserThreadIsStandalone) | |
| 1027 return; // If this is set, the parser thread will receive the data d irectly. | |
| 974 | 1028 |
| 975 OwnPtr<Vector<char> > buffer = adoptPtr(new Vector<char>(length)); | 1029 OwnPtr<Vector<char> > buffer = adoptPtr(new Vector<char>(length)); |
| 976 memcpy(buffer->data(), data, length); | 1030 memcpy(buffer->data(), data, length); |
| 977 TRACE_EVENT1("net", "HTMLDocumentParser::appendBytes", "size", (unsigned )length); | 1031 TRACE_EVENT1("net", "HTMLDocumentParser::appendBytes", "size", (unsigned )length); |
| 978 | 1032 |
| 979 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::appendB ytes, m_backgroundParser, buffer.release())); | 1033 ASSERT(s_parserThread); |
| 1034 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::appendByte s, m_backgroundParser, buffer.release()))); | |
| 980 return; | 1035 return; |
| 981 } | 1036 } |
| 982 | 1037 |
| 983 DecodedDataDocumentParser::appendBytes(data, length); | 1038 DecodedDataDocumentParser::appendBytes(data, length); |
| 984 } | 1039 } |
| 985 | 1040 |
| 1041 void HTMLDocumentParser::didSwitchedToBackgroundClient() | |
| 1042 { | |
| 1043 if (isDetached()) | |
| 1044 return; | |
| 1045 | |
| 1046 ASSERT(s_parserThread); | |
| 1047 ASSERT(m_haveBackgroundParser); | |
| 1048 // At this point the background parser will start receiving data chunks dire ctly | |
| 1049 // from the I/O thread and we no longer need to pass it any data. | |
| 1050 m_parserThreadIsStandalone = true; | |
| 1051 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::didSwitchedToB ackgroundClient, m_backgroundParser))); | |
| 1052 } | |
| 1053 | |
| 986 void HTMLDocumentParser::flush() | 1054 void HTMLDocumentParser::flush() |
| 987 { | 1055 { |
| 988 // If we've got no decoder, we never received any data. | 1056 // If we've got no decoder, we never received any data. |
| 989 if (isDetached() || needsDecoder()) | 1057 if (isDetached() || needsDecoder()) |
| 990 return; | 1058 return; |
| 991 | 1059 |
| 992 if (m_haveBackgroundParser) | 1060 if (m_haveBackgroundParser) |
| 993 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::flush, m_backgroundParser)); | 1061 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::flush, m_b ackgroundParser))); |
| 994 else | 1062 else |
| 995 DecodedDataDocumentParser::flush(); | 1063 DecodedDataDocumentParser::flush(); |
| 996 } | 1064 } |
| 997 | 1065 |
| 998 void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder) | 1066 void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder) |
| 999 { | 1067 { |
| 1000 ASSERT(decoder); | 1068 ASSERT(decoder); |
| 1001 DecodedDataDocumentParser::setDecoder(decoder); | 1069 DecodedDataDocumentParser::setDecoder(decoder); |
| 1002 | 1070 |
| 1003 if (m_haveBackgroundParser) | 1071 if (m_haveBackgroundParser) |
| 1004 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::setDeco der, m_backgroundParser, takeDecoder())); | 1072 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::setDecoder , m_backgroundParser, takeDecoder()))); |
| 1005 } | 1073 } |
| 1006 | 1074 |
| 1007 } | 1075 } |
| OLD | NEW |