| 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 27 matching lines...) Expand all Loading... |
| 38 #include "core/html/parser/BackgroundHTMLParser.h" | 38 #include "core/html/parser/BackgroundHTMLParser.h" |
| 39 #include "core/html/parser/HTMLParserScheduler.h" | 39 #include "core/html/parser/HTMLParserScheduler.h" |
| 40 #include "core/html/parser/HTMLParserThread.h" | 40 #include "core/html/parser/HTMLParserThread.h" |
| 41 #include "core/html/parser/HTMLScriptRunner.h" | 41 #include "core/html/parser/HTMLScriptRunner.h" |
| 42 #include "core/html/parser/HTMLTreeBuilder.h" | 42 #include "core/html/parser/HTMLTreeBuilder.h" |
| 43 #include "core/inspector/InspectorInstrumentation.h" | 43 #include "core/inspector/InspectorInstrumentation.h" |
| 44 #include "core/inspector/InspectorTraceEvents.h" | 44 #include "core/inspector/InspectorTraceEvents.h" |
| 45 #include "core/loader/DocumentLoader.h" | 45 #include "core/loader/DocumentLoader.h" |
| 46 #include "core/loader/LinkLoader.h" | 46 #include "core/loader/LinkLoader.h" |
| 47 #include "core/loader/NavigationScheduler.h" | 47 #include "core/loader/NavigationScheduler.h" |
| 48 #include "platform/CrossThreadFunctional.h" |
| 48 #include "platform/Histogram.h" | 49 #include "platform/Histogram.h" |
| 49 #include "platform/SharedBuffer.h" | 50 #include "platform/SharedBuffer.h" |
| 50 #include "platform/ThreadSafeFunctional.h" | |
| 51 #include "platform/TraceEvent.h" | 51 #include "platform/TraceEvent.h" |
| 52 #include "platform/heap/Handle.h" | 52 #include "platform/heap/Handle.h" |
| 53 #include "public/platform/Platform.h" | 53 #include "public/platform/Platform.h" |
| 54 #include "public/platform/WebFrameScheduler.h" | 54 #include "public/platform/WebFrameScheduler.h" |
| 55 #include "public/platform/WebLoadingBehaviorFlag.h" | 55 #include "public/platform/WebLoadingBehaviorFlag.h" |
| 56 #include "public/platform/WebScheduler.h" | 56 #include "public/platform/WebScheduler.h" |
| 57 #include "public/platform/WebThread.h" | 57 #include "public/platform/WebThread.h" |
| 58 #include "wtf/PtrUtil.h" | 58 #include "wtf/PtrUtil.h" |
| 59 #include "wtf/TemporaryChange.h" | 59 #include "wtf/TemporaryChange.h" |
| 60 #include <memory> | 60 #include <memory> |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 checkpoint->parser = m_weakFactory.createWeakPtr(); | 403 checkpoint->parser = m_weakFactory.createWeakPtr(); |
| 404 checkpoint->token = std::move(token); | 404 checkpoint->token = std::move(token); |
| 405 checkpoint->tokenizer = std::move(tokenizer); | 405 checkpoint->tokenizer = std::move(tokenizer); |
| 406 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil
der.get()); | 406 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil
der.get()); |
| 407 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; | 407 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; |
| 408 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner
Checkpoint; | 408 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner
Checkpoint; |
| 409 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); | 409 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); |
| 410 m_input.current().clear(); // FIXME: This should be passed in instead of cle
ared. | 410 m_input.current().clear(); // FIXME: This should be passed in instead of cle
ared. |
| 411 | 411 |
| 412 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); | 412 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); |
| 413 postTaskToLookaheadParser(threadSafeBind(&BackgroundHTMLParser::resumeFrom,
m_backgroundParser, passed(std::move(checkpoint)))); | 413 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::resumeFrom,
m_backgroundParser, passed(std::move(checkpoint)))); |
| 414 } | 414 } |
| 415 | 415 |
| 416 size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(std::unique_pt
r<ParsedChunk> popChunk) | 416 size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(std::unique_pt
r<ParsedChunk> popChunk) |
| 417 { | 417 { |
| 418 TRACE_EVENT_WITH_FLOW0("blink,loading", "HTMLDocumentParser::processParsedCh
unkFromBackgroundParser", popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); | 418 TRACE_EVENT_WITH_FLOW0("blink,loading", "HTMLDocumentParser::processParsedCh
unkFromBackgroundParser", popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); |
| 419 TemporaryChange<bool> hasLineNumber(m_isParsingAtLineNumber, true); | 419 TemporaryChange<bool> hasLineNumber(m_isParsingAtLineNumber, true); |
| 420 | 420 |
| 421 ASSERT_WITH_SECURITY_IMPLICATION(m_pumpSpeculationsSessionNestingLevel == 1)
; | 421 ASSERT_WITH_SECURITY_IMPLICATION(m_pumpSpeculationsSessionNestingLevel == 1)
; |
| 422 ASSERT_WITH_SECURITY_IMPLICATION(!inPumpSession()); | 422 ASSERT_WITH_SECURITY_IMPLICATION(!inPumpSession()); |
| 423 ASSERT(!isParsingFragment()); | 423 ASSERT(!isParsingFragment()); |
| 424 ASSERT(!isWaitingForScripts()); | 424 ASSERT(!isWaitingForScripts()); |
| 425 ASSERT(!isStopped()); | 425 ASSERT(!isStopped()); |
| 426 ASSERT(shouldUseThreading()); | 426 ASSERT(shouldUseThreading()); |
| 427 ASSERT(!m_tokenizer); | 427 ASSERT(!m_tokenizer); |
| 428 ASSERT(!m_token); | 428 ASSERT(!m_token); |
| 429 ASSERT(!m_lastChunkBeforeScript); | 429 ASSERT(!m_lastChunkBeforeScript); |
| 430 | 430 |
| 431 std::unique_ptr<ParsedChunk> chunk(std::move(popChunk)); | 431 std::unique_ptr<ParsedChunk> chunk(std::move(popChunk)); |
| 432 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); | 432 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); |
| 433 size_t elementTokenCount = 0; | 433 size_t elementTokenCount = 0; |
| 434 | 434 |
| 435 postTaskToLookaheadParser(threadSafeBind(&BackgroundHTMLParser::startedChunk
WithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); | 435 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::startedChun
kWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); |
| 436 | 436 |
| 437 for (const auto& xssInfo : chunk->xssInfos) { | 437 for (const auto& xssInfo : chunk->xssInfos) { |
| 438 m_textPosition = xssInfo->m_textPosition; | 438 m_textPosition = xssInfo->m_textPosition; |
| 439 m_xssAuditorDelegate.didBlockScript(*xssInfo); | 439 m_xssAuditorDelegate.didBlockScript(*xssInfo); |
| 440 if (isStopped()) | 440 if (isStopped()) |
| 441 break; | 441 break; |
| 442 } | 442 } |
| 443 // XSSAuditorDelegate can detach the parser if it decides to block the entir
e current document. | 443 // XSSAuditorDelegate can detach the parser if it decides to block the entir
e current document. |
| 444 if (isDetached()) | 444 if (isDetached()) |
| 445 return elementTokenCount; | 445 return elementTokenCount; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 } | 556 } |
| 557 | 557 |
| 558 void HTMLDocumentParser::forcePlaintextForTextDocument() | 558 void HTMLDocumentParser::forcePlaintextForTextDocument() |
| 559 { | 559 { |
| 560 if (shouldUseThreading()) { | 560 if (shouldUseThreading()) { |
| 561 // This method is called before any data is appended, so we have to star
t | 561 // This method is called before any data is appended, so we have to star
t |
| 562 // the background parser ourselves. | 562 // the background parser ourselves. |
| 563 if (!m_haveBackgroundParser) | 563 if (!m_haveBackgroundParser) |
| 564 startBackgroundParser(); | 564 startBackgroundParser(); |
| 565 | 565 |
| 566 postTaskToLookaheadParser(threadSafeBind(&BackgroundHTMLParser::forcePla
intextForTextDocument, m_backgroundParser)); | 566 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::forcePl
aintextForTextDocument, m_backgroundParser)); |
| 567 } else | 567 } else |
| 568 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); | 568 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); |
| 569 } | 569 } |
| 570 | 570 |
| 571 void HTMLDocumentParser::pumpTokenizer() | 571 void HTMLDocumentParser::pumpTokenizer() |
| 572 { | 572 { |
| 573 ASSERT(!isStopped()); | 573 ASSERT(!isStopped()); |
| 574 ASSERT(m_tokenizer); | 574 ASSERT(m_tokenizer); |
| 575 ASSERT(m_token); | 575 ASSERT(m_token); |
| 576 | 576 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 config->decoder = takeDecoder(); | 732 config->decoder = takeDecoder(); |
| 733 config->parsedChunkQueue = m_parsedChunkQueue.get(); | 733 config->parsedChunkQueue = m_parsedChunkQueue.get(); |
| 734 if (document()->settings()) { | 734 if (document()->settings()) { |
| 735 if (document()->settings()->backgroundHtmlParserOutstandingTokenLimit()) | 735 if (document()->settings()->backgroundHtmlParserOutstandingTokenLimit()) |
| 736 config->outstandingTokenLimit = document()->settings()->backgroundHt
mlParserOutstandingTokenLimit(); | 736 config->outstandingTokenLimit = document()->settings()->backgroundHt
mlParserOutstandingTokenLimit(); |
| 737 if (document()->settings()->backgroundHtmlParserPendingTokenLimit()) | 737 if (document()->settings()->backgroundHtmlParserPendingTokenLimit()) |
| 738 config->pendingTokenLimit = document()->settings()->backgroundHtmlPa
rserPendingTokenLimit(); | 738 config->pendingTokenLimit = document()->settings()->backgroundHtmlPa
rserPendingTokenLimit(); |
| 739 } | 739 } |
| 740 | 740 |
| 741 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); | 741 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); |
| 742 postTaskToLookaheadParser(threadSafeBind( | 742 postTaskToLookaheadParser(crossThreadBind( |
| 743 &BackgroundHTMLParser::start, | 743 &BackgroundHTMLParser::start, |
| 744 reference.release(), | 744 reference.release(), |
| 745 passed(std::move(config)), | 745 passed(std::move(config)), |
| 746 document()->url(), | 746 document()->url(), |
| 747 passed(CachedDocumentParameters::create(document())), | 747 passed(CachedDocumentParameters::create(document())), |
| 748 MediaValuesCached::MediaValuesCachedData(*document()), | 748 MediaValuesCached::MediaValuesCachedData(*document()), |
| 749 passed(wrapUnique(m_loadingTaskRunner->clone()))), Synchronous); | 749 passed(wrapUnique(m_loadingTaskRunner->clone()))), Synchronous); |
| 750 } | 750 } |
| 751 | 751 |
| 752 void HTMLDocumentParser::stopBackgroundParser() | 752 void HTMLDocumentParser::stopBackgroundParser() |
| 753 { | 753 { |
| 754 ASSERT(shouldUseThreading()); | 754 ASSERT(shouldUseThreading()); |
| 755 ASSERT(m_haveBackgroundParser); | 755 ASSERT(m_haveBackgroundParser); |
| 756 m_haveBackgroundParser = false; | 756 m_haveBackgroundParser = false; |
| 757 | 757 |
| 758 // Make this sync, as lsan triggers on some unittests if the task runner is | 758 // Make this sync, as lsan triggers on some unittests if the task runner is |
| 759 // used. Note that these lifetimes will be much more concrete if | 759 // used. Note that these lifetimes will be much more concrete if |
| 760 // ParseHTMLOnMainThread lands (the lookahead parser will be a member). | 760 // ParseHTMLOnMainThread lands (the lookahead parser will be a member). |
| 761 postTaskToLookaheadParser(threadSafeBind(&BackgroundHTMLParser::stop, m_back
groundParser), Synchronous); | 761 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::stop, m_bac
kgroundParser), Synchronous); |
| 762 m_weakFactory.revokeAll(); | 762 m_weakFactory.revokeAll(); |
| 763 } | 763 } |
| 764 | 764 |
| 765 void HTMLDocumentParser::append(const String& inputSource) | 765 void HTMLDocumentParser::append(const String& inputSource) |
| 766 { | 766 { |
| 767 if (isStopped()) | 767 if (isStopped()) |
| 768 return; | 768 return; |
| 769 | 769 |
| 770 // We should never reach this point if we're using a parser thread, | 770 // We should never reach this point if we're using a parser thread, |
| 771 // as appendBytes() will directly ship the data to the thread. | 771 // as appendBytes() will directly ship the data to the thread. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 flush(); | 859 flush(); |
| 860 if (isDetached()) | 860 if (isDetached()) |
| 861 return; | 861 return; |
| 862 | 862 |
| 863 // Empty documents never got an append() call, and thus have never started | 863 // Empty documents never got an append() call, and thus have never started |
| 864 // a background parser. In those cases, we ignore shouldUseThreading() | 864 // a background parser. In those cases, we ignore shouldUseThreading() |
| 865 // and fall through to the non-threading case. | 865 // and fall through to the non-threading case. |
| 866 if (m_haveBackgroundParser) { | 866 if (m_haveBackgroundParser) { |
| 867 if (!m_input.haveSeenEndOfFile()) | 867 if (!m_input.haveSeenEndOfFile()) |
| 868 m_input.closeWithoutMarkingEndOfFile(); | 868 m_input.closeWithoutMarkingEndOfFile(); |
| 869 postTaskToLookaheadParser(threadSafeBind(&BackgroundHTMLParser::finish,
m_backgroundParser)); | 869 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::finish,
m_backgroundParser)); |
| 870 return; | 870 return; |
| 871 } | 871 } |
| 872 | 872 |
| 873 if (!m_tokenizer) { | 873 if (!m_tokenizer) { |
| 874 ASSERT(!m_token); | 874 ASSERT(!m_token); |
| 875 // We're finishing before receiving any data. Rather than booting up | 875 // We're finishing before receiving any data. Rather than booting up |
| 876 // the background parser just to spin it down, we finish parsing | 876 // the background parser just to spin it down, we finish parsing |
| 877 // synchronously. | 877 // synchronously. |
| 878 m_token = wrapUnique(new HTMLToken); | 878 m_token = wrapUnique(new HTMLToken); |
| 879 m_tokenizer = HTMLTokenizer::create(m_options); | 879 m_tokenizer = HTMLTokenizer::create(m_options); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1025 | 1025 |
| 1026 if (shouldUseThreading()) { | 1026 if (shouldUseThreading()) { |
| 1027 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); | 1027 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); |
| 1028 if (!m_haveBackgroundParser) | 1028 if (!m_haveBackgroundParser) |
| 1029 startBackgroundParser(); | 1029 startBackgroundParser(); |
| 1030 | 1030 |
| 1031 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(lengt
h)); | 1031 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(lengt
h)); |
| 1032 memcpy(buffer->data(), data, length); | 1032 memcpy(buffer->data(), data, length); |
| 1033 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentPars
er::appendBytes", "size", (unsigned)length); | 1033 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentPars
er::appendBytes", "size", (unsigned)length); |
| 1034 | 1034 |
| 1035 postTaskToLookaheadParser(threadSafeBind(&BackgroundHTMLParser::appendRa
wBytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesReceiv
edTime)); | 1035 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::appendR
awBytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesRecei
vedTime)); |
| 1036 return; | 1036 return; |
| 1037 } | 1037 } |
| 1038 | 1038 |
| 1039 DecodedDataDocumentParser::appendBytes(data, length); | 1039 DecodedDataDocumentParser::appendBytes(data, length); |
| 1040 } | 1040 } |
| 1041 | 1041 |
| 1042 void HTMLDocumentParser::flush() | 1042 void HTMLDocumentParser::flush() |
| 1043 { | 1043 { |
| 1044 // If we've got no decoder, we never received any data. | 1044 // If we've got no decoder, we never received any data. |
| 1045 if (isDetached() || needsDecoder()) | 1045 if (isDetached() || needsDecoder()) |
| 1046 return; | 1046 return; |
| 1047 | 1047 |
| 1048 if (shouldUseThreading()) { | 1048 if (shouldUseThreading()) { |
| 1049 // In some cases, flush() is called without any invocation of | 1049 // In some cases, flush() is called without any invocation of |
| 1050 // appendBytes. Fallback to synchronous parsing in that case. | 1050 // appendBytes. Fallback to synchronous parsing in that case. |
| 1051 if (!m_haveBackgroundParser) { | 1051 if (!m_haveBackgroundParser) { |
| 1052 m_shouldUseThreading = false; | 1052 m_shouldUseThreading = false; |
| 1053 m_token = wrapUnique(new HTMLToken); | 1053 m_token = wrapUnique(new HTMLToken); |
| 1054 m_tokenizer = HTMLTokenizer::create(m_options); | 1054 m_tokenizer = HTMLTokenizer::create(m_options); |
| 1055 DecodedDataDocumentParser::flush(); | 1055 DecodedDataDocumentParser::flush(); |
| 1056 return; | 1056 return; |
| 1057 } | 1057 } |
| 1058 | 1058 |
| 1059 postTaskToLookaheadParser(threadSafeBind(&BackgroundHTMLParser::flush, m
_backgroundParser)); | 1059 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::flush,
m_backgroundParser)); |
| 1060 } else { | 1060 } else { |
| 1061 DecodedDataDocumentParser::flush(); | 1061 DecodedDataDocumentParser::flush(); |
| 1062 } | 1062 } |
| 1063 } | 1063 } |
| 1064 | 1064 |
| 1065 void HTMLDocumentParser::setDecoder(std::unique_ptr<TextResourceDecoder> decoder
) | 1065 void HTMLDocumentParser::setDecoder(std::unique_ptr<TextResourceDecoder> decoder
) |
| 1066 { | 1066 { |
| 1067 ASSERT(decoder); | 1067 ASSERT(decoder); |
| 1068 DecodedDataDocumentParser::setDecoder(std::move(decoder)); | 1068 DecodedDataDocumentParser::setDecoder(std::move(decoder)); |
| 1069 | 1069 |
| 1070 if (m_haveBackgroundParser) | 1070 if (m_haveBackgroundParser) |
| 1071 postTaskToLookaheadParser(threadSafeBind(&BackgroundHTMLParser::setDecod
er, m_backgroundParser, passed(takeDecoder()))); | 1071 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::setDeco
der, m_backgroundParser, passed(takeDecoder()))); |
| 1072 } | 1072 } |
| 1073 | 1073 |
| 1074 void HTMLDocumentParser::documentElementAvailable() | 1074 void HTMLDocumentParser::documentElementAvailable() |
| 1075 { | 1075 { |
| 1076 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable")
; | 1076 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable")
; |
| 1077 DCHECK(document()->documentElement()); | 1077 DCHECK(document()->documentElement()); |
| 1078 for (const String& scriptSource : m_queuedDocumentWriteScripts) { | 1078 for (const String& scriptSource : m_queuedDocumentWriteScripts) { |
| 1079 evaluateAndPreloadScriptForDocumentWrite(scriptSource); | 1079 evaluateAndPreloadScriptForDocumentWrite(scriptSource); |
| 1080 } | 1080 } |
| 1081 | 1081 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1146 (*closure)(); | 1146 (*closure)(); |
| 1147 return; | 1147 return; |
| 1148 case Asynchronous: | 1148 case Asynchronous: |
| 1149 m_loadingTaskRunner->postTask(BLINK_FROM_HERE, std::move(closure)); | 1149 m_loadingTaskRunner->postTask(BLINK_FROM_HERE, std::move(closure)); |
| 1150 return; | 1150 return; |
| 1151 } | 1151 } |
| 1152 NOTREACHED(); | 1152 NOTREACHED(); |
| 1153 } | 1153 } |
| 1154 | 1154 |
| 1155 } // namespace blink | 1155 } // namespace blink |
| OLD | NEW |