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 |