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 |