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