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 |
| 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 APPLE INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE 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 APPLE INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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/HTMLDocumentParser.h" | 26 #include "core/html/parser/HTMLDocumentParser.h" |
| 27 | 27 |
| 28 #include <memory> | |
| 28 #include "bindings/core/v8/DocumentWriteEvaluator.h" | 29 #include "bindings/core/v8/DocumentWriteEvaluator.h" |
| 29 #include "core/HTMLNames.h" | 30 #include "core/HTMLNames.h" |
| 30 #include "core/css/MediaValuesCached.h" | 31 #include "core/css/MediaValuesCached.h" |
| 31 #include "core/css/resolver/StyleResolver.h" | 32 #include "core/css/resolver/StyleResolver.h" |
| 32 #include "core/dom/DocumentFragment.h" | 33 #include "core/dom/DocumentFragment.h" |
| 33 #include "core/dom/Element.h" | 34 #include "core/dom/Element.h" |
| 34 #include "core/dom/TaskRunnerHelper.h" | 35 #include "core/dom/TaskRunnerHelper.h" |
| 35 #include "core/frame/LocalFrame.h" | 36 #include "core/frame/LocalFrame.h" |
| 36 #include "core/frame/Settings.h" | 37 #include "core/frame/Settings.h" |
| 37 #include "core/html/HTMLDocument.h" | 38 #include "core/html/HTMLDocument.h" |
| 38 #include "core/html/parser/AtomicHTMLToken.h" | 39 #include "core/html/parser/AtomicHTMLToken.h" |
| 39 #include "core/html/parser/BackgroundHTMLParser.h" | 40 #include "core/html/parser/BackgroundHTMLParser.h" |
| 40 #include "core/html/parser/HTMLParserScheduler.h" | 41 #include "core/html/parser/HTMLParserScheduler.h" |
| 41 #include "core/html/parser/HTMLParserScriptRunner.h" | 42 #include "core/html/parser/HTMLParserScriptRunner.h" |
| 42 #include "core/html/parser/HTMLResourcePreloader.h" | 43 #include "core/html/parser/HTMLResourcePreloader.h" |
| 43 #include "core/html/parser/HTMLTreeBuilder.h" | 44 #include "core/html/parser/HTMLTreeBuilder.h" |
| 44 #include "core/inspector/InspectorInstrumentation.h" | 45 #include "core/inspector/InspectorInstrumentation.h" |
| 45 #include "core/inspector/InspectorTraceEvents.h" | 46 #include "core/inspector/InspectorTraceEvents.h" |
| 46 #include "core/loader/DocumentLoader.h" | 47 #include "core/loader/DocumentLoader.h" |
| 47 #include "core/loader/LinkLoader.h" | 48 #include "core/loader/LinkLoader.h" |
| 48 #include "core/loader/NavigationScheduler.h" | 49 #include "core/loader/NavigationScheduler.h" |
| 49 #include "platform/CrossThreadFunctional.h" | 50 #include "platform/CrossThreadFunctional.h" |
| 50 #include "platform/Histogram.h" | 51 #include "platform/Histogram.h" |
| 51 #include "platform/SharedBuffer.h" | 52 #include "platform/SharedBuffer.h" |
| 52 #include "platform/WebFrameScheduler.h" | 53 #include "platform/WebFrameScheduler.h" |
| 53 #include "platform/heap/Handle.h" | 54 #include "platform/heap/Handle.h" |
| 55 #include "platform/heap/Persistent.h" | |
| 54 #include "platform/instrumentation/tracing/TraceEvent.h" | 56 #include "platform/instrumentation/tracing/TraceEvent.h" |
| 55 #include "platform/loader/fetch/ResourceFetcher.h" | 57 #include "platform/loader/fetch/ResourceFetcher.h" |
| 56 #include "public/platform/Platform.h" | 58 #include "public/platform/Platform.h" |
| 57 #include "public/platform/WebLoadingBehaviorFlag.h" | 59 #include "public/platform/WebLoadingBehaviorFlag.h" |
| 58 #include "public/platform/WebScheduler.h" | 60 #include "public/platform/WebScheduler.h" |
| 59 #include "public/platform/WebThread.h" | 61 #include "public/platform/WebThread.h" |
| 60 #include "wtf/AutoReset.h" | 62 #include "wtf/AutoReset.h" |
| 61 #include "wtf/PtrUtil.h" | 63 #include "wtf/PtrUtil.h" |
| 62 #include <memory> | |
| 63 | 64 |
| 64 namespace blink { | 65 namespace blink { |
| 65 | 66 |
| 66 using namespace HTMLNames; | 67 using namespace HTMLNames; |
| 67 | 68 |
| 68 // This is a direct transcription of step 4 from: | 69 // This is a direct transcription of step 4 from: |
| 69 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag ment-case | 70 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag ment-case |
| 70 static HTMLTokenizer::State tokenizerStateForContextElement( | 71 static HTMLTokenizer::State tokenizerStateForContextElement( |
| 71 Element* contextElement, | 72 Element* contextElement, |
| 72 bool reportErrors, | 73 bool reportErrors, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 ParserSynchronizationPolicy syncPolicy) | 125 ParserSynchronizationPolicy syncPolicy) |
| 125 : ScriptableDocumentParser(document, contentPolicy), | 126 : ScriptableDocumentParser(document, contentPolicy), |
| 126 m_options(&document), | 127 m_options(&document), |
| 127 m_reentryPermit(HTMLParserReentryPermit::create()), | 128 m_reentryPermit(HTMLParserReentryPermit::create()), |
| 128 m_token(syncPolicy == ForceSynchronousParsing | 129 m_token(syncPolicy == ForceSynchronousParsing |
| 129 ? WTF::wrapUnique(new HTMLToken) | 130 ? WTF::wrapUnique(new HTMLToken) |
| 130 : nullptr), | 131 : nullptr), |
| 131 m_tokenizer(syncPolicy == ForceSynchronousParsing | 132 m_tokenizer(syncPolicy == ForceSynchronousParsing |
| 132 ? HTMLTokenizer::create(m_options) | 133 ? HTMLTokenizer::create(m_options) |
| 133 : nullptr), | 134 : nullptr), |
| 134 m_loadingTaskRunner( | |
| 135 TaskRunnerHelper::get(TaskType::Networking, &document)), | |
| 136 m_parserScheduler( | 135 m_parserScheduler( |
| 137 syncPolicy == AllowAsynchronousParsing | 136 syncPolicy == AllowAsynchronousParsing |
| 138 ? HTMLParserScheduler::create(this, m_loadingTaskRunner.get()) | 137 ? HTMLParserScheduler::create( |
| 138 this, | |
| 139 TaskRunnerHelper::get(TaskType::Networking, &document)) | |
| 139 : nullptr), | 140 : nullptr), |
| 140 m_xssAuditorDelegate(&document), | 141 m_xssAuditorDelegate(&document), |
| 141 m_weakFactory(this), | |
| 142 m_preloader(HTMLResourcePreloader::create(document)), | 142 m_preloader(HTMLResourcePreloader::create(document)), |
| 143 m_tokenizedChunkQueue(TokenizedChunkQueue::create()), | 143 m_tokenizedChunkQueue(TokenizedChunkQueue::create()), |
| 144 m_evaluator(DocumentWriteEvaluator::create(document)), | 144 m_evaluator(DocumentWriteEvaluator::create(document)), |
| 145 m_pendingCSPMetaToken(nullptr), | 145 m_pendingCSPMetaToken(nullptr), |
| 146 m_shouldUseThreading(syncPolicy == AllowAsynchronousParsing), | 146 m_shouldUseThreading(syncPolicy == AllowAsynchronousParsing), |
| 147 m_endWasDelayed(false), | 147 m_endWasDelayed(false), |
| 148 m_haveBackgroundParser(false), | |
| 149 m_tasksWereSuspended(false), | 148 m_tasksWereSuspended(false), |
| 150 m_pumpSessionNestingLevel(0), | 149 m_pumpSessionNestingLevel(0), |
| 151 m_pumpSpeculationsSessionNestingLevel(0), | 150 m_pumpSpeculationsSessionNestingLevel(0), |
| 152 m_isParsingAtLineNumber(false), | 151 m_isParsingAtLineNumber(false), |
| 153 m_triedLoadingLinkHeaders(false), | 152 m_triedLoadingLinkHeaders(false), |
| 154 m_addedPendingStylesheetInBody(false), | 153 m_addedPendingStylesheetInBody(false), |
| 155 m_isWaitingForStylesheets(false) { | 154 m_isWaitingForStylesheets(false) { |
| 156 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); | 155 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); |
| 157 // Threading is not allowed in prefetch mode. | 156 // Threading is not allowed in prefetch mode. |
| 158 DCHECK(!document.isPrefetchOnly() || !shouldUseThreading()); | 157 DCHECK(!document.isPrefetchOnly() || !shouldUseThreading()); |
| 159 } | 158 } |
| 160 | 159 |
| 161 HTMLDocumentParser::~HTMLDocumentParser() {} | 160 HTMLDocumentParser::~HTMLDocumentParser() {} |
| 162 | 161 |
| 163 void HTMLDocumentParser::dispose() { | |
| 164 // In Oilpan, HTMLDocumentParser can die together with Document, and detach() | |
| 165 // is not called in this case. | |
| 166 if (m_haveBackgroundParser) | |
| 167 stopBackgroundParser(); | |
| 168 } | |
| 169 | |
| 170 DEFINE_TRACE(HTMLDocumentParser) { | 162 DEFINE_TRACE(HTMLDocumentParser) { |
| 171 visitor->trace(m_treeBuilder); | 163 visitor->trace(m_treeBuilder); |
| 172 visitor->trace(m_parserScheduler); | 164 visitor->trace(m_parserScheduler); |
| 173 visitor->trace(m_xssAuditorDelegate); | 165 visitor->trace(m_xssAuditorDelegate); |
| 174 visitor->trace(m_scriptRunner); | 166 visitor->trace(m_scriptRunner); |
| 167 visitor->trace(m_backgroundParser); | |
| 175 visitor->trace(m_preloader); | 168 visitor->trace(m_preloader); |
| 176 ScriptableDocumentParser::trace(visitor); | 169 ScriptableDocumentParser::trace(visitor); |
| 177 HTMLParserScriptRunnerHost::trace(visitor); | 170 HTMLParserScriptRunnerHost::trace(visitor); |
| 178 } | 171 } |
| 179 | 172 |
| 180 void HTMLDocumentParser::detach() { | 173 void HTMLDocumentParser::detach() { |
| 181 if (!isParsingFragment() && m_tokenizedChunkQueue.get() && | 174 if (!isParsingFragment() && m_tokenizedChunkQueue.get() && |
| 182 m_tokenizedChunkQueue->peakPendingChunkCount()) { | 175 m_tokenizedChunkQueue->peakPendingChunkCount()) { |
| 183 DEFINE_STATIC_LOCAL(CustomCountHistogram, peakPendingChunkHistogram, | 176 DEFINE_STATIC_LOCAL(CustomCountHistogram, peakPendingChunkHistogram, |
| 184 ("Parser.PeakPendingChunkCount", 1, 1000, 50)); | 177 ("Parser.PeakPendingChunkCount", 1, 1000, 50)); |
| 185 peakPendingChunkHistogram.count( | 178 peakPendingChunkHistogram.count( |
| 186 m_tokenizedChunkQueue->peakPendingChunkCount()); | 179 m_tokenizedChunkQueue->peakPendingChunkCount()); |
| 187 DEFINE_STATIC_LOCAL(CustomCountHistogram, peakPendingTokenHistogram, | 180 DEFINE_STATIC_LOCAL(CustomCountHistogram, peakPendingTokenHistogram, |
| 188 ("Parser.PeakPendingTokenCount", 1, 100000, 50)); | 181 ("Parser.PeakPendingTokenCount", 1, 100000, 50)); |
| 189 peakPendingTokenHistogram.count( | 182 peakPendingTokenHistogram.count( |
| 190 m_tokenizedChunkQueue->peakPendingTokenCount()); | 183 m_tokenizedChunkQueue->peakPendingTokenCount()); |
| 191 } | 184 } |
| 192 | 185 |
| 193 if (m_haveBackgroundParser) | 186 m_backgroundParser.clear(); |
| 194 stopBackgroundParser(); | |
| 195 DocumentParser::detach(); | 187 DocumentParser::detach(); |
| 196 if (m_scriptRunner) | 188 if (m_scriptRunner) |
| 197 m_scriptRunner->detach(); | 189 m_scriptRunner->detach(); |
| 198 m_treeBuilder->detach(); | 190 m_treeBuilder->detach(); |
| 199 // FIXME: It seems wrong that we would have a preload scanner here. Yet during | 191 // FIXME: It seems wrong that we would have a preload scanner here. Yet during |
| 200 // fast/dom/HTMLScriptElement/script-load-events.html we do. | 192 // fast/dom/HTMLScriptElement/script-load-events.html we do. |
| 201 m_preloadScanner.reset(); | 193 m_preloadScanner.reset(); |
| 202 m_insertionPreloadScanner.reset(); | 194 m_insertionPreloadScanner.reset(); |
| 203 if (m_parserScheduler) { | 195 if (m_parserScheduler) { |
| 204 m_parserScheduler->detach(); | 196 m_parserScheduler->detach(); |
| 205 m_parserScheduler.clear(); | 197 m_parserScheduler.clear(); |
| 206 } | 198 } |
| 207 // Oilpan: It is important to clear m_token to deallocate backing memory of | 199 // Oilpan: It is important to clear m_token to deallocate backing memory of |
| 208 // HTMLToken::m_data and let the allocator reuse the memory for | 200 // HTMLToken::m_data and let the allocator reuse the memory for |
| 209 // HTMLToken::m_data of a next HTMLDocumentParser. We need to clear | 201 // HTMLToken::m_data of a next HTMLDocumentParser. We need to clear |
| 210 // m_tokenizer first because m_tokenizer has a raw pointer to m_token. | 202 // m_tokenizer first because m_tokenizer has a raw pointer to m_token. |
| 211 m_tokenizer.reset(); | 203 m_tokenizer.reset(); |
| 212 m_token.reset(); | 204 m_token.reset(); |
| 213 } | 205 } |
| 214 | 206 |
| 215 void HTMLDocumentParser::stopParsing() { | 207 void HTMLDocumentParser::stopParsing() { |
| 216 DocumentParser::stopParsing(); | 208 DocumentParser::stopParsing(); |
| 217 if (m_parserScheduler) { | 209 if (m_parserScheduler) { |
| 218 m_parserScheduler->detach(); | 210 m_parserScheduler->detach(); |
| 219 m_parserScheduler.clear(); | 211 m_parserScheduler.clear(); |
| 220 } | 212 } |
| 221 if (m_haveBackgroundParser) | 213 m_backgroundParser.clear(); |
| 222 stopBackgroundParser(); | |
| 223 } | 214 } |
| 224 | 215 |
| 225 // This kicks off "Once the user agent stops parsing" as described by: | 216 // This kicks off "Once the user agent stops parsing" as described by: |
| 226 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the- end | 217 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the- end |
| 227 void HTMLDocumentParser::prepareToStopParsing() { | 218 void HTMLDocumentParser::prepareToStopParsing() { |
| 228 // FIXME: It may not be correct to disable this for the background parser. | 219 // FIXME: It may not be correct to disable this for the background parser. |
| 229 // That means hasInsertionPoint() may not be correct in some cases. | 220 // That means hasInsertionPoint() may not be correct in some cases. |
| 230 ASSERT(!hasInsertionPoint() || m_haveBackgroundParser); | 221 ASSERT(!hasInsertionPoint() || m_backgroundParser); |
| 231 | 222 |
| 232 // NOTE: This pump should only ever emit buffered character tokens. | 223 // NOTE: This pump should only ever emit buffered character tokens. |
| 233 if (m_tokenizer) { | 224 if (m_tokenizer) { |
| 234 ASSERT(!m_haveBackgroundParser); | 225 ASSERT(!m_backgroundParser); |
| 235 pumpTokenizerIfPossible(); | 226 pumpTokenizerIfPossible(); |
| 236 } | 227 } |
| 237 | 228 |
| 238 if (isStopped()) | 229 if (isStopped()) |
| 239 return; | 230 return; |
| 240 | 231 |
| 241 DocumentParser::prepareToStopParsing(); | 232 DocumentParser::prepareToStopParsing(); |
| 242 | 233 |
| 243 // We will not have a scriptRunner when parsing a DocumentFragment. | 234 // We will not have a scriptRunner when parsing a DocumentFragment. |
| 244 if (m_scriptRunner) | 235 if (m_scriptRunner) |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 264 pumpTokenizer(); | 255 pumpTokenizer(); |
| 265 } | 256 } |
| 266 | 257 |
| 267 bool HTMLDocumentParser::isScheduledForResume() const { | 258 bool HTMLDocumentParser::isScheduledForResume() const { |
| 268 return m_parserScheduler && m_parserScheduler->isScheduledForResume(); | 259 return m_parserScheduler && m_parserScheduler->isScheduledForResume(); |
| 269 } | 260 } |
| 270 | 261 |
| 271 // Used by HTMLParserScheduler | 262 // Used by HTMLParserScheduler |
| 272 void HTMLDocumentParser::resumeParsingAfterYield() { | 263 void HTMLDocumentParser::resumeParsingAfterYield() { |
| 273 ASSERT(shouldUseThreading()); | 264 ASSERT(shouldUseThreading()); |
| 274 ASSERT(m_haveBackgroundParser); | 265 ASSERT(m_backgroundParser); |
| 275 | 266 |
| 276 checkIfBodyStlyesheetAdded(); | 267 checkIfBodyStlyesheetAdded(); |
| 277 if (isStopped() || isPaused()) | 268 if (isStopped() || isPaused()) |
| 278 return; | 269 return; |
| 279 | 270 |
| 280 pumpPendingSpeculations(); | 271 pumpPendingSpeculations(); |
| 281 } | 272 } |
| 282 | 273 |
| 283 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() { | 274 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() { |
| 284 ASSERT(scriptingContentIsAllowed(getParserContentPolicy())); | 275 ASSERT(scriptingContentIsAllowed(getParserContentPolicy())); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 391 if (!isPaused() && !isScheduledForResume()) { | 382 if (!isPaused() && !isScheduledForResume()) { |
| 392 if (m_tasksWereSuspended) | 383 if (m_tasksWereSuspended) |
| 393 m_parserScheduler->forceResumeAfterYield(); | 384 m_parserScheduler->forceResumeAfterYield(); |
| 394 else | 385 else |
| 395 m_parserScheduler->scheduleForResume(); | 386 m_parserScheduler->scheduleForResume(); |
| 396 } | 387 } |
| 397 } | 388 } |
| 398 | 389 |
| 399 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser( | 390 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser( |
| 400 const DocumentEncodingData& data) { | 391 const DocumentEncodingData& data) { |
| 392 if (!isParsing()) | |
|
Yoav Weiss
2017/02/09 10:39:00
Could you explain why you added that? Is that rela
| |
| 393 return; | |
| 401 document()->setEncodingData(data); | 394 document()->setEncodingData(data); |
| 402 } | 395 } |
| 403 | 396 |
| 404 void HTMLDocumentParser::validateSpeculations( | 397 void HTMLDocumentParser::validateSpeculations( |
| 405 std::unique_ptr<TokenizedChunk> chunk) { | 398 std::unique_ptr<TokenizedChunk> chunk) { |
| 406 ASSERT(chunk); | 399 ASSERT(chunk); |
| 407 // TODO(kouhei): We should simplify codepath here by disallowing | 400 // TODO(kouhei): We should simplify codepath here by disallowing |
| 408 // validateSpeculations | 401 // validateSpeculations |
| 409 // while isPaused, and m_lastChunkBeforePause can simply be | 402 // while isPaused, and m_lastChunkBeforePause can simply be |
| 410 // pushed to m_speculations. | 403 // pushed to m_speculations. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 } | 437 } |
| 445 | 438 |
| 446 discardSpeculationsAndResumeFrom(std::move(chunk), std::move(token), | 439 discardSpeculationsAndResumeFrom(std::move(chunk), std::move(token), |
| 447 std::move(tokenizer)); | 440 std::move(tokenizer)); |
| 448 } | 441 } |
| 449 | 442 |
| 450 void HTMLDocumentParser::discardSpeculationsAndResumeFrom( | 443 void HTMLDocumentParser::discardSpeculationsAndResumeFrom( |
| 451 std::unique_ptr<TokenizedChunk> lastChunkBeforeScript, | 444 std::unique_ptr<TokenizedChunk> lastChunkBeforeScript, |
| 452 std::unique_ptr<HTMLToken> token, | 445 std::unique_ptr<HTMLToken> token, |
| 453 std::unique_ptr<HTMLTokenizer> tokenizer) { | 446 std::unique_ptr<HTMLTokenizer> tokenizer) { |
| 454 m_weakFactory.revokeAll(); | |
| 455 | |
| 456 size_t discardedTokenCount = 0; | 447 size_t discardedTokenCount = 0; |
| 457 for (const auto& speculation : m_speculations) { | 448 for (const auto& speculation : m_speculations) { |
| 458 discardedTokenCount += speculation->tokens->size(); | 449 discardedTokenCount += speculation->tokens->size(); |
| 459 } | 450 } |
| 460 DEFINE_STATIC_LOCAL(CustomCountHistogram, discardedTokenCountHistogram, | 451 DEFINE_STATIC_LOCAL(CustomCountHistogram, discardedTokenCountHistogram, |
| 461 ("Parser.DiscardedTokenCount", 1, 100000, 50)); | 452 ("Parser.DiscardedTokenCount", 1, 100000, 50)); |
| 462 discardedTokenCountHistogram.count(discardedTokenCount); | 453 discardedTokenCountHistogram.count(discardedTokenCount); |
| 463 | 454 |
| 464 m_speculations.clear(); | 455 m_speculations.clear(); |
| 465 m_pendingCSPMetaToken = nullptr; | 456 m_pendingCSPMetaToken = nullptr; |
| 466 m_queuedPreloads.clear(); | 457 m_queuedPreloads.clear(); |
| 467 | 458 |
| 468 std::unique_ptr<BackgroundHTMLParser::Checkpoint> checkpoint = | 459 std::unique_ptr<BackgroundHTMLParser::Checkpoint> checkpoint = |
| 469 WTF::wrapUnique(new BackgroundHTMLParser::Checkpoint); | 460 WTF::wrapUnique(new BackgroundHTMLParser::Checkpoint); |
| 470 checkpoint->parser = m_weakFactory.createWeakPtr(); | |
| 471 checkpoint->token = std::move(token); | 461 checkpoint->token = std::move(token); |
| 472 checkpoint->tokenizer = std::move(tokenizer); | 462 checkpoint->tokenizer = std::move(tokenizer); |
| 473 checkpoint->treeBuilderState = | 463 checkpoint->treeBuilderState = |
| 474 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get()); | 464 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get()); |
| 475 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; | 465 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; |
| 476 checkpoint->preloadScannerCheckpoint = | 466 checkpoint->preloadScannerCheckpoint = |
| 477 lastChunkBeforeScript->preloadScannerCheckpoint; | 467 lastChunkBeforeScript->preloadScannerCheckpoint; |
| 478 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); | 468 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); |
| 479 // FIXME: This should be passed in instead of cleared. | 469 // FIXME: This should be passed in instead of cleared. |
| 480 m_input.current().clear(); | 470 m_input.current().clear(); |
| 481 | 471 |
| 482 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); | 472 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); |
| 483 m_loadingTaskRunner->postTask( | 473 m_backgroundParser->resumeFrom(std::move(checkpoint)); |
| 484 BLINK_FROM_HERE, | |
| 485 WTF::bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, | |
| 486 WTF::passed(std::move(checkpoint)))); | |
| 487 } | 474 } |
| 488 | 475 |
| 489 size_t HTMLDocumentParser::processTokenizedChunkFromBackgroundParser( | 476 size_t HTMLDocumentParser::processTokenizedChunkFromBackgroundParser( |
| 490 std::unique_ptr<TokenizedChunk> popChunk) { | 477 std::unique_ptr<TokenizedChunk> popChunk) { |
| 491 TRACE_EVENT_WITH_FLOW0( | 478 TRACE_EVENT_WITH_FLOW0( |
| 492 "blink,loading", | 479 "blink,loading", |
| 493 "HTMLDocumentParser::processTokenizedChunkFromBackgroundParser", | 480 "HTMLDocumentParser::processTokenizedChunkFromBackgroundParser", |
| 494 popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); | 481 popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); |
| 495 AutoReset<bool> hasLineNumber(&m_isParsingAtLineNumber, true); | 482 AutoReset<bool> hasLineNumber(&m_isParsingAtLineNumber, true); |
| 496 | 483 |
| 497 SECURITY_DCHECK(m_pumpSpeculationsSessionNestingLevel == 1); | 484 SECURITY_DCHECK(m_pumpSpeculationsSessionNestingLevel == 1); |
| 498 SECURITY_DCHECK(!inPumpSession()); | 485 SECURITY_DCHECK(!inPumpSession()); |
| 499 ASSERT(!isParsingFragment()); | 486 ASSERT(!isParsingFragment()); |
| 500 DCHECK(!isPaused()); | 487 DCHECK(!isPaused()); |
| 501 ASSERT(!isStopped()); | 488 ASSERT(!isStopped()); |
| 502 ASSERT(shouldUseThreading()); | 489 ASSERT(shouldUseThreading()); |
| 503 ASSERT(!m_tokenizer); | 490 ASSERT(!m_tokenizer); |
| 504 ASSERT(!m_token); | 491 ASSERT(!m_token); |
| 505 DCHECK(!m_lastChunkBeforePause); | 492 DCHECK(!m_lastChunkBeforePause); |
| 506 | 493 |
| 507 std::unique_ptr<TokenizedChunk> chunk(std::move(popChunk)); | 494 std::unique_ptr<TokenizedChunk> chunk(std::move(popChunk)); |
| 508 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); | 495 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); |
| 509 size_t elementTokenCount = 0; | 496 size_t elementTokenCount = 0; |
| 510 | 497 |
| 511 m_loadingTaskRunner->postTask( | 498 m_backgroundParser->startedChunkWithCheckpoint(chunk->inputCheckpoint); |
| 512 BLINK_FROM_HERE, | |
| 513 WTF::bind(&BackgroundHTMLParser::startedChunkWithCheckpoint, | |
| 514 m_backgroundParser, chunk->inputCheckpoint)); | |
| 515 | 499 |
| 516 for (const auto& xssInfo : chunk->xssInfos) { | 500 for (const auto& xssInfo : chunk->xssInfos) { |
| 517 m_textPosition = xssInfo->m_textPosition; | 501 m_textPosition = xssInfo->m_textPosition; |
| 518 m_xssAuditorDelegate.didBlockScript(*xssInfo); | 502 m_xssAuditorDelegate.didBlockScript(*xssInfo); |
| 519 if (isStopped()) | 503 if (isStopped()) |
| 520 break; | 504 break; |
| 521 } | 505 } |
| 522 // XSSAuditorDelegate can detach the parser if it decides to block the entire | 506 // XSSAuditorDelegate can detach the parser if it decides to block the entire |
| 523 // current document. | 507 // current document. |
| 524 if (isDetached()) | 508 if (isDetached()) |
| 525 return elementTokenCount; | 509 return elementTokenCount; |
| 526 | 510 |
| 527 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); | 511 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); |
| 528 it != tokens->end(); ++it) { | 512 it != tokens->end(); ++it) { |
| 529 ASSERT(!isWaitingForScripts()); | 513 ASSERT(!isWaitingForScripts()); |
| 530 | 514 |
| 531 if (!chunk->startingScript && | 515 if (!chunk->startingScript && |
| 532 (it->type() == HTMLToken::StartTag || it->type() == HTMLToken::EndTag)) | 516 (it->type() == HTMLToken::StartTag || it->type() == HTMLToken::EndTag)) |
| 533 elementTokenCount++; | 517 elementTokenCount++; |
| 534 | 518 |
| 535 if (document()->frame() && | 519 if (document()->frame() && |
| 536 document()->frame()->navigationScheduler().locationChangePending()) { | 520 document()->frame()->navigationScheduler().locationChangePending()) { |
| 537 // To match main-thread parser behavior (which never checks | 521 // To match main-thread parser behavior (which never checks |
| 538 // locationChangePending on the EOF path) we peek to see if this chunk has | 522 // locationChangePending on the EOF path) we peek to see if this chunk has |
| 539 // an EOF and process it anyway. | 523 // an EOF and process it anyway. |
| 540 if (tokens->back().type() == HTMLToken::EndOfFile) { | 524 if (tokens->back().type() == HTMLToken::EndOfFile) { |
| 541 ASSERT( | 525 // There should never be any chunks after the EOF. |
| 542 m_speculations | 526 ASSERT(m_speculations.isEmpty()); |
| 543 .isEmpty()); // There should never be any chunks after the EOF. | |
| 544 prepareToStopParsing(); | 527 prepareToStopParsing(); |
| 545 } | 528 } |
| 546 break; | 529 break; |
| 547 } | 530 } |
| 548 | 531 |
| 549 m_textPosition = it->textPosition(); | 532 m_textPosition = it->textPosition(); |
| 550 | 533 |
| 551 constructTreeFromCompactHTMLToken(*it); | 534 constructTreeFromCompactHTMLToken(*it); |
| 552 | 535 |
| 553 if (isStopped()) | 536 if (isStopped()) |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 647 InspectorParseHtmlEvent::endData(lineNumber().zeroBasedInt() - 1)); | 630 InspectorParseHtmlEvent::endData(lineNumber().zeroBasedInt() - 1)); |
| 648 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), | 631 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), |
| 649 "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", | 632 "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", |
| 650 InspectorUpdateCountersEvent::data()); | 633 InspectorUpdateCountersEvent::data()); |
| 651 } | 634 } |
| 652 | 635 |
| 653 void HTMLDocumentParser::forcePlaintextForTextDocument() { | 636 void HTMLDocumentParser::forcePlaintextForTextDocument() { |
| 654 if (shouldUseThreading()) { | 637 if (shouldUseThreading()) { |
| 655 // This method is called before any data is appended, so we have to start | 638 // This method is called before any data is appended, so we have to start |
| 656 // the background parser ourselves. | 639 // the background parser ourselves. |
| 657 if (!m_haveBackgroundParser) | 640 if (!m_backgroundParser) |
| 658 startBackgroundParser(); | 641 startBackgroundParser(); |
| 659 | 642 |
| 660 // This task should be synchronous, because otherwise synchronous | 643 // This task should be synchronous, because otherwise synchronous |
| 661 // tokenizing can happen before plaintext is forced. | 644 // tokenizing can happen before plaintext is forced. |
| 662 m_backgroundParser->forcePlaintextForTextDocument(); | 645 m_backgroundParser->forcePlaintextForTextDocument(); |
| 663 } else | 646 } else |
| 664 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); | 647 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); |
| 665 } | 648 } |
| 666 | 649 |
| 667 void HTMLDocumentParser::pumpTokenizer() { | 650 void HTMLDocumentParser::pumpTokenizer() { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 | 770 |
| 788 void HTMLDocumentParser::insert(const SegmentedString& source) { | 771 void HTMLDocumentParser::insert(const SegmentedString& source) { |
| 789 if (isStopped()) | 772 if (isStopped()) |
| 790 return; | 773 return; |
| 791 | 774 |
| 792 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", | 775 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", |
| 793 source.length()); | 776 source.length()); |
| 794 | 777 |
| 795 if (!m_tokenizer) { | 778 if (!m_tokenizer) { |
| 796 ASSERT(!inPumpSession()); | 779 ASSERT(!inPumpSession()); |
| 797 ASSERT(m_haveBackgroundParser || wasCreatedByScript()); | 780 ASSERT(m_backgroundParser || wasCreatedByScript()); |
| 798 m_token = WTF::wrapUnique(new HTMLToken); | 781 m_token = WTF::wrapUnique(new HTMLToken); |
| 799 m_tokenizer = HTMLTokenizer::create(m_options); | 782 m_tokenizer = HTMLTokenizer::create(m_options); |
| 800 } | 783 } |
| 801 | 784 |
| 802 SegmentedString excludedLineNumberSource(source); | 785 SegmentedString excludedLineNumberSource(source); |
| 803 excludedLineNumberSource.setExcludeLineNumbers(); | 786 excludedLineNumberSource.setExcludeLineNumbers(); |
| 804 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); | 787 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); |
| 805 pumpTokenizerIfPossible(); | 788 pumpTokenizerIfPossible(); |
| 806 | 789 |
| 807 if (isPaused()) { | 790 if (isPaused()) { |
| 808 // Check the document.write() output with a separate preload scanner as | 791 // Check the document.write() output with a separate preload scanner as |
| 809 // the main scanner can't deal with insertions. | 792 // the main scanner can't deal with insertions. |
| 810 if (!m_insertionPreloadScanner) | 793 if (!m_insertionPreloadScanner) |
| 811 m_insertionPreloadScanner = createPreloadScanner(); | 794 m_insertionPreloadScanner = createPreloadScanner(); |
| 812 m_insertionPreloadScanner->appendToEnd(source); | 795 m_insertionPreloadScanner->appendToEnd(source); |
| 813 scanAndPreload(m_insertionPreloadScanner.get()); | 796 scanAndPreload(m_insertionPreloadScanner.get()); |
| 814 } | 797 } |
| 815 | 798 |
| 816 endIfDelayed(); | 799 endIfDelayed(); |
| 817 } | 800 } |
| 818 | 801 |
| 819 void HTMLDocumentParser::startBackgroundParser() { | 802 void HTMLDocumentParser::startBackgroundParser() { |
| 820 ASSERT(!isStopped()); | 803 ASSERT(!isStopped()); |
| 821 ASSERT(shouldUseThreading()); | 804 ASSERT(shouldUseThreading()); |
| 822 ASSERT(!m_haveBackgroundParser); | 805 ASSERT(!m_backgroundParser); |
| 823 ASSERT(document()); | 806 ASSERT(document()); |
| 824 m_haveBackgroundParser = true; | |
| 825 | 807 |
| 826 // TODO(alexclarke): Remove WebFrameScheduler::setDocumentParsingInBackground | 808 // TODO(csharrison): Remove WebFrameScheduler::setDocumentParsingInBackground. |
| 827 // when background parser goes away. | |
| 828 if (document()->frame() && document()->frame()->frameScheduler()) | 809 if (document()->frame() && document()->frame()->frameScheduler()) |
| 829 document()->frame()->frameScheduler()->setDocumentParsingInBackground(true); | 810 document()->frame()->frameScheduler()->setDocumentParsingInBackground(true); |
| 830 | 811 |
| 831 // Make sure that a resolver is set up, so that the correct viewport | 812 // Make sure that a resolver is set up, so that the correct viewport |
| 832 // dimensions will be fed to the background parser and preload scanner. | 813 // dimensions will be fed to the background parser and preload scanner. |
| 833 if (document()->loader()) | 814 if (document()->loader()) |
| 834 document()->ensureStyleResolver(); | 815 document()->ensureStyleResolver(); |
| 835 | 816 |
| 836 std::unique_ptr<BackgroundHTMLParser::Configuration> config = | 817 std::unique_ptr<BackgroundHTMLParser::Configuration> config = |
| 837 WTF::wrapUnique(new BackgroundHTMLParser::Configuration); | 818 WTF::wrapUnique(new BackgroundHTMLParser::Configuration); |
| 838 config->options = m_options; | 819 config->options = m_options; |
| 839 config->parser = m_weakFactory.createWeakPtr(); | |
| 840 config->xssAuditor = WTF::wrapUnique(new XSSAuditor); | 820 config->xssAuditor = WTF::wrapUnique(new XSSAuditor); |
| 841 config->xssAuditor->init(document(), &m_xssAuditorDelegate); | 821 config->xssAuditor->init(document(), &m_xssAuditorDelegate); |
| 842 | 822 |
| 843 config->decoder = takeDecoder(); | 823 config->decoder = takeDecoder(); |
| 844 config->tokenizedChunkQueue = m_tokenizedChunkQueue.get(); | 824 config->tokenizedChunkQueue = m_tokenizedChunkQueue.get(); |
| 845 if (document()->settings()) { | 825 if (document()->settings()) { |
| 846 if (document() | 826 if (document() |
| 847 ->settings() | 827 ->settings() |
| 848 ->getBackgroundHtmlParserOutstandingTokenLimit()) { | 828 ->getBackgroundHtmlParserOutstandingTokenLimit()) { |
| 849 config->outstandingTokenLimit = | 829 config->outstandingTokenLimit = |
| 850 document() | 830 document() |
| 851 ->settings() | 831 ->settings() |
| 852 ->getBackgroundHtmlParserOutstandingTokenLimit(); | 832 ->getBackgroundHtmlParserOutstandingTokenLimit(); |
| 853 } | 833 } |
| 854 if (document()->settings()->getBackgroundHtmlParserPendingTokenLimit()) { | 834 if (document()->settings()->getBackgroundHtmlParserPendingTokenLimit()) { |
| 855 config->pendingTokenLimit = | 835 config->pendingTokenLimit = |
| 856 document()->settings()->getBackgroundHtmlParserPendingTokenLimit(); | 836 document()->settings()->getBackgroundHtmlParserPendingTokenLimit(); |
| 857 } | 837 } |
| 858 } | 838 } |
| 859 | 839 |
| 860 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); | 840 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); |
| 861 | 841 |
| 862 // The background parser is created on the main thread, but may otherwise | |
| 863 // only be used from the parser thread. | |
| 864 m_backgroundParser = | 842 m_backgroundParser = |
| 865 BackgroundHTMLParser::create(std::move(config), m_loadingTaskRunner); | 843 BackgroundHTMLParser::create(this, *document(), std::move(config)); |
| 866 // TODO(csharrison): This is a hack to initialize MediaValuesCached on the | |
| 867 // correct thread. We should get rid of it. | |
| 868 m_backgroundParser->init( | |
| 869 document()->url(), CachedDocumentParameters::create(document()), | |
| 870 MediaValuesCached::MediaValuesCachedData(*document())); | |
| 871 } | |
| 872 | |
| 873 void HTMLDocumentParser::stopBackgroundParser() { | |
| 874 ASSERT(shouldUseThreading()); | |
| 875 ASSERT(m_haveBackgroundParser); | |
| 876 | |
| 877 if (m_haveBackgroundParser && document()->frame() && | |
| 878 document()->frame()->frameScheduler()) | |
| 879 document()->frame()->frameScheduler()->setDocumentParsingInBackground( | |
| 880 false); | |
| 881 | |
| 882 m_haveBackgroundParser = false; | |
| 883 | |
| 884 // Make this sync, as lsan triggers on some unittests if the task runner is | |
| 885 // used. | |
| 886 m_backgroundParser->stop(); | |
| 887 m_weakFactory.revokeAll(); | |
| 888 } | 844 } |
| 889 | 845 |
| 890 void HTMLDocumentParser::append(const String& inputSource) { | 846 void HTMLDocumentParser::append(const String& inputSource) { |
| 891 if (isStopped()) | 847 if (isStopped()) |
| 892 return; | 848 return; |
| 893 | 849 |
| 894 // We should never reach this point if we're using a parser thread, as | 850 // We should never reach this point if we're using a parser thread, as |
| 895 // appendBytes() will directly ship the data to the thread. | 851 // appendBytes() will directly ship the data to the thread. |
| 896 ASSERT(!shouldUseThreading()); | 852 ASSERT(!shouldUseThreading()); |
| 897 | 853 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 934 | 890 |
| 935 pumpTokenizerIfPossible(); | 891 pumpTokenizerIfPossible(); |
| 936 | 892 |
| 937 endIfDelayed(); | 893 endIfDelayed(); |
| 938 } | 894 } |
| 939 | 895 |
| 940 void HTMLDocumentParser::end() { | 896 void HTMLDocumentParser::end() { |
| 941 ASSERT(!isDetached()); | 897 ASSERT(!isDetached()); |
| 942 ASSERT(!isScheduledForResume()); | 898 ASSERT(!isScheduledForResume()); |
| 943 | 899 |
| 944 if (m_haveBackgroundParser) | 900 m_backgroundParser.clear(); |
| 945 stopBackgroundParser(); | |
| 946 | 901 |
| 947 // Informs the the rest of WebCore that parsing is really finished (and | 902 // Informs the the rest of WebCore that parsing is really finished (and |
| 948 // deletes this). | 903 // deletes this). |
| 949 m_treeBuilder->finished(); | 904 m_treeBuilder->finished(); |
| 950 | 905 |
| 951 DocumentParser::stopParsing(); | 906 DocumentParser::stopParsing(); |
| 952 } | 907 } |
| 953 | 908 |
| 954 void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd() { | 909 void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd() { |
| 955 ASSERT(isStopping()); | 910 ASSERT(isStopping()); |
| 956 // FIXME: It may not be correct to disable this for the background parser. | 911 // FIXME: It may not be correct to disable this for the background parser. |
| 957 // That means hasInsertionPoint() may not be correct in some cases. | 912 // That means hasInsertionPoint() may not be correct in some cases. |
| 958 ASSERT(!hasInsertionPoint() || m_haveBackgroundParser); | 913 ASSERT(!hasInsertionPoint() || m_backgroundParser); |
| 959 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing()) | 914 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing()) |
| 960 return; | 915 return; |
| 961 end(); | 916 end(); |
| 962 } | 917 } |
| 963 | 918 |
| 964 void HTMLDocumentParser::attemptToEnd() { | 919 void HTMLDocumentParser::attemptToEnd() { |
| 965 // finish() indicates we will not receive any more data. If we are waiting on | 920 // finish() indicates we will not receive any more data. If we are waiting on |
| 966 // an external script to load, we can't finish parsing quite yet. | 921 // an external script to load, we can't finish parsing quite yet. |
| 967 | 922 |
| 968 if (shouldDelayEnd()) { | 923 if (shouldDelayEnd()) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 989 // sense to call any methods on DocumentParser once it's been stopped. | 944 // sense to call any methods on DocumentParser once it's been stopped. |
| 990 // However, FrameLoader::stop calls DocumentParser::finish unconditionally. | 945 // However, FrameLoader::stop calls DocumentParser::finish unconditionally. |
| 991 | 946 |
| 992 flush(); | 947 flush(); |
| 993 if (isDetached()) | 948 if (isDetached()) |
| 994 return; | 949 return; |
| 995 | 950 |
| 996 // Empty documents never got an append() call, and thus have never started a | 951 // Empty documents never got an append() call, and thus have never started a |
| 997 // background parser. In those cases, we ignore shouldUseThreading() and fall | 952 // background parser. In those cases, we ignore shouldUseThreading() and fall |
| 998 // through to the non-threading case. | 953 // through to the non-threading case. |
| 999 if (m_haveBackgroundParser) { | 954 if (m_backgroundParser) { |
| 1000 if (!m_input.haveSeenEndOfFile()) | 955 if (!m_input.haveSeenEndOfFile()) |
| 1001 m_input.closeWithoutMarkingEndOfFile(); | 956 m_input.closeWithoutMarkingEndOfFile(); |
| 1002 m_loadingTaskRunner->postTask( | 957 m_backgroundParser->finish(); |
| 1003 BLINK_FROM_HERE, | |
| 1004 WTF::bind(&BackgroundHTMLParser::finish, m_backgroundParser)); | |
| 1005 return; | 958 return; |
| 1006 } | 959 } |
| 1007 | 960 |
| 1008 if (!m_tokenizer) { | 961 if (!m_tokenizer) { |
| 1009 ASSERT(!m_token); | 962 ASSERT(!m_token); |
| 1010 // We're finishing before receiving any data. Rather than booting up the | 963 // We're finishing before receiving any data. Rather than booting up the |
| 1011 // background parser just to spin it down, we finish parsing synchronously. | 964 // background parser just to spin it down, we finish parsing synchronously. |
| 1012 m_token = WTF::wrapUnique(new HTMLToken); | 965 m_token = WTF::wrapUnique(new HTMLToken); |
| 1013 m_tokenizer = HTMLTokenizer::create(m_options); | 966 m_tokenizer = HTMLTokenizer::create(m_options); |
| 1014 } | 967 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1027 return false; | 980 return false; |
| 1028 return m_scriptRunner->isExecutingScript(); | 981 return m_scriptRunner->isExecutingScript(); |
| 1029 } | 982 } |
| 1030 | 983 |
| 1031 bool HTMLDocumentParser::isParsingAtLineNumber() const { | 984 bool HTMLDocumentParser::isParsingAtLineNumber() const { |
| 1032 return m_isParsingAtLineNumber && | 985 return m_isParsingAtLineNumber && |
| 1033 ScriptableDocumentParser::isParsingAtLineNumber(); | 986 ScriptableDocumentParser::isParsingAtLineNumber(); |
| 1034 } | 987 } |
| 1035 | 988 |
| 1036 OrdinalNumber HTMLDocumentParser::lineNumber() const { | 989 OrdinalNumber HTMLDocumentParser::lineNumber() const { |
| 1037 if (m_haveBackgroundParser) | 990 if (m_backgroundParser) |
| 1038 return m_textPosition.m_line; | 991 return m_textPosition.m_line; |
| 1039 | 992 |
| 1040 return m_input.current().currentLine(); | 993 return m_input.current().currentLine(); |
| 1041 } | 994 } |
| 1042 | 995 |
| 1043 TextPosition HTMLDocumentParser::textPosition() const { | 996 TextPosition HTMLDocumentParser::textPosition() const { |
| 1044 if (m_haveBackgroundParser) | 997 if (m_backgroundParser) |
| 1045 return m_textPosition; | 998 return m_textPosition; |
| 1046 | 999 |
| 1047 const SegmentedString& currentString = m_input.current(); | 1000 const SegmentedString& currentString = m_input.current(); |
| 1048 OrdinalNumber line = currentString.currentLine(); | 1001 OrdinalNumber line = currentString.currentLine(); |
| 1049 OrdinalNumber column = currentString.currentColumn(); | 1002 OrdinalNumber column = currentString.currentColumn(); |
| 1050 | 1003 |
| 1051 return TextPosition(line, column); | 1004 return TextPosition(line, column); |
| 1052 } | 1005 } |
| 1053 | 1006 |
| 1054 bool HTMLDocumentParser::isWaitingForScripts() const { | 1007 bool HTMLDocumentParser::isWaitingForScripts() const { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1071 } | 1024 } |
| 1072 | 1025 |
| 1073 void HTMLDocumentParser::resumeParsingAfterPause() { | 1026 void HTMLDocumentParser::resumeParsingAfterPause() { |
| 1074 ASSERT(!isExecutingScript()); | 1027 ASSERT(!isExecutingScript()); |
| 1075 DCHECK(!isPaused()); | 1028 DCHECK(!isPaused()); |
| 1076 | 1029 |
| 1077 checkIfBodyStlyesheetAdded(); | 1030 checkIfBodyStlyesheetAdded(); |
| 1078 if (isPaused()) | 1031 if (isPaused()) |
| 1079 return; | 1032 return; |
| 1080 | 1033 |
| 1081 if (m_haveBackgroundParser) { | 1034 if (m_backgroundParser) { |
| 1082 if (m_lastChunkBeforePause) { | 1035 if (m_lastChunkBeforePause) { |
| 1083 validateSpeculations(std::move(m_lastChunkBeforePause)); | 1036 validateSpeculations(std::move(m_lastChunkBeforePause)); |
| 1084 DCHECK(!m_lastChunkBeforePause); | 1037 DCHECK(!m_lastChunkBeforePause); |
| 1085 pumpPendingSpeculations(); | 1038 pumpPendingSpeculations(); |
| 1086 } | 1039 } |
| 1087 return; | 1040 return; |
| 1088 } | 1041 } |
| 1089 | 1042 |
| 1090 m_insertionPreloadScanner.reset(); | 1043 m_insertionPreloadScanner.reset(); |
| 1091 if (m_tokenizer) { | 1044 if (m_tokenizer) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1184 if (m_parserScheduler) | 1137 if (m_parserScheduler) |
| 1185 m_parserScheduler->resume(); | 1138 m_parserScheduler->resume(); |
| 1186 } | 1139 } |
| 1187 | 1140 |
| 1188 void HTMLDocumentParser::appendBytes(const char* data, size_t length) { | 1141 void HTMLDocumentParser::appendBytes(const char* data, size_t length) { |
| 1189 if (!length || isStopped()) | 1142 if (!length || isStopped()) |
| 1190 return; | 1143 return; |
| 1191 | 1144 |
| 1192 if (shouldUseThreading()) { | 1145 if (shouldUseThreading()) { |
| 1193 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); | 1146 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); |
| 1194 if (!m_haveBackgroundParser) | 1147 if (!m_backgroundParser) |
| 1195 startBackgroundParser(); | 1148 startBackgroundParser(); |
| 1196 | 1149 |
| 1197 std::unique_ptr<Vector<char>> buffer = | 1150 std::unique_ptr<Vector<char>> buffer = |
| 1198 WTF::makeUnique<Vector<char>>(length); | 1151 WTF::makeUnique<Vector<char>>(length); |
| 1199 memcpy(buffer->data(), data, length); | 1152 memcpy(buffer->data(), data, length); |
| 1200 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), | 1153 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), |
| 1201 "HTMLDocumentParser::appendBytes", "size", (unsigned)length); | 1154 "HTMLDocumentParser::appendBytes", "size", (unsigned)length); |
| 1202 | 1155 |
| 1203 m_loadingTaskRunner->postTask( | 1156 m_backgroundParser->appendRawBytesFromMainThread(std::move(buffer), |
| 1204 BLINK_FROM_HERE, | 1157 bytesReceivedTime); |
| 1205 WTF::bind(&BackgroundHTMLParser::appendRawBytesFromMainThread, | |
| 1206 m_backgroundParser, WTF::passed(std::move(buffer)), | |
| 1207 bytesReceivedTime)); | |
| 1208 return; | 1158 return; |
| 1209 } | 1159 } |
| 1210 | 1160 |
| 1211 DecodedDataDocumentParser::appendBytes(data, length); | 1161 DecodedDataDocumentParser::appendBytes(data, length); |
| 1212 } | 1162 } |
| 1213 | 1163 |
| 1214 void HTMLDocumentParser::flush() { | 1164 void HTMLDocumentParser::flush() { |
| 1215 // If we've got no decoder, we never received any data. | 1165 // If we've got no decoder, we never received any data. |
| 1216 if (isDetached() || needsDecoder()) | 1166 if (isDetached() || needsDecoder()) |
| 1217 return; | 1167 return; |
| 1218 | 1168 |
| 1219 if (shouldUseThreading()) { | 1169 if (shouldUseThreading()) { |
| 1220 // In some cases, flush() is called without any invocation of appendBytes. | 1170 // In some cases, flush() is called without any invocation of appendBytes. |
| 1221 // Fallback to synchronous parsing in that case. | 1171 // Fallback to synchronous parsing in that case. |
| 1222 if (!m_haveBackgroundParser) { | 1172 if (!m_backgroundParser) { |
| 1223 m_shouldUseThreading = false; | 1173 m_shouldUseThreading = false; |
| 1224 m_token = WTF::wrapUnique(new HTMLToken); | 1174 m_token = WTF::wrapUnique(new HTMLToken); |
| 1225 m_tokenizer = HTMLTokenizer::create(m_options); | 1175 m_tokenizer = HTMLTokenizer::create(m_options); |
| 1226 DecodedDataDocumentParser::flush(); | 1176 DecodedDataDocumentParser::flush(); |
| 1227 return; | 1177 return; |
| 1228 } | 1178 } |
| 1229 | 1179 m_backgroundParser->flush(); |
| 1230 m_loadingTaskRunner->postTask( | |
| 1231 BLINK_FROM_HERE, | |
| 1232 WTF::bind(&BackgroundHTMLParser::flush, m_backgroundParser)); | |
| 1233 } else { | 1180 } else { |
| 1234 DecodedDataDocumentParser::flush(); | 1181 DecodedDataDocumentParser::flush(); |
| 1235 } | 1182 } |
| 1236 } | 1183 } |
| 1237 | 1184 |
| 1238 void HTMLDocumentParser::setDecoder( | 1185 void HTMLDocumentParser::setDecoder( |
| 1239 std::unique_ptr<TextResourceDecoder> decoder) { | 1186 std::unique_ptr<TextResourceDecoder> decoder) { |
| 1240 ASSERT(decoder); | 1187 ASSERT(decoder); |
| 1241 DecodedDataDocumentParser::setDecoder(std::move(decoder)); | 1188 DecodedDataDocumentParser::setDecoder(std::move(decoder)); |
| 1242 | 1189 |
| 1243 if (m_haveBackgroundParser) { | 1190 if (m_backgroundParser) |
| 1244 m_loadingTaskRunner->postTask( | 1191 m_backgroundParser->setDecoder(takeDecoder()); |
| 1245 BLINK_FROM_HERE, | |
| 1246 WTF::bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, | |
| 1247 WTF::passed(takeDecoder()))); | |
| 1248 } | |
| 1249 } | 1192 } |
| 1250 | 1193 |
| 1251 void HTMLDocumentParser::documentElementAvailable() { | 1194 void HTMLDocumentParser::documentElementAvailable() { |
| 1252 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable"); | 1195 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable"); |
| 1253 DCHECK(document()->documentElement()); | 1196 DCHECK(document()->documentElement()); |
| 1254 fetchQueuedPreloads(); | 1197 fetchQueuedPreloads(); |
| 1255 } | 1198 } |
| 1256 | 1199 |
| 1257 std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::createPreloadScanner() { | 1200 std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::createPreloadScanner() { |
| 1258 return HTMLPreloadScanner::create( | 1201 return HTMLPreloadScanner::create( |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1330 successHistogram.count(duration); | 1273 successHistogram.count(duration); |
| 1331 } else { | 1274 } else { |
| 1332 DEFINE_STATIC_LOCAL( | 1275 DEFINE_STATIC_LOCAL( |
| 1333 CustomCountHistogram, failureHistogram, | 1276 CustomCountHistogram, failureHistogram, |
| 1334 ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); | 1277 ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); |
| 1335 failureHistogram.count(duration); | 1278 failureHistogram.count(duration); |
| 1336 } | 1279 } |
| 1337 } | 1280 } |
| 1338 | 1281 |
| 1339 } // namespace blink | 1282 } // namespace blink |
| OLD | NEW |