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 392 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(crossThreadBind(&BackgroundHTMLParser::resumeFrom,
m_backgroundParser, passed(std::move(checkpoint)))); | 413 postTaskToLookaheadParser(Asynchronous, &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(crossThreadBind(&BackgroundHTMLParser::startedChun
kWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); | 435 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::startedChunkW
ithCheckpoint, 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(crossThreadBind(&BackgroundHTMLParser::forcePl
aintextForTextDocument, m_backgroundParser)); | 566 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::forcePlai
ntextForTextDocument, 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(crossThreadBind( | 742 postTaskToLookaheadParser( |
| 743 Synchronous, |
743 &BackgroundHTMLParser::start, | 744 &BackgroundHTMLParser::start, |
744 reference.release(), | 745 reference.release(), |
745 passed(std::move(config)), | 746 passed(std::move(config)), |
746 document()->url(), | 747 document()->url(), |
747 passed(CachedDocumentParameters::create(document())), | 748 passed(CachedDocumentParameters::create(document())), |
748 MediaValuesCached::MediaValuesCachedData(*document()), | 749 MediaValuesCached::MediaValuesCachedData(*document()), |
749 passed(wrapUnique(m_loadingTaskRunner->clone()))), Synchronous); | 750 passed(wrapUnique(m_loadingTaskRunner->clone()))); |
750 } | 751 } |
751 | 752 |
752 void HTMLDocumentParser::stopBackgroundParser() | 753 void HTMLDocumentParser::stopBackgroundParser() |
753 { | 754 { |
754 ASSERT(shouldUseThreading()); | 755 ASSERT(shouldUseThreading()); |
755 ASSERT(m_haveBackgroundParser); | 756 ASSERT(m_haveBackgroundParser); |
756 m_haveBackgroundParser = false; | 757 m_haveBackgroundParser = false; |
757 | 758 |
758 // Make this sync, as lsan triggers on some unittests if the task runner is | 759 // 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 | 760 // used. Note that these lifetimes will be much more concrete if |
760 // ParseHTMLOnMainThread lands (the lookahead parser will be a member). | 761 // ParseHTMLOnMainThread lands (the lookahead parser will be a member). |
761 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::stop, m_bac
kgroundParser), Synchronous); | 762 postTaskToLookaheadParser(Synchronous, &BackgroundHTMLParser::stop, m_backgr
oundParser); |
762 m_weakFactory.revokeAll(); | 763 m_weakFactory.revokeAll(); |
763 } | 764 } |
764 | 765 |
765 void HTMLDocumentParser::append(const String& inputSource) | 766 void HTMLDocumentParser::append(const String& inputSource) |
766 { | 767 { |
767 if (isStopped()) | 768 if (isStopped()) |
768 return; | 769 return; |
769 | 770 |
770 // We should never reach this point if we're using a parser thread, | 771 // We should never reach this point if we're using a parser thread, |
771 // as appendBytes() will directly ship the data to the thread. | 772 // 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(); | 860 flush(); |
860 if (isDetached()) | 861 if (isDetached()) |
861 return; | 862 return; |
862 | 863 |
863 // Empty documents never got an append() call, and thus have never started | 864 // Empty documents never got an append() call, and thus have never started |
864 // a background parser. In those cases, we ignore shouldUseThreading() | 865 // a background parser. In those cases, we ignore shouldUseThreading() |
865 // and fall through to the non-threading case. | 866 // and fall through to the non-threading case. |
866 if (m_haveBackgroundParser) { | 867 if (m_haveBackgroundParser) { |
867 if (!m_input.haveSeenEndOfFile()) | 868 if (!m_input.haveSeenEndOfFile()) |
868 m_input.closeWithoutMarkingEndOfFile(); | 869 m_input.closeWithoutMarkingEndOfFile(); |
869 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::finish,
m_backgroundParser)); | 870 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::finish, m
_backgroundParser); |
870 return; | 871 return; |
871 } | 872 } |
872 | 873 |
873 if (!m_tokenizer) { | 874 if (!m_tokenizer) { |
874 ASSERT(!m_token); | 875 ASSERT(!m_token); |
875 // We're finishing before receiving any data. Rather than booting up | 876 // We're finishing before receiving any data. Rather than booting up |
876 // the background parser just to spin it down, we finish parsing | 877 // the background parser just to spin it down, we finish parsing |
877 // synchronously. | 878 // synchronously. |
878 m_token = wrapUnique(new HTMLToken); | 879 m_token = wrapUnique(new HTMLToken); |
879 m_tokenizer = HTMLTokenizer::create(m_options); | 880 m_tokenizer = HTMLTokenizer::create(m_options); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 if (shouldUseThreading()) { | 1027 if (shouldUseThreading()) { |
1027 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); | 1028 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); |
1028 if (!m_haveBackgroundParser) | 1029 if (!m_haveBackgroundParser) |
1029 startBackgroundParser(); | 1030 startBackgroundParser(); |
1030 | 1031 |
1031 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(lengt
h)); | 1032 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(lengt
h)); |
1032 memcpy(buffer->data(), data, length); | 1033 memcpy(buffer->data(), data, length); |
1033 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentPars
er::appendBytes", "size", (unsigned)length); | 1034 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentPars
er::appendBytes", "size", (unsigned)length); |
1034 | 1035 |
1035 LookaheadParserTaskSynchrony policy = document()->settings() && document
()->settings()->parseHTMLOnMainThreadSyncTokenize() ? Synchronous : Asynchronous
; | 1036 LookaheadParserTaskSynchrony policy = document()->settings() && document
()->settings()->parseHTMLOnMainThreadSyncTokenize() ? Synchronous : Asynchronous
; |
1036 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::appendR
awBytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesRecei
vedTime), policy); | 1037 postTaskToLookaheadParser(policy, &BackgroundHTMLParser::appendRawBytesF
romMainThread, m_backgroundParser, passed(std::move(buffer)), bytesReceivedTime)
; |
1037 return; | 1038 return; |
1038 } | 1039 } |
1039 | 1040 |
1040 DecodedDataDocumentParser::appendBytes(data, length); | 1041 DecodedDataDocumentParser::appendBytes(data, length); |
1041 } | 1042 } |
1042 | 1043 |
1043 void HTMLDocumentParser::flush() | 1044 void HTMLDocumentParser::flush() |
1044 { | 1045 { |
1045 // If we've got no decoder, we never received any data. | 1046 // If we've got no decoder, we never received any data. |
1046 if (isDetached() || needsDecoder()) | 1047 if (isDetached() || needsDecoder()) |
1047 return; | 1048 return; |
1048 | 1049 |
1049 if (shouldUseThreading()) { | 1050 if (shouldUseThreading()) { |
1050 // In some cases, flush() is called without any invocation of | 1051 // In some cases, flush() is called without any invocation of |
1051 // appendBytes. Fallback to synchronous parsing in that case. | 1052 // appendBytes. Fallback to synchronous parsing in that case. |
1052 if (!m_haveBackgroundParser) { | 1053 if (!m_haveBackgroundParser) { |
1053 m_shouldUseThreading = false; | 1054 m_shouldUseThreading = false; |
1054 m_token = wrapUnique(new HTMLToken); | 1055 m_token = wrapUnique(new HTMLToken); |
1055 m_tokenizer = HTMLTokenizer::create(m_options); | 1056 m_tokenizer = HTMLTokenizer::create(m_options); |
1056 DecodedDataDocumentParser::flush(); | 1057 DecodedDataDocumentParser::flush(); |
1057 return; | 1058 return; |
1058 } | 1059 } |
1059 | 1060 |
1060 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::flush,
m_backgroundParser)); | 1061 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::flush, m_
backgroundParser); |
1061 } else { | 1062 } else { |
1062 DecodedDataDocumentParser::flush(); | 1063 DecodedDataDocumentParser::flush(); |
1063 } | 1064 } |
1064 } | 1065 } |
1065 | 1066 |
1066 void HTMLDocumentParser::setDecoder(std::unique_ptr<TextResourceDecoder> decoder
) | 1067 void HTMLDocumentParser::setDecoder(std::unique_ptr<TextResourceDecoder> decoder
) |
1067 { | 1068 { |
1068 ASSERT(decoder); | 1069 ASSERT(decoder); |
1069 DecodedDataDocumentParser::setDecoder(std::move(decoder)); | 1070 DecodedDataDocumentParser::setDecoder(std::move(decoder)); |
1070 | 1071 |
1071 if (m_haveBackgroundParser) | 1072 if (m_haveBackgroundParser) |
1072 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::setDeco
der, m_backgroundParser, passed(takeDecoder()))); | 1073 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::setDecode
r, m_backgroundParser, passed(takeDecoder())); |
1073 } | 1074 } |
1074 | 1075 |
1075 void HTMLDocumentParser::documentElementAvailable() | 1076 void HTMLDocumentParser::documentElementAvailable() |
1076 { | 1077 { |
1077 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable")
; | 1078 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable")
; |
1078 DCHECK(document()->documentElement()); | 1079 DCHECK(document()->documentElement()); |
1079 if (!m_queuedPreloads.isEmpty()) | 1080 if (!m_queuedPreloads.isEmpty()) |
1080 m_preloader->takeAndPreload(m_queuedPreloads); | 1081 m_preloader->takeAndPreload(m_queuedPreloads); |
1081 | 1082 |
1082 for (const String& scriptSource : m_queuedDocumentWriteScripts) { | 1083 for (const String& scriptSource : m_queuedDocumentWriteScripts) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1127 | 1128 |
1128 if (numPreloads) { | 1129 if (numPreloads) { |
1129 DEFINE_STATIC_LOCAL(CustomCountHistogram, successHistogram, ("PreloadSca
nner.DocumentWrite.ExecutionTime.Success", 1, 10000, 50)); | 1130 DEFINE_STATIC_LOCAL(CustomCountHistogram, successHistogram, ("PreloadSca
nner.DocumentWrite.ExecutionTime.Success", 1, 10000, 50)); |
1130 successHistogram.count(duration); | 1131 successHistogram.count(duration); |
1131 } else { | 1132 } else { |
1132 DEFINE_STATIC_LOCAL(CustomCountHistogram, failureHistogram, ("PreloadSca
nner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); | 1133 DEFINE_STATIC_LOCAL(CustomCountHistogram, failureHistogram, ("PreloadSca
nner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); |
1133 failureHistogram.count(duration); | 1134 failureHistogram.count(duration); |
1134 } | 1135 } |
1135 } | 1136 } |
1136 | 1137 |
1137 void HTMLDocumentParser::postTaskToLookaheadParser(std::unique_ptr<CrossThreadCl
osure> closure, LookaheadParserTaskSynchrony synchronyPolicy) | 1138 template <typename FunctionType, typename... Ps> |
| 1139 void HTMLDocumentParser::postTaskToLookaheadParser(LookaheadParserTaskSynchrony
synchronyPolicy, FunctionType function, Ps&&... parameters) |
1138 { | 1140 { |
1139 if (!RuntimeEnabledFeatures::parseHTMLOnMainThreadEnabled()) { | 1141 if (!RuntimeEnabledFeatures::parseHTMLOnMainThreadEnabled()) { |
1140 HTMLParserThread::shared()->postTask(std::move(closure)); | 1142 HTMLParserThread::shared()->postTask(crossThreadBind(function, std::forw
ard<Ps>(parameters)...)); |
1141 return; | 1143 return; |
1142 } | 1144 } |
1143 | 1145 |
1144 // Some messages to the lookahead parser should be synchronous. Otherwise, | 1146 // Some messages to the lookahead parser should be synchronous. Otherwise, |
1145 // just post to the loading task runner. | 1147 // just post to the loading task runner. |
1146 switch (synchronyPolicy) { | 1148 switch (synchronyPolicy) { |
1147 case Synchronous: | 1149 case Synchronous: |
1148 (*closure)(); | 1150 (*WTF::bind(function, std::forward<Ps>(parameters)...))(); |
1149 return; | 1151 return; |
1150 case Asynchronous: | 1152 case Asynchronous: |
1151 m_loadingTaskRunner->postTask(BLINK_FROM_HERE, std::move(closure)); | 1153 m_loadingTaskRunner->postTask(BLINK_FROM_HERE, WTF::bind(function, std::
forward<Ps>(parameters)...)); |
1152 return; | 1154 return; |
1153 } | 1155 } |
1154 NOTREACHED(); | 1156 NOTREACHED(); |
1155 } | 1157 } |
1156 | 1158 |
1157 } // namespace blink | 1159 } // namespace blink |
OLD | NEW |