| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2013 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 |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``AS IS'' AND ANY |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "core/html/parser/BackgroundHTMLParser.h" | 26 #include "core/html/parser/BackgroundHTMLParser.h" |
| 27 | 27 |
| 28 #include "core/HTMLNames.h" | 28 #include "core/HTMLNames.h" |
| 29 #include "core/dom/Document.h" |
| 30 #include "core/dom/TaskRunnerHelper.h" |
| 29 #include "core/html/parser/HTMLDocumentParser.h" | 31 #include "core/html/parser/HTMLDocumentParser.h" |
| 30 #include "core/html/parser/TextResourceDecoder.h" | 32 #include "core/html/parser/TextResourceDecoder.h" |
| 33 #include "core/html/parser/TokenizedChunkQueue.h" |
| 31 #include "core/html/parser/XSSAuditor.h" | 34 #include "core/html/parser/XSSAuditor.h" |
| 32 #include "platform/CrossThreadFunctional.h" | 35 #include "platform/CrossThreadFunctional.h" |
| 33 #include "platform/Histogram.h" | 36 #include "platform/Histogram.h" |
| 34 #include "platform/WebTaskRunner.h" | 37 #include "platform/WebTaskRunner.h" |
| 35 #include "platform/instrumentation/tracing/TraceEvent.h" | 38 #include "platform/instrumentation/tracing/TraceEvent.h" |
| 36 #include "public/platform/Platform.h" | 39 #include "public/platform/Platform.h" |
| 37 #include "wtf/CurrentTime.h" | 40 #include "wtf/CurrentTime.h" |
| 38 #include "wtf/Functional.h" | 41 #include "wtf/Functional.h" |
| 39 #include "wtf/PtrUtil.h" | 42 #include "wtf/PtrUtil.h" |
| 40 #include "wtf/text/TextPosition.h" | 43 #include "wtf/text/TextPosition.h" |
| 41 #include <memory> | |
| 42 | 44 |
| 43 namespace blink { | 45 namespace blink { |
| 44 | 46 |
| 45 // On a network with high latency and high bandwidth, using a device with a fast | 47 // On a network with high latency and high bandwidth, using a device with a fast |
| 46 // CPU, we could end up speculatively tokenizing the whole document, well ahead | 48 // CPU, we could end up speculatively tokenizing the whole document, well ahead |
| 47 // of when the main-thread actually needs it. This is a waste of memory (and | 49 // of when the main-thread actually needs it. This is a waste of memory (and |
| 48 // potentially time if the speculation fails). So we limit our outstanding | 50 // potentially time if the speculation fails). So we limit our outstanding |
| 49 // tokens arbitrarily to 10,000. Our maximal memory spent speculating will be | 51 // tokens arbitrarily to 10,000. Our maximal memory spent speculating will be |
| 50 // approximately: | 52 // approximately: |
| 51 // (defaultOutstandingTokenLimit + defaultPendingTokenLimit) * | 53 // (defaultOutstandingTokenLimit + defaultPendingTokenLimit) * |
| (...skipping 27 matching lines...) Expand all Loading... |
| 79 } | 81 } |
| 80 | 82 |
| 81 static void checkThatXSSInfosAreSafeToSendToAnotherThread( | 83 static void checkThatXSSInfosAreSafeToSendToAnotherThread( |
| 82 const XSSInfoStream& infos) { | 84 const XSSInfoStream& infos) { |
| 83 for (size_t i = 0; i < infos.size(); ++i) | 85 for (size_t i = 0; i < infos.size(); ++i) |
| 84 ASSERT(infos[i]->isSafeToSendToAnotherThread()); | 86 ASSERT(infos[i]->isSafeToSendToAnotherThread()); |
| 85 } | 87 } |
| 86 | 88 |
| 87 #endif | 89 #endif |
| 88 | 90 |
| 89 WeakPtr<BackgroundHTMLParser> BackgroundHTMLParser::create( | 91 BackgroundHTMLParser* BackgroundHTMLParser::create( |
| 90 std::unique_ptr<Configuration> config, | 92 HTMLDocumentParser* parser, |
| 91 RefPtr<WebTaskRunner> loadingTaskRunner) { | 93 Document& document, |
| 92 auto* backgroundParser = | 94 std::unique_ptr<Configuration> config) { |
| 93 new BackgroundHTMLParser(std::move(config), std::move(loadingTaskRunner)); | 95 return new BackgroundHTMLParser( |
| 94 return backgroundParser->m_weakFactory.createWeakPtr(); | 96 parser, std::move(config), |
| 97 TaskRunnerHelper::get(TaskType::Networking, &document), |
| 98 WTF::makeUnique<TokenPreloadScanner>( |
| 99 document.url(), CachedDocumentParameters::create(&document), |
| 100 MediaValuesCached::MediaValuesCachedData(document))); |
| 95 } | 101 } |
| 96 | 102 |
| 97 void BackgroundHTMLParser::init( | 103 DEFINE_TRACE(BackgroundHTMLParser) { |
| 98 const KURL& documentURL, | 104 visitor->trace(m_parser); |
| 99 std::unique_ptr<CachedDocumentParameters> cachedDocumentParameters, | |
| 100 const MediaValuesCached::MediaValuesCachedData& mediaValuesCachedData) { | |
| 101 m_preloadScanner.reset(new TokenPreloadScanner( | |
| 102 documentURL, std::move(cachedDocumentParameters), mediaValuesCachedData)); | |
| 103 } | 105 } |
| 104 | 106 |
| 105 BackgroundHTMLParser::Configuration::Configuration() | 107 BackgroundHTMLParser::Configuration::Configuration() |
| 106 : outstandingTokenLimit(defaultOutstandingTokenLimit), | 108 : outstandingTokenLimit(defaultOutstandingTokenLimit), |
| 107 pendingTokenLimit(defaultPendingTokenLimit), | 109 pendingTokenLimit(defaultPendingTokenLimit), |
| 108 shouldCoalesceChunks(false) {} | 110 shouldCoalesceChunks(false) {} |
| 109 | 111 |
| 110 BackgroundHTMLParser::BackgroundHTMLParser( | 112 BackgroundHTMLParser::BackgroundHTMLParser( |
| 113 HTMLDocumentParser* parser, |
| 111 std::unique_ptr<Configuration> config, | 114 std::unique_ptr<Configuration> config, |
| 112 RefPtr<WebTaskRunner> loadingTaskRunner) | 115 RefPtr<WebTaskRunner> loadingTaskRunner, |
| 113 : m_weakFactory(this), | 116 std::unique_ptr<TokenPreloadScanner> scanner) |
| 114 m_token(WTF::wrapUnique(new HTMLToken)), | 117 : m_token(WTF::wrapUnique(new HTMLToken)), |
| 115 m_tokenizer(HTMLTokenizer::create(config->options)), | 118 m_tokenizer(HTMLTokenizer::create(config->options)), |
| 116 m_treeBuilderSimulator(config->options), | 119 m_treeBuilderSimulator(config->options), |
| 117 m_options(config->options), | 120 m_options(config->options), |
| 118 m_outstandingTokenLimit(config->outstandingTokenLimit), | 121 m_outstandingTokenLimit(config->outstandingTokenLimit), |
| 119 m_parser(config->parser), | 122 m_parser(parser), |
| 120 m_pendingTokens(WTF::wrapUnique(new CompactHTMLTokenStream)), | 123 m_pendingTokens(WTF::wrapUnique(new CompactHTMLTokenStream)), |
| 121 m_pendingTokenLimit(config->pendingTokenLimit), | 124 m_pendingTokenLimit(config->pendingTokenLimit), |
| 122 m_xssAuditor(std::move(config->xssAuditor)), | 125 m_xssAuditor(std::move(config->xssAuditor)), |
| 126 m_preloadScanner(std::move(scanner)), |
| 123 m_decoder(std::move(config->decoder)), | 127 m_decoder(std::move(config->decoder)), |
| 124 m_loadingTaskRunner(std::move(loadingTaskRunner)), | 128 m_loadingTaskRunner(std::move(loadingTaskRunner)), |
| 125 m_tokenizedChunkQueue(std::move(config->tokenizedChunkQueue)), | |
| 126 m_pendingCSPMetaTokenIndex( | 129 m_pendingCSPMetaTokenIndex( |
| 127 HTMLDocumentParser::TokenizedChunk::noPendingToken), | 130 HTMLDocumentParser::TokenizedChunk::noPendingToken), |
| 128 m_startingScript(false), | 131 m_startingScript(false), |
| 129 m_lastBytesReceivedTime(0.0), | 132 m_lastBytesReceivedTime(0.0), |
| 130 m_shouldCoalesceChunks(config->shouldCoalesceChunks) { | 133 m_shouldCoalesceChunks(config->shouldCoalesceChunks) { |
| 131 ASSERT(m_outstandingTokenLimit > 0); | 134 ASSERT(m_outstandingTokenLimit > 0); |
| 132 ASSERT(m_pendingTokenLimit > 0); | 135 ASSERT(m_pendingTokenLimit > 0); |
| 133 ASSERT(m_outstandingTokenLimit >= m_pendingTokenLimit); | 136 ASSERT(m_outstandingTokenLimit >= m_pendingTokenLimit); |
| 134 } | 137 } |
| 135 | 138 |
| 136 BackgroundHTMLParser::~BackgroundHTMLParser() {} | 139 BackgroundHTMLParser::~BackgroundHTMLParser() {} |
| 137 | 140 |
| 138 void BackgroundHTMLParser::appendRawBytesFromMainThread( | 141 void BackgroundHTMLParser::appendRawBytesFromMainThread( |
| 139 std::unique_ptr<Vector<char>> buffer, | 142 std::unique_ptr<Vector<char>> buffer, |
| 140 double bytesReceivedTime) { | 143 double bytesReceivedTime) { |
| 141 ASSERT(m_decoder); | 144 ASSERT(m_decoder); |
| 142 m_lastBytesReceivedTime = bytesReceivedTime; | 145 m_lastBytesReceivedTime = bytesReceivedTime; |
| 143 DEFINE_STATIC_LOCAL(CustomCountHistogram, queueDelay, | 146 DEFINE_STATIC_LOCAL(CustomCountHistogram, queueDelay, |
| 144 ("Parser.AppendBytesDelay", 1, 5000, 50)); | 147 ("Parser.AppendBytesDelay", 1, 5000, 50)); |
| 145 queueDelay.count(monotonicallyIncreasingTimeMS() - bytesReceivedTime); | 148 queueDelay.count(monotonicallyIncreasingTimeMS() - bytesReceivedTime); |
| 146 updateDocument(m_decoder->decode(buffer->data(), buffer->size())); | 149 m_loadingTaskRunner->postTask( |
| 150 BLINK_FROM_HERE, |
| 151 WTF::bind(&BackgroundHTMLParser::updateDocument, wrapPersistent(this), |
| 152 m_decoder->decode(buffer->data(), buffer->size()))); |
| 147 } | 153 } |
| 148 | 154 |
| 149 void BackgroundHTMLParser::appendDecodedBytes(const String& input) { | 155 void BackgroundHTMLParser::appendDecodedBytes(const String& input) { |
| 150 ASSERT(!m_input.current().isClosed()); | 156 ASSERT(!m_input.current().isClosed()); |
| 151 m_input.append(input); | 157 m_input.append(input); |
| 152 pumpTokenizer(); | 158 pumpTokenizer(); |
| 153 } | 159 } |
| 154 | 160 |
| 155 void BackgroundHTMLParser::setDecoder( | 161 void BackgroundHTMLParser::setDecoder( |
| 156 std::unique_ptr<TextResourceDecoder> decoder) { | 162 std::unique_ptr<TextResourceDecoder> decoder) { |
| 157 ASSERT(decoder); | 163 ASSERT(decoder); |
| 158 m_decoder = std::move(decoder); | 164 m_decoder = std::move(decoder); |
| 159 } | 165 } |
| 160 | 166 |
| 161 void BackgroundHTMLParser::flush() { | 167 void BackgroundHTMLParser::flush() { |
| 162 ASSERT(m_decoder); | 168 ASSERT(m_decoder); |
| 163 updateDocument(m_decoder->flush()); | 169 m_loadingTaskRunner->postTask( |
| 170 BLINK_FROM_HERE, WTF::bind(&BackgroundHTMLParser::updateDocument, |
| 171 wrapPersistent(this), m_decoder->flush())); |
| 164 } | 172 } |
| 165 | 173 |
| 166 void BackgroundHTMLParser::updateDocument(const String& decodedData) { | 174 void BackgroundHTMLParser::updateDocument(const String& decodedData) { |
| 167 DocumentEncodingData encodingData(*m_decoder.get()); | 175 DocumentEncodingData encodingData(*m_decoder.get()); |
| 168 | 176 |
| 169 if (encodingData != m_lastSeenEncodingData) { | 177 if (encodingData != m_lastSeenEncodingData) { |
| 170 m_lastSeenEncodingData = encodingData; | 178 m_lastSeenEncodingData = encodingData; |
| 171 | 179 |
| 172 m_xssAuditor->setEncoding(encodingData.encoding()); | 180 m_xssAuditor->setEncoding(encodingData.encoding()); |
| 173 runOnMainThread( | 181 m_parser->didReceiveEncodingDataFromBackgroundParser(encodingData); |
| 174 &HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser, | |
| 175 m_parser, encodingData); | |
| 176 } | 182 } |
| 177 | 183 |
| 178 if (decodedData.isEmpty()) | 184 if (decodedData.isEmpty()) |
| 179 return; | 185 return; |
| 180 | 186 |
| 181 appendDecodedBytes(decodedData); | 187 appendDecodedBytes(decodedData); |
| 182 } | 188 } |
| 183 | 189 |
| 184 void BackgroundHTMLParser::resumeFrom(std::unique_ptr<Checkpoint> checkpoint) { | 190 void BackgroundHTMLParser::resumeFrom(std::unique_ptr<Checkpoint> checkpoint) { |
| 185 m_parser = checkpoint->parser; | 191 m_loadingTaskRunner->postTask( |
| 192 BLINK_FROM_HERE, |
| 193 WTF::bind(&BackgroundHTMLParser::onResumeFrom, wrapPersistent(this), |
| 194 WTF::passed(std::move(checkpoint)))); |
| 195 } |
| 196 |
| 197 void BackgroundHTMLParser::onResumeFrom( |
| 198 std::unique_ptr<Checkpoint> checkpoint) { |
| 186 m_token = std::move(checkpoint->token); | 199 m_token = std::move(checkpoint->token); |
| 187 m_tokenizer = std::move(checkpoint->tokenizer); | 200 m_tokenizer = std::move(checkpoint->tokenizer); |
| 188 m_treeBuilderSimulator.setState(checkpoint->treeBuilderState); | 201 m_treeBuilderSimulator.setState(checkpoint->treeBuilderState); |
| 189 m_input.rewindTo(checkpoint->inputCheckpoint, checkpoint->unparsedInput); | 202 m_input.rewindTo(checkpoint->inputCheckpoint, checkpoint->unparsedInput); |
| 190 m_preloadScanner->rewindTo(checkpoint->preloadScannerCheckpoint); | 203 m_preloadScanner->rewindTo(checkpoint->preloadScannerCheckpoint); |
| 191 m_startingScript = false; | 204 m_startingScript = false; |
| 192 m_tokenizedChunkQueue->clear(); | 205 m_parser->tokenizedChunkQueue()->clear(); |
| 193 m_lastBytesReceivedTime = monotonicallyIncreasingTimeMS(); | 206 m_lastBytesReceivedTime = monotonicallyIncreasingTimeMS(); |
| 194 pumpTokenizer(); | 207 pumpTokenizer(); |
| 195 } | 208 } |
| 196 | 209 |
| 197 void BackgroundHTMLParser::startedChunkWithCheckpoint( | 210 void BackgroundHTMLParser::startedChunkWithCheckpoint( |
| 198 HTMLInputCheckpoint inputCheckpoint) { | 211 HTMLInputCheckpoint inputCheckpoint) { |
| 199 // Note, we should not have to worry about the index being invalid as messages | 212 // Note, we should not have to worry about the index being invalid as messages |
| 200 // from the main thread will be processed in FIFO order. | 213 // from the main thread will be processed in FIFO order. |
| 201 m_input.invalidateCheckpointsBefore(inputCheckpoint); | 214 m_input.invalidateCheckpointsBefore(inputCheckpoint); |
| 215 m_loadingTaskRunner->postTask( |
| 216 BLINK_FROM_HERE, |
| 217 WTF::bind(&BackgroundHTMLParser::pumpTokenizer, wrapPersistent(this))); |
| 218 } |
| 219 |
| 220 void BackgroundHTMLParser::onFinish() { |
| 221 markEndOfFile(); |
| 202 pumpTokenizer(); | 222 pumpTokenizer(); |
| 203 } | 223 } |
| 204 | 224 |
| 205 void BackgroundHTMLParser::finish() { | 225 void BackgroundHTMLParser::finish() { |
| 206 markEndOfFile(); | 226 m_loadingTaskRunner->postTask( |
| 207 pumpTokenizer(); | 227 BLINK_FROM_HERE, |
| 208 } | 228 WTF::bind(&BackgroundHTMLParser::onFinish, wrapPersistent(this))); |
| 209 | |
| 210 void BackgroundHTMLParser::stop() { | |
| 211 delete this; | |
| 212 } | 229 } |
| 213 | 230 |
| 214 void BackgroundHTMLParser::forcePlaintextForTextDocument() { | 231 void BackgroundHTMLParser::forcePlaintextForTextDocument() { |
| 215 // This is only used by the TextDocumentParser (a subclass of | 232 // This is only used by the TextDocumentParser (a subclass of |
| 216 // HTMLDocumentParser) to force us into the PLAINTEXT state w/o using a | 233 // HTMLDocumentParser) to force us into the PLAINTEXT state w/o using a |
| 217 // <plaintext> tag. The TextDocumentParser uses a <pre> tag for historical / | 234 // <plaintext> tag. The TextDocumentParser uses a <pre> tag for historical / |
| 218 // compatibility reasons. | 235 // compatibility reasons. |
| 219 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); | 236 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); |
| 220 } | 237 } |
| 221 | 238 |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 simulatedToken == HTMLTreeBuilderSimulator::Link || | 312 simulatedToken == HTMLTreeBuilderSimulator::Link || |
| 296 m_pendingTokens->size() >= m_pendingTokenLimit) { | 313 m_pendingTokens->size() >= m_pendingTokenLimit) { |
| 297 shouldNotifyMainThread |= queueChunkForMainThread(); | 314 shouldNotifyMainThread |= queueChunkForMainThread(); |
| 298 // If we're far ahead of the main thread, yield for a bit to avoid | 315 // If we're far ahead of the main thread, yield for a bit to avoid |
| 299 // consuming too much memory. | 316 // consuming too much memory. |
| 300 if (m_input.totalCheckpointTokenCount() > m_outstandingTokenLimit) | 317 if (m_input.totalCheckpointTokenCount() > m_outstandingTokenLimit) |
| 301 break; | 318 break; |
| 302 } | 319 } |
| 303 | 320 |
| 304 if (!m_shouldCoalesceChunks && shouldNotifyMainThread) { | 321 if (!m_shouldCoalesceChunks && shouldNotifyMainThread) { |
| 305 runOnMainThread(&HTMLDocumentParser::notifyPendingTokenizedChunks, | 322 m_parser->notifyPendingTokenizedChunks(); |
| 306 m_parser); | |
| 307 shouldNotifyMainThread = false; | 323 shouldNotifyMainThread = false; |
| 308 } | 324 } |
| 309 } | 325 } |
| 310 // Wait to notify the main thread about the chunks until we're at the limit. | 326 // Wait to notify the main thread about the chunks until we're at the limit. |
| 311 // This lets the background parser generate lots of valuable preloads before | 327 // This lets the background parser generate lots of valuable preloads before |
| 312 // anything expensive (extensions, scripts) take up time on the main thread. A | 328 // anything expensive (extensions, scripts) take up time on the main thread. A |
| 313 // busy main thread can cause preload delays. | 329 // busy main thread can cause preload delays. |
| 314 if (shouldNotifyMainThread) { | 330 if (shouldNotifyMainThread) { |
| 315 runOnMainThread(&HTMLDocumentParser::notifyPendingTokenizedChunks, | 331 m_parser->notifyPendingTokenizedChunks(); |
| 316 m_parser); | |
| 317 } | 332 } |
| 318 } | 333 } |
| 319 | 334 |
| 320 bool BackgroundHTMLParser::queueChunkForMainThread() { | 335 bool BackgroundHTMLParser::queueChunkForMainThread() { |
| 321 if (m_pendingTokens->isEmpty()) | 336 if (m_pendingTokens->isEmpty()) |
| 322 return false; | 337 return false; |
| 323 | 338 |
| 324 #if DCHECK_IS_ON() | 339 #if DCHECK_IS_ON() |
| 325 checkThatTokensAreSafeToSendToAnotherThread(m_pendingTokens.get()); | 340 checkThatTokensAreSafeToSendToAnotherThread(m_pendingTokens.get()); |
| 326 checkThatPreloadsAreSafeToSendToAnotherThread(m_pendingPreloads); | 341 checkThatPreloadsAreSafeToSendToAnotherThread(m_pendingPreloads); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 351 chunk->preloadScannerCheckpoint = m_preloadScanner->createCheckpoint(); | 366 chunk->preloadScannerCheckpoint = m_preloadScanner->createCheckpoint(); |
| 352 chunk->tokens = std::move(m_pendingTokens); | 367 chunk->tokens = std::move(m_pendingTokens); |
| 353 chunk->startingScript = m_startingScript; | 368 chunk->startingScript = m_startingScript; |
| 354 chunk->likelyDocumentWriteScriptIndices.swap( | 369 chunk->likelyDocumentWriteScriptIndices.swap( |
| 355 m_likelyDocumentWriteScriptIndices); | 370 m_likelyDocumentWriteScriptIndices); |
| 356 chunk->pendingCSPMetaTokenIndex = m_pendingCSPMetaTokenIndex; | 371 chunk->pendingCSPMetaTokenIndex = m_pendingCSPMetaTokenIndex; |
| 357 m_startingScript = false; | 372 m_startingScript = false; |
| 358 m_pendingCSPMetaTokenIndex = | 373 m_pendingCSPMetaTokenIndex = |
| 359 HTMLDocumentParser::TokenizedChunk::noPendingToken; | 374 HTMLDocumentParser::TokenizedChunk::noPendingToken; |
| 360 | 375 |
| 361 bool isEmpty = m_tokenizedChunkQueue->enqueue(std::move(chunk)); | 376 bool isEmpty = m_parser->tokenizedChunkQueue()->enqueue(std::move(chunk)); |
| 362 | 377 |
| 363 DEFINE_STATIC_LOCAL(CustomCountHistogram, chunkEnqueueTime, | 378 DEFINE_STATIC_LOCAL(CustomCountHistogram, chunkEnqueueTime, |
| 364 ("Parser.ChunkEnqueueTime", 1, 10000, 50)); | 379 ("Parser.ChunkEnqueueTime", 1, 10000, 50)); |
| 365 chunkEnqueueTime.count(monotonicallyIncreasingTimeMS() - chunkStartTime); | 380 chunkEnqueueTime.count(monotonicallyIncreasingTimeMS() - chunkStartTime); |
| 366 | 381 |
| 367 m_pendingTokens = WTF::wrapUnique(new CompactHTMLTokenStream); | 382 m_pendingTokens = WTF::wrapUnique(new CompactHTMLTokenStream); |
| 368 return isEmpty; | 383 return isEmpty; |
| 369 } | 384 } |
| 370 | 385 |
| 371 // If the background parser is already running on the main thread, then it is | |
| 372 // not necessary to post a task to the main thread to run asynchronously. The | |
| 373 // main parser deals with chunking up its own work. | |
| 374 // TODO(csharrison): This is a pretty big hack because we don't actually need a | |
| 375 // CrossThreadClosure in these cases. This is just experimental. | |
| 376 template <typename FunctionType, typename... Ps> | |
| 377 void BackgroundHTMLParser::runOnMainThread(FunctionType function, | |
| 378 Ps&&... parameters) { | |
| 379 if (isMainThread()) { | |
| 380 (*WTF::bind(function, std::forward<Ps>(parameters)...))(); | |
| 381 } else { | |
| 382 m_loadingTaskRunner->postTask( | |
| 383 BLINK_FROM_HERE, | |
| 384 crossThreadBind(function, std::forward<Ps>(parameters)...)); | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 } // namespace blink | 386 } // namespace blink |
| OLD | NEW |