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 20 matching lines...) Expand all Loading... |
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" | 36 #include "core/html/parser/HTMLParserThread.h" |
37 #include "core/html/parser/HTMLScriptRunner.h" | 37 #include "core/html/parser/HTMLScriptRunner.h" |
38 #include "core/html/parser/HTMLTreeBuilder.h" | 38 #include "core/html/parser/HTMLTreeBuilder.h" |
39 #include "core/inspector/InspectorInstrumentation.h" | 39 #include "core/inspector/InspectorInstrumentation.h" |
40 #include "core/frame/Frame.h" | 40 #include "core/frame/Frame.h" |
| 41 #include "platform/SharedBuffer.h" |
41 #include "platform/TraceEvent.h" | 42 #include "platform/TraceEvent.h" |
42 #include "wtf/Functional.h" | 43 #include "wtf/Functional.h" |
43 | 44 |
44 namespace WebCore { | 45 namespace WebCore { |
45 | 46 |
46 using namespace HTMLNames; | 47 using namespace HTMLNames; |
47 | 48 |
48 // This is a direct transcription of step 4 from: | 49 // This is a direct transcription of step 4 from: |
49 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag
ment-case | 50 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag
ment-case |
50 static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem
ent, bool reportErrors, const HTMLParserOptions& options) | 51 static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem
ent, bool reportErrors, const HTMLParserOptions& options) |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 // processParsedChunkFromBackgroundParser can cause this parser to be detach
ed from the Document, | 310 // processParsedChunkFromBackgroundParser can cause this parser to be detach
ed from the Document, |
310 // but we need to ensure it isn't deleted yet. | 311 // but we need to ensure it isn't deleted yet. |
311 RefPtr<HTMLDocumentParser> protect(this); | 312 RefPtr<HTMLDocumentParser> protect(this); |
312 | 313 |
313 ASSERT(m_speculations.isEmpty()); | 314 ASSERT(m_speculations.isEmpty()); |
314 chunk->preloads.clear(); // We don't need to preload because we're going to
parse immediately. | 315 chunk->preloads.clear(); // We don't need to preload because we're going to
parse immediately. |
315 m_speculations.append(chunk); | 316 m_speculations.append(chunk); |
316 pumpPendingSpeculations(); | 317 pumpPendingSpeculations(); |
317 } | 318 } |
318 | 319 |
| 320 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume
ntEncodingData& data) |
| 321 { |
| 322 document()->setEncodingData(data); |
| 323 } |
| 324 |
319 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk) | 325 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk) |
320 { | 326 { |
321 ASSERT(chunk); | 327 ASSERT(chunk); |
322 if (isWaitingForScripts()) { | 328 if (isWaitingForScripts()) { |
323 // We're waiting on a network script, just save the chunk, we'll get | 329 // We're waiting on a network script, just save the chunk, we'll get |
324 // a second validateSpeculations call after the script completes. | 330 // a second validateSpeculations call after the script completes. |
325 // This call should have been made immediately after runScriptsForPaused
TreeBuilder | 331 // This call should have been made immediately after runScriptsForPaused
TreeBuilder |
326 // which may have started a network load and left us waiting. | 332 // which may have started a network load and left us waiting. |
327 ASSERT(!m_lastChunkBeforeScript); | 333 ASSERT(!m_lastChunkBeforeScript); |
328 m_lastChunkBeforeScript = chunk; | 334 m_lastChunkBeforeScript = chunk; |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 | 665 |
660 RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<Backg
roundHTMLParser>::createUnbound(); | 666 RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<Backg
roundHTMLParser>::createUnbound(); |
661 m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference); | 667 m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference); |
662 | 668 |
663 OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new Background
HTMLParser::Configuration); | 669 OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new Background
HTMLParser::Configuration); |
664 config->options = m_options; | 670 config->options = m_options; |
665 config->parser = m_weakFactory.createWeakPtr(); | 671 config->parser = m_weakFactory.createWeakPtr(); |
666 config->xssAuditor = adoptPtr(new XSSAuditor); | 672 config->xssAuditor = adoptPtr(new XSSAuditor); |
667 config->xssAuditor->init(document(), &m_xssAuditorDelegate); | 673 config->xssAuditor->init(document(), &m_xssAuditorDelegate); |
668 config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url().
copy(), document()->devicePixelRatio())); | 674 config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url().
copy(), document()->devicePixelRatio())); |
| 675 config->decoder = takeDecoder(); |
669 | 676 |
670 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); | 677 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); |
671 ASSERT(config->preloadScanner->isSafeToSendToAnotherThread()); | 678 ASSERT(config->preloadScanner->isSafeToSendToAnotherThread()); |
672 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::create, ref
erence.release(), config.release())); | 679 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::start, refe
rence.release(), config.release())); |
673 } | 680 } |
674 | 681 |
675 void HTMLDocumentParser::stopBackgroundParser() | 682 void HTMLDocumentParser::stopBackgroundParser() |
676 { | 683 { |
677 ASSERT(shouldUseThreading()); | 684 ASSERT(shouldUseThreading()); |
678 ASSERT(m_haveBackgroundParser); | 685 ASSERT(m_haveBackgroundParser); |
679 m_haveBackgroundParser = false; | 686 m_haveBackgroundParser = false; |
680 | 687 |
681 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::stop, m_bac
kgroundParser)); | 688 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::stop, m_bac
kgroundParser)); |
682 m_weakFactory.revokeAll(); | 689 m_weakFactory.revokeAll(); |
683 } | 690 } |
684 | 691 |
685 void HTMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) | 692 void HTMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) |
686 { | 693 { |
687 if (isStopped()) | 694 if (isStopped()) |
688 return; | 695 return; |
689 | 696 |
690 if (shouldUseThreading()) { | 697 // We should never reach this point if we're using a parser thread, |
691 if (!m_haveBackgroundParser) | 698 // as appendBytes() will directly ship the data to the thread. |
692 startBackgroundParser(); | 699 ASSERT(!shouldUseThreading()); |
693 | |
694 ASSERT(inputSource->hasOneRef()); | |
695 TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->l
ength()); | |
696 // NOTE: Important that the String temporary is destroyed before we post
the task | |
697 // otherwise the String could call deref() on a StringImpl now owned by
the background parser. | |
698 // We would like to ASSERT(closure.arg3()->hasOneRef()) but sadly the ar
gs are private. | |
699 Closure closure = bind(&BackgroundHTMLParser::append, m_backgroundParser
, String(inputSource)); | |
700 HTMLParserThread::shared()->postTask(closure); | |
701 return; | |
702 } | |
703 | 700 |
704 // pumpTokenizer can cause this parser to be detached from the Document, | 701 // pumpTokenizer can cause this parser to be detached from the Document, |
705 // but we need to ensure it isn't deleted yet. | 702 // but we need to ensure it isn't deleted yet. |
706 RefPtr<HTMLDocumentParser> protect(this); | 703 RefPtr<HTMLDocumentParser> protect(this); |
707 TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->lengt
h()); | 704 TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->lengt
h()); |
708 String source(inputSource); | 705 String source(inputSource); |
709 | 706 |
710 if (m_preloadScanner) { | 707 if (m_preloadScanner) { |
711 if (m_input.current().isEmpty() && !isWaitingForScripts()) { | 708 if (m_input.current().isEmpty() && !isWaitingForScripts()) { |
712 // We have parsed until the end of the current input and so are now
moving ahead of the preload scanner. | 709 // We have parsed until the end of the current input and so are now
moving ahead of the preload scanner. |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
958 if (m_parserScheduler) | 955 if (m_parserScheduler) |
959 m_parserScheduler->suspend(); | 956 m_parserScheduler->suspend(); |
960 } | 957 } |
961 | 958 |
962 void HTMLDocumentParser::resumeScheduledTasks() | 959 void HTMLDocumentParser::resumeScheduledTasks() |
963 { | 960 { |
964 if (m_parserScheduler) | 961 if (m_parserScheduler) |
965 m_parserScheduler->resume(); | 962 m_parserScheduler->resume(); |
966 } | 963 } |
967 | 964 |
| 965 void HTMLDocumentParser::appendBytes(const char* data, size_t length) |
| 966 { |
| 967 if (!length || isDetached()) |
| 968 return; |
| 969 |
| 970 if (shouldUseThreading()) { |
| 971 if (!m_haveBackgroundParser) |
| 972 startBackgroundParser(); |
| 973 |
| 974 OwnPtr<Vector<char> > buffer = adoptPtr(new Vector<char>(length)); |
| 975 memcpy(buffer->data(), data, length); |
| 976 TRACE_EVENT1("net", "HTMLDocumentParser::appendBytes", "size", (unsigned
)length); |
| 977 |
| 978 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::appendB
ytes, m_backgroundParser, buffer.release())); |
| 979 return; |
| 980 } |
| 981 |
| 982 DecodedDataDocumentParser::appendBytes(data, length); |
968 } | 983 } |
| 984 |
| 985 void HTMLDocumentParser::flush() |
| 986 { |
| 987 // If we've got no decoder, we never received any data. |
| 988 if (isDetached() || needsDecoder()) |
| 989 return; |
| 990 |
| 991 if (m_haveBackgroundParser) |
| 992 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::flush,
m_backgroundParser)); |
| 993 else |
| 994 DecodedDataDocumentParser::flush(); |
| 995 } |
| 996 |
| 997 void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder) |
| 998 { |
| 999 DecodedDataDocumentParser::setDecoder(decoder); |
| 1000 |
| 1001 if (m_haveBackgroundParser) |
| 1002 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::setDeco
der, m_backgroundParser, takeDecoder())); |
| 1003 } |
| 1004 |
| 1005 } |
OLD | NEW |