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 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 checkpoint->parser = m_weakFactory.createWeakPtr(); | 396 checkpoint->parser = m_weakFactory.createWeakPtr(); |
| 397 checkpoint->token = std::move(token); | 397 checkpoint->token = std::move(token); |
| 398 checkpoint->tokenizer = std::move(tokenizer); | 398 checkpoint->tokenizer = std::move(tokenizer); |
| 399 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil der.get()); | 399 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil der.get()); |
| 400 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; | 400 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; |
| 401 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner Checkpoint; | 401 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner Checkpoint; |
| 402 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); | 402 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); |
| 403 m_input.current().clear(); // FIXME: This should be passed in instead of cle ared. | 403 m_input.current().clear(); // FIXME: This should be passed in instead of cle ared. |
| 404 | 404 |
| 405 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); | 405 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); |
| 406 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, passed(std::move(checkpoint)))); | 406 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::resumeFrom, m _backgroundParser, passed(std::move(checkpoint))); |
| 407 } | 407 } |
| 408 | 408 |
| 409 size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(std::unique_pt r<ParsedChunk> popChunk) | 409 size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(std::unique_pt r<ParsedChunk> popChunk) |
| 410 { | 410 { |
| 411 TRACE_EVENT_WITH_FLOW0("blink,loading", "HTMLDocumentParser::processParsedCh unkFromBackgroundParser", popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); | 411 TRACE_EVENT_WITH_FLOW0("blink,loading", "HTMLDocumentParser::processParsedCh unkFromBackgroundParser", popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); |
| 412 TemporaryChange<bool> hasLineNumber(m_isParsingAtLineNumber, true); | 412 TemporaryChange<bool> hasLineNumber(m_isParsingAtLineNumber, true); |
| 413 | 413 |
| 414 ASSERT_WITH_SECURITY_IMPLICATION(m_pumpSpeculationsSessionNestingLevel == 1) ; | 414 ASSERT_WITH_SECURITY_IMPLICATION(m_pumpSpeculationsSessionNestingLevel == 1) ; |
| 415 ASSERT_WITH_SECURITY_IMPLICATION(!inPumpSession()); | 415 ASSERT_WITH_SECURITY_IMPLICATION(!inPumpSession()); |
| 416 ASSERT(!isParsingFragment()); | 416 ASSERT(!isParsingFragment()); |
| 417 ASSERT(!isWaitingForScripts()); | 417 ASSERT(!isWaitingForScripts()); |
| 418 ASSERT(!isStopped()); | 418 ASSERT(!isStopped()); |
| 419 ASSERT(shouldUseThreading()); | 419 ASSERT(shouldUseThreading()); |
| 420 ASSERT(!m_tokenizer); | 420 ASSERT(!m_tokenizer); |
| 421 ASSERT(!m_token); | 421 ASSERT(!m_token); |
| 422 ASSERT(!m_lastChunkBeforeScript); | 422 ASSERT(!m_lastChunkBeforeScript); |
| 423 | 423 |
| 424 std::unique_ptr<ParsedChunk> chunk(std::move(popChunk)); | 424 std::unique_ptr<ParsedChunk> chunk(std::move(popChunk)); |
| 425 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); | 425 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); |
| 426 size_t elementTokenCount = 0; | 426 size_t elementTokenCount = 0; |
| 427 | 427 |
| 428 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::startedChun kWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); | 428 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::startedChunkW ithCheckpoint, m_backgroundParser, chunk->inputCheckpoint); |
| 429 | 429 |
| 430 for (const auto& xssInfo : chunk->xssInfos) { | 430 for (const auto& xssInfo : chunk->xssInfos) { |
| 431 m_textPosition = xssInfo->m_textPosition; | 431 m_textPosition = xssInfo->m_textPosition; |
| 432 m_xssAuditorDelegate.didBlockScript(*xssInfo); | 432 m_xssAuditorDelegate.didBlockScript(*xssInfo); |
| 433 if (isStopped()) | 433 if (isStopped()) |
| 434 break; | 434 break; |
| 435 } | 435 } |
| 436 // XSSAuditorDelegate can detach the parser if it decides to block the entir e current document. | 436 // XSSAuditorDelegate can detach the parser if it decides to block the entir e current document. |
| 437 if (isDetached()) | 437 if (isDetached()) |
| 438 return elementTokenCount; | 438 return elementTokenCount; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 549 } | 549 } |
| 550 | 550 |
| 551 void HTMLDocumentParser::forcePlaintextForTextDocument() | 551 void HTMLDocumentParser::forcePlaintextForTextDocument() |
| 552 { | 552 { |
| 553 if (shouldUseThreading()) { | 553 if (shouldUseThreading()) { |
| 554 // This method is called before any data is appended, so we have to star t | 554 // This method is called before any data is appended, so we have to star t |
| 555 // the background parser ourselves. | 555 // the background parser ourselves. |
| 556 if (!m_haveBackgroundParser) | 556 if (!m_haveBackgroundParser) |
| 557 startBackgroundParser(); | 557 startBackgroundParser(); |
| 558 | 558 |
| 559 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::forcePl aintextForTextDocument, m_backgroundParser)); | 559 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::forcePlai ntextForTextDocument, m_backgroundParser); |
| 560 } else | 560 } else |
| 561 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); | 561 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); |
| 562 } | 562 } |
| 563 | 563 |
| 564 void HTMLDocumentParser::pumpTokenizer() | 564 void HTMLDocumentParser::pumpTokenizer() |
| 565 { | 565 { |
| 566 ASSERT(!isStopped()); | 566 ASSERT(!isStopped()); |
| 567 ASSERT(m_tokenizer); | 567 ASSERT(m_tokenizer); |
| 568 ASSERT(m_token); | 568 ASSERT(m_token); |
| 569 | 569 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 config->decoder = takeDecoder(); | 725 config->decoder = takeDecoder(); |
| 726 config->parsedChunkQueue = m_parsedChunkQueue.get(); | 726 config->parsedChunkQueue = m_parsedChunkQueue.get(); |
| 727 if (document()->settings()) { | 727 if (document()->settings()) { |
| 728 if (document()->settings()->backgroundHtmlParserOutstandingTokenLimit()) | 728 if (document()->settings()->backgroundHtmlParserOutstandingTokenLimit()) |
| 729 config->outstandingTokenLimit = document()->settings()->backgroundHt mlParserOutstandingTokenLimit(); | 729 config->outstandingTokenLimit = document()->settings()->backgroundHt mlParserOutstandingTokenLimit(); |
| 730 if (document()->settings()->backgroundHtmlParserPendingTokenLimit()) | 730 if (document()->settings()->backgroundHtmlParserPendingTokenLimit()) |
| 731 config->pendingTokenLimit = document()->settings()->backgroundHtmlPa rserPendingTokenLimit(); | 731 config->pendingTokenLimit = document()->settings()->backgroundHtmlPa rserPendingTokenLimit(); |
| 732 } | 732 } |
| 733 | 733 |
| 734 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); | 734 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); |
| 735 postTaskToLookaheadParser(crossThreadBind( | 735 postTaskToLookaheadParser( |
| 736 Synchronous, | |
| 736 &BackgroundHTMLParser::start, | 737 &BackgroundHTMLParser::start, |
| 737 reference.release(), | 738 reference.release(), |
| 738 passed(std::move(config)), | 739 passed(std::move(config)), |
| 739 document()->url(), | 740 document()->url(), |
| 740 passed(CachedDocumentParameters::create(document())), | 741 passed(CachedDocumentParameters::create(document())), |
| 741 MediaValuesCached::MediaValuesCachedData(*document()), | 742 MediaValuesCached::MediaValuesCachedData(*document()), |
| 742 passed(wrapUnique(m_loadingTaskRunner->clone()))), Synchronous); | 743 passed(wrapUnique(m_loadingTaskRunner->clone()))); |
| 743 } | 744 } |
| 744 | 745 |
| 745 void HTMLDocumentParser::stopBackgroundParser() | 746 void HTMLDocumentParser::stopBackgroundParser() |
| 746 { | 747 { |
| 747 ASSERT(shouldUseThreading()); | 748 ASSERT(shouldUseThreading()); |
| 748 ASSERT(m_haveBackgroundParser); | 749 ASSERT(m_haveBackgroundParser); |
| 749 m_haveBackgroundParser = false; | 750 m_haveBackgroundParser = false; |
| 750 | 751 |
| 751 // Make this sync, as lsan triggers on some unittests if the task runner is | 752 // Make this sync, as lsan triggers on some unittests if the task runner is |
| 752 // used. Note that these lifetimes will be much more concrete if | 753 // used. Note that these lifetimes will be much more concrete if |
| 753 // ParseHTMLOnMainThread lands (the lookahead parser will be a member). | 754 // ParseHTMLOnMainThread lands (the lookahead parser will be a member). |
| 754 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::stop, m_bac kgroundParser), Synchronous); | 755 postTaskToLookaheadParser(Synchronous, &BackgroundHTMLParser::stop, m_backgr oundParser); |
| 755 m_weakFactory.revokeAll(); | 756 m_weakFactory.revokeAll(); |
| 756 } | 757 } |
| 757 | 758 |
| 758 void HTMLDocumentParser::append(const String& inputSource) | 759 void HTMLDocumentParser::append(const String& inputSource) |
| 759 { | 760 { |
| 760 if (isStopped()) | 761 if (isStopped()) |
| 761 return; | 762 return; |
| 762 | 763 |
| 763 // We should never reach this point if we're using a parser thread, | 764 // We should never reach this point if we're using a parser thread, |
| 764 // as appendBytes() will directly ship the data to the thread. | 765 // as appendBytes() will directly ship the data to the thread. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 852 flush(); | 853 flush(); |
| 853 if (isDetached()) | 854 if (isDetached()) |
| 854 return; | 855 return; |
| 855 | 856 |
| 856 // Empty documents never got an append() call, and thus have never started | 857 // Empty documents never got an append() call, and thus have never started |
| 857 // a background parser. In those cases, we ignore shouldUseThreading() | 858 // a background parser. In those cases, we ignore shouldUseThreading() |
| 858 // and fall through to the non-threading case. | 859 // and fall through to the non-threading case. |
| 859 if (m_haveBackgroundParser) { | 860 if (m_haveBackgroundParser) { |
| 860 if (!m_input.haveSeenEndOfFile()) | 861 if (!m_input.haveSeenEndOfFile()) |
| 861 m_input.closeWithoutMarkingEndOfFile(); | 862 m_input.closeWithoutMarkingEndOfFile(); |
| 862 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::finish, m_backgroundParser)); | 863 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::finish, m _backgroundParser); |
| 863 return; | 864 return; |
| 864 } | 865 } |
| 865 | 866 |
| 866 if (!m_tokenizer) { | 867 if (!m_tokenizer) { |
| 867 ASSERT(!m_token); | 868 ASSERT(!m_token); |
| 868 // We're finishing before receiving any data. Rather than booting up | 869 // We're finishing before receiving any data. Rather than booting up |
| 869 // the background parser just to spin it down, we finish parsing | 870 // the background parser just to spin it down, we finish parsing |
| 870 // synchronously. | 871 // synchronously. |
| 871 m_token = wrapUnique(new HTMLToken); | 872 m_token = wrapUnique(new HTMLToken); |
| 872 m_tokenizer = HTMLTokenizer::create(m_options); | 873 m_tokenizer = HTMLTokenizer::create(m_options); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1018 | 1019 |
| 1019 if (shouldUseThreading()) { | 1020 if (shouldUseThreading()) { |
| 1020 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); | 1021 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); |
| 1021 if (!m_haveBackgroundParser) | 1022 if (!m_haveBackgroundParser) |
| 1022 startBackgroundParser(); | 1023 startBackgroundParser(); |
| 1023 | 1024 |
| 1024 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(lengt h)); | 1025 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(lengt h)); |
| 1025 memcpy(buffer->data(), data, length); | 1026 memcpy(buffer->data(), data, length); |
| 1026 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentPars er::appendBytes", "size", (unsigned)length); | 1027 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentPars er::appendBytes", "size", (unsigned)length); |
| 1027 | 1028 |
| 1028 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::appendR awBytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesRecei vedTime)); | 1029 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::appendRaw BytesFromMainThread, m_backgroundParser, passed(std::move(buffer)), bytesReceive dTime); |
| 1029 return; | 1030 return; |
| 1030 } | 1031 } |
| 1031 | 1032 |
| 1032 DecodedDataDocumentParser::appendBytes(data, length); | 1033 DecodedDataDocumentParser::appendBytes(data, length); |
| 1033 } | 1034 } |
| 1034 | 1035 |
| 1035 void HTMLDocumentParser::flush() | 1036 void HTMLDocumentParser::flush() |
| 1036 { | 1037 { |
| 1037 // If we've got no decoder, we never received any data. | 1038 // If we've got no decoder, we never received any data. |
| 1038 if (isDetached() || needsDecoder()) | 1039 if (isDetached() || needsDecoder()) |
| 1039 return; | 1040 return; |
| 1040 | 1041 |
| 1041 if (shouldUseThreading()) { | 1042 if (shouldUseThreading()) { |
| 1042 // In some cases, flush() is called without any invocation of | 1043 // In some cases, flush() is called without any invocation of |
| 1043 // appendBytes. Fallback to synchronous parsing in that case. | 1044 // appendBytes. Fallback to synchronous parsing in that case. |
| 1044 if (!m_haveBackgroundParser) { | 1045 if (!m_haveBackgroundParser) { |
| 1045 m_shouldUseThreading = false; | 1046 m_shouldUseThreading = false; |
| 1046 m_token = wrapUnique(new HTMLToken); | 1047 m_token = wrapUnique(new HTMLToken); |
| 1047 m_tokenizer = HTMLTokenizer::create(m_options); | 1048 m_tokenizer = HTMLTokenizer::create(m_options); |
| 1048 DecodedDataDocumentParser::flush(); | 1049 DecodedDataDocumentParser::flush(); |
| 1049 return; | 1050 return; |
| 1050 } | 1051 } |
| 1051 | 1052 |
| 1052 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::flush, m_backgroundParser)); | 1053 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::flush, m_ backgroundParser); |
| 1053 } else { | 1054 } else { |
| 1054 DecodedDataDocumentParser::flush(); | 1055 DecodedDataDocumentParser::flush(); |
| 1055 } | 1056 } |
| 1056 } | 1057 } |
| 1057 | 1058 |
| 1058 void HTMLDocumentParser::setDecoder(std::unique_ptr<TextResourceDecoder> decoder ) | 1059 void HTMLDocumentParser::setDecoder(std::unique_ptr<TextResourceDecoder> decoder ) |
| 1059 { | 1060 { |
| 1060 ASSERT(decoder); | 1061 ASSERT(decoder); |
| 1061 DecodedDataDocumentParser::setDecoder(std::move(decoder)); | 1062 DecodedDataDocumentParser::setDecoder(std::move(decoder)); |
| 1062 | 1063 |
| 1063 if (m_haveBackgroundParser) | 1064 if (m_haveBackgroundParser) |
| 1064 postTaskToLookaheadParser(crossThreadBind(&BackgroundHTMLParser::setDeco der, m_backgroundParser, passed(takeDecoder()))); | 1065 postTaskToLookaheadParser(Asynchronous, &BackgroundHTMLParser::setDecode r, m_backgroundParser, passed(takeDecoder())); |
| 1065 } | 1066 } |
| 1066 | 1067 |
| 1067 void HTMLDocumentParser::documentElementAvailable() | 1068 void HTMLDocumentParser::documentElementAvailable() |
| 1068 { | 1069 { |
| 1069 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable") ; | 1070 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable") ; |
| 1070 DCHECK(document()->documentElement()); | 1071 DCHECK(document()->documentElement()); |
| 1071 for (const String& scriptSource : m_queuedDocumentWriteScripts) { | 1072 for (const String& scriptSource : m_queuedDocumentWriteScripts) { |
| 1072 evaluateAndPreloadScriptForDocumentWrite(scriptSource); | 1073 evaluateAndPreloadScriptForDocumentWrite(scriptSource); |
| 1073 } | 1074 } |
| 1074 | 1075 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1118 | 1119 |
| 1119 if (numPreloads) { | 1120 if (numPreloads) { |
| 1120 DEFINE_STATIC_LOCAL(CustomCountHistogram, successHistogram, ("PreloadSca nner.DocumentWrite.ExecutionTime.Success", 1, 10000, 50)); | 1121 DEFINE_STATIC_LOCAL(CustomCountHistogram, successHistogram, ("PreloadSca nner.DocumentWrite.ExecutionTime.Success", 1, 10000, 50)); |
| 1121 successHistogram.count(duration); | 1122 successHistogram.count(duration); |
| 1122 } else { | 1123 } else { |
| 1123 DEFINE_STATIC_LOCAL(CustomCountHistogram, failureHistogram, ("PreloadSca nner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); | 1124 DEFINE_STATIC_LOCAL(CustomCountHistogram, failureHistogram, ("PreloadSca nner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); |
| 1124 failureHistogram.count(duration); | 1125 failureHistogram.count(duration); |
| 1125 } | 1126 } |
| 1126 } | 1127 } |
| 1127 | 1128 |
| 1128 void HTMLDocumentParser::postTaskToLookaheadParser(std::unique_ptr<CrossThreadCl osure> closure, LookaheadParserTaskSynchrony synchronyPolicy) | 1129 template <typename FunctionType, typename... Ps> |
| 1130 void HTMLDocumentParser::postTaskToLookaheadParser(LookaheadParserTaskSynchrony synchronyPolicy, FunctionType function, Ps&&... parameters) | |
| 1129 { | 1131 { |
| 1130 if (!RuntimeEnabledFeatures::parseHTMLOnMainThreadEnabled()) { | 1132 if (!RuntimeEnabledFeatures::parseHTMLOnMainThreadEnabled()) { |
| 1131 HTMLParserThread::shared()->postTask(std::move(closure)); | 1133 HTMLParserThread::shared()->postTask(crossThreadBind(function, std::forw ard<Ps>(parameters)...)); |
| 1132 return; | 1134 return; |
| 1133 } | 1135 } |
| 1134 | 1136 |
| 1135 // Some messages to the lookahead parser should be synchronous. Otherwise, | 1137 // Some messages to the lookahead parser should be synchronous. Otherwise, |
| 1136 // just post to the loading task runner. | 1138 // just post to the loading task runner. |
| 1137 switch (synchronyPolicy) { | 1139 switch (synchronyPolicy) { |
| 1138 case Synchronous: | 1140 case Synchronous: |
| 1139 (*closure)(); | 1141 (*WTF::bind(function, std::forward<Ps>(parameters)...))(); |
|
hiroshige
2016/07/12 05:33:12
Is this statement covered by tests?
Charlie Harrison
2016/07/12 12:18:36
Yes, ditto.
| |
| 1140 return; | 1142 return; |
| 1141 case Asynchronous: | 1143 case Asynchronous: |
| 1142 m_loadingTaskRunner->postTask(BLINK_FROM_HERE, std::move(closure)); | 1144 m_loadingTaskRunner->postTask(BLINK_FROM_HERE, WTF::bind(function, std:: forward<Ps>(parameters)...)); |
| 1143 return; | 1145 return; |
| 1144 } | 1146 } |
| 1145 NOTREACHED(); | 1147 NOTREACHED(); |
| 1146 } | 1148 } |
| 1147 | 1149 |
| 1148 } // namespace blink | 1150 } // namespace blink |
| OLD | NEW |