OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 #include "platform/Histogram.h" | 48 #include "platform/Histogram.h" |
49 #include "platform/SharedBuffer.h" | 49 #include "platform/SharedBuffer.h" |
50 #include "platform/ThreadSafeFunctional.h" | 50 #include "platform/ThreadSafeFunctional.h" |
51 #include "platform/TraceEvent.h" | 51 #include "platform/TraceEvent.h" |
52 #include "platform/heap/Handle.h" | 52 #include "platform/heap/Handle.h" |
53 #include "public/platform/Platform.h" | 53 #include "public/platform/Platform.h" |
54 #include "public/platform/WebFrameScheduler.h" | 54 #include "public/platform/WebFrameScheduler.h" |
55 #include "public/platform/WebLoadingBehaviorFlag.h" | 55 #include "public/platform/WebLoadingBehaviorFlag.h" |
56 #include "public/platform/WebScheduler.h" | 56 #include "public/platform/WebScheduler.h" |
57 #include "public/platform/WebThread.h" | 57 #include "public/platform/WebThread.h" |
58 #include "wtf/PtrUtil.h" | |
59 #include "wtf/TemporaryChange.h" | 58 #include "wtf/TemporaryChange.h" |
60 #include <memory> | |
61 | 59 |
62 namespace blink { | 60 namespace blink { |
63 | 61 |
64 using namespace HTMLNames; | 62 using namespace HTMLNames; |
65 | 63 |
66 // This is a direct transcription of step 4 from: | 64 // This is a direct transcription of step 4 from: |
67 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag
ment-case | 65 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag
ment-case |
68 static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem
ent, bool reportErrors, const HTMLParserOptions& options) | 66 static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem
ent, bool reportErrors, const HTMLParserOptions& options) |
69 { | 67 { |
70 if (!contextElement) | 68 if (!contextElement) |
(...skipping 13 matching lines...) Expand all Loading... |
84 if (contextTag.matches(scriptTag)) | 82 if (contextTag.matches(scriptTag)) |
85 return reportErrors ? HTMLTokenizer::ScriptDataState : HTMLTokenizer::PL
AINTEXTState; | 83 return reportErrors ? HTMLTokenizer::ScriptDataState : HTMLTokenizer::PL
AINTEXTState; |
86 if (contextTag.matches(plaintextTag)) | 84 if (contextTag.matches(plaintextTag)) |
87 return HTMLTokenizer::PLAINTEXTState; | 85 return HTMLTokenizer::PLAINTEXTState; |
88 return HTMLTokenizer::DataState; | 86 return HTMLTokenizer::DataState; |
89 } | 87 } |
90 | 88 |
91 HTMLDocumentParser::HTMLDocumentParser(HTMLDocument& document, ParserSynchroniza
tionPolicy syncPolicy) | 89 HTMLDocumentParser::HTMLDocumentParser(HTMLDocument& document, ParserSynchroniza
tionPolicy syncPolicy) |
92 : ScriptableDocumentParser(document) | 90 : ScriptableDocumentParser(document) |
93 , m_options(&document) | 91 , m_options(&document) |
94 , m_token(syncPolicy == ForceSynchronousParsing ? wrapUnique(new HTMLToken)
: nullptr) | 92 , m_token(syncPolicy == ForceSynchronousParsing ? adoptPtr(new HTMLToken) :
nullptr) |
95 , m_tokenizer(syncPolicy == ForceSynchronousParsing ? HTMLTokenizer::create(
m_options) : nullptr) | 93 , m_tokenizer(syncPolicy == ForceSynchronousParsing ? HTMLTokenizer::create(
m_options) : nullptr) |
96 , m_scriptRunner(HTMLScriptRunner::create(&document, this)) | 94 , m_scriptRunner(HTMLScriptRunner::create(&document, this)) |
97 , m_treeBuilder(HTMLTreeBuilder::create(this, &document, getParserContentPol
icy(), m_options)) | 95 , m_treeBuilder(HTMLTreeBuilder::create(this, &document, getParserContentPol
icy(), m_options)) |
98 , m_loadingTaskRunner(wrapUnique(document.loadingTaskRunner()->clone())) | 96 , m_loadingTaskRunner(adoptPtr(document.loadingTaskRunner()->clone())) |
99 , m_parserScheduler(HTMLParserScheduler::create(this, m_loadingTaskRunner.ge
t())) | 97 , m_parserScheduler(HTMLParserScheduler::create(this, m_loadingTaskRunner.ge
t())) |
100 , m_xssAuditorDelegate(&document) | 98 , m_xssAuditorDelegate(&document) |
101 , m_weakFactory(this) | 99 , m_weakFactory(this) |
102 , m_preloader(HTMLResourcePreloader::create(document)) | 100 , m_preloader(HTMLResourcePreloader::create(document)) |
103 , m_parsedChunkQueue(ParsedChunkQueue::create()) | 101 , m_parsedChunkQueue(ParsedChunkQueue::create()) |
104 , m_evaluator(DocumentWriteEvaluator::create(document)) | 102 , m_evaluator(DocumentWriteEvaluator::create(document)) |
105 , m_shouldUseThreading(syncPolicy == AllowAsynchronousParsing) | 103 , m_shouldUseThreading(syncPolicy == AllowAsynchronousParsing) |
106 , m_endWasDelayed(false) | 104 , m_endWasDelayed(false) |
107 , m_haveBackgroundParser(false) | 105 , m_haveBackgroundParser(false) |
108 , m_tasksWereSuspended(false) | 106 , m_tasksWereSuspended(false) |
109 , m_pumpSessionNestingLevel(0) | 107 , m_pumpSessionNestingLevel(0) |
110 , m_pumpSpeculationsSessionNestingLevel(0) | 108 , m_pumpSpeculationsSessionNestingLevel(0) |
111 , m_isParsingAtLineNumber(false) | 109 , m_isParsingAtLineNumber(false) |
112 , m_triedLoadingLinkHeaders(false) | 110 , m_triedLoadingLinkHeaders(false) |
113 { | 111 { |
114 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); | 112 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); |
115 } | 113 } |
116 | 114 |
117 // FIXME: Member variables should be grouped into self-initializing structs to | 115 // FIXME: Member variables should be grouped into self-initializing structs to |
118 // minimize code duplication between these constructors. | 116 // minimize code duplication between these constructors. |
119 HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont
extElement, ParserContentPolicy parserContentPolicy) | 117 HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont
extElement, ParserContentPolicy parserContentPolicy) |
120 : ScriptableDocumentParser(fragment->document(), parserContentPolicy) | 118 : ScriptableDocumentParser(fragment->document(), parserContentPolicy) |
121 , m_options(&fragment->document()) | 119 , m_options(&fragment->document()) |
122 , m_token(wrapUnique(new HTMLToken)) | 120 , m_token(adoptPtr(new HTMLToken)) |
123 , m_tokenizer(HTMLTokenizer::create(m_options)) | 121 , m_tokenizer(HTMLTokenizer::create(m_options)) |
124 , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, this
->getParserContentPolicy(), m_options)) | 122 , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, this
->getParserContentPolicy(), m_options)) |
125 , m_loadingTaskRunner(wrapUnique(fragment->document().loadingTaskRunner()->c
lone())) | 123 , m_loadingTaskRunner(adoptPtr(fragment->document().loadingTaskRunner()->clo
ne())) |
126 , m_xssAuditorDelegate(&fragment->document()) | 124 , m_xssAuditorDelegate(&fragment->document()) |
127 , m_weakFactory(this) | 125 , m_weakFactory(this) |
128 , m_shouldUseThreading(false) | 126 , m_shouldUseThreading(false) |
129 , m_endWasDelayed(false) | 127 , m_endWasDelayed(false) |
130 , m_haveBackgroundParser(false) | 128 , m_haveBackgroundParser(false) |
131 , m_tasksWereSuspended(false) | 129 , m_tasksWereSuspended(false) |
132 , m_pumpSessionNestingLevel(0) | 130 , m_pumpSessionNestingLevel(0) |
133 , m_pumpSpeculationsSessionNestingLevel(0) | 131 , m_pumpSpeculationsSessionNestingLevel(0) |
134 { | 132 { |
135 bool reportErrors = false; // For now document fragment parsing never report
s errors. | 133 bool reportErrors = false; // For now document fragment parsing never report
s errors. |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 return false; | 283 return false; |
286 | 284 |
287 return true; | 285 return true; |
288 } | 286 } |
289 | 287 |
290 void HTMLDocumentParser::notifyPendingParsedChunks() | 288 void HTMLDocumentParser::notifyPendingParsedChunks() |
291 { | 289 { |
292 TRACE_EVENT0("blink", "HTMLDocumentParser::notifyPendingParsedChunks"); | 290 TRACE_EVENT0("blink", "HTMLDocumentParser::notifyPendingParsedChunks"); |
293 ASSERT(m_parsedChunkQueue); | 291 ASSERT(m_parsedChunkQueue); |
294 | 292 |
295 Vector<std::unique_ptr<ParsedChunk>> pendingChunks; | 293 Vector<OwnPtr<ParsedChunk>> pendingChunks; |
296 m_parsedChunkQueue->takeAll(pendingChunks); | 294 m_parsedChunkQueue->takeAll(pendingChunks); |
297 | 295 |
298 if (!isParsing()) | 296 if (!isParsing()) |
299 return; | 297 return; |
300 | 298 |
301 // ApplicationCache needs to be initialized before issuing preloads. | 299 // ApplicationCache needs to be initialized before issuing preloads. |
302 // We suspend preload until HTMLHTMLElement is inserted and | 300 // We suspend preload until HTMLHTMLElement is inserted and |
303 // ApplicationCache is initialized. | 301 // ApplicationCache is initialized. |
304 if (!document()->documentElement()) { | 302 if (!document()->documentElement()) { |
305 for (auto& chunk : pendingChunks) { | 303 for (auto& chunk : pendingChunks) { |
(...skipping 30 matching lines...) Expand all Loading... |
336 else | 334 else |
337 m_parserScheduler->scheduleForResume(); | 335 m_parserScheduler->scheduleForResume(); |
338 } | 336 } |
339 } | 337 } |
340 | 338 |
341 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume
ntEncodingData& data) | 339 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume
ntEncodingData& data) |
342 { | 340 { |
343 document()->setEncodingData(data); | 341 document()->setEncodingData(data); |
344 } | 342 } |
345 | 343 |
346 void HTMLDocumentParser::validateSpeculations(std::unique_ptr<ParsedChunk> chunk
) | 344 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk) |
347 { | 345 { |
348 ASSERT(chunk); | 346 ASSERT(chunk); |
349 if (isWaitingForScripts()) { | 347 if (isWaitingForScripts()) { |
350 // We're waiting on a network script, just save the chunk, we'll get | 348 // We're waiting on a network script, just save the chunk, we'll get |
351 // a second validateSpeculations call after the script completes. | 349 // a second validateSpeculations call after the script completes. |
352 // This call should have been made immediately after runScriptsForPaused
TreeBuilder | 350 // This call should have been made immediately after runScriptsForPaused
TreeBuilder |
353 // which may have started a network load and left us waiting. | 351 // which may have started a network load and left us waiting. |
354 ASSERT(!m_lastChunkBeforeScript); | 352 ASSERT(!m_lastChunkBeforeScript); |
355 m_lastChunkBeforeScript = std::move(chunk); | 353 m_lastChunkBeforeScript = std::move(chunk); |
356 return; | 354 return; |
357 } | 355 } |
358 | 356 |
359 ASSERT(!m_lastChunkBeforeScript); | 357 ASSERT(!m_lastChunkBeforeScript); |
360 std::unique_ptr<HTMLTokenizer> tokenizer = std::move(m_tokenizer); | 358 OwnPtr<HTMLTokenizer> tokenizer = std::move(m_tokenizer); |
361 std::unique_ptr<HTMLToken> token = std::move(m_token); | 359 OwnPtr<HTMLToken> token = std::move(m_token); |
362 | 360 |
363 if (!tokenizer) { | 361 if (!tokenizer) { |
364 // There must not have been any changes to the HTMLTokenizer state on | 362 // There must not have been any changes to the HTMLTokenizer state on |
365 // the main thread, which means the speculation buffer is correct. | 363 // the main thread, which means the speculation buffer is correct. |
366 return; | 364 return; |
367 } | 365 } |
368 | 366 |
369 // Currently we're only smart enough to reuse the speculation buffer if the
tokenizer | 367 // Currently we're only smart enough to reuse the speculation buffer if the
tokenizer |
370 // both starts and ends in the DataState. That state is simplest because the
HTMLToken | 368 // both starts and ends in the DataState. That state is simplest because the
HTMLToken |
371 // is always in the Uninitialized state. We should consider whether we can r
euse the | 369 // is always in the Uninitialized state. We should consider whether we can r
euse the |
372 // speculation buffer in other states, but we'd likely need to do something
more | 370 // speculation buffer in other states, but we'd likely need to do something
more |
373 // sophisticated with the HTMLToken. | 371 // sophisticated with the HTMLToken. |
374 if (chunk->tokenizerState == HTMLTokenizer::DataState | 372 if (chunk->tokenizerState == HTMLTokenizer::DataState |
375 && tokenizer->getState() == HTMLTokenizer::DataState | 373 && tokenizer->getState() == HTMLTokenizer::DataState |
376 && m_input.current().isEmpty() | 374 && m_input.current().isEmpty() |
377 && chunk->treeBuilderState == HTMLTreeBuilderSimulator::stateFor(m_treeB
uilder.get())) { | 375 && chunk->treeBuilderState == HTMLTreeBuilderSimulator::stateFor(m_treeB
uilder.get())) { |
378 ASSERT(token->isUninitialized()); | 376 ASSERT(token->isUninitialized()); |
379 return; | 377 return; |
380 } | 378 } |
381 | 379 |
382 discardSpeculationsAndResumeFrom(std::move(chunk), std::move(token), std::mo
ve(tokenizer)); | 380 discardSpeculationsAndResumeFrom(std::move(chunk), std::move(token), std::mo
ve(tokenizer)); |
383 } | 381 } |
384 | 382 |
385 void HTMLDocumentParser::discardSpeculationsAndResumeFrom(std::unique_ptr<Parsed
Chunk> lastChunkBeforeScript, std::unique_ptr<HTMLToken> token, std::unique_ptr<
HTMLTokenizer> tokenizer) | 383 void HTMLDocumentParser::discardSpeculationsAndResumeFrom(PassOwnPtr<ParsedChunk
> lastChunkBeforeScript, PassOwnPtr<HTMLToken> token, PassOwnPtr<HTMLTokenizer>
tokenizer) |
386 { | 384 { |
387 m_weakFactory.revokeAll(); | 385 m_weakFactory.revokeAll(); |
388 m_speculations.clear(); | 386 m_speculations.clear(); |
389 | 387 |
390 std::unique_ptr<BackgroundHTMLParser::Checkpoint> checkpoint = wrapUnique(ne
w BackgroundHTMLParser::Checkpoint); | 388 OwnPtr<BackgroundHTMLParser::Checkpoint> checkpoint = adoptPtr(new Backgroun
dHTMLParser::Checkpoint); |
391 checkpoint->parser = m_weakFactory.createWeakPtr(); | 389 checkpoint->parser = m_weakFactory.createWeakPtr(); |
392 checkpoint->token = std::move(token); | 390 checkpoint->token = std::move(token); |
393 checkpoint->tokenizer = std::move(tokenizer); | 391 checkpoint->tokenizer = std::move(tokenizer); |
394 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil
der.get()); | 392 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil
der.get()); |
395 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; | 393 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; |
396 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner
Checkpoint; | 394 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner
Checkpoint; |
397 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); | 395 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); |
398 m_input.current().clear(); // FIXME: This should be passed in instead of cle
ared. | 396 m_input.current().clear(); // FIXME: This should be passed in instead of cle
ared. |
399 | 397 |
400 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); | 398 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); |
401 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::r
esumeFrom, m_backgroundParser, passed(std::move(checkpoint)))); | 399 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::r
esumeFrom, m_backgroundParser, passed(std::move(checkpoint)))); |
402 } | 400 } |
403 | 401 |
404 size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(std::unique_pt
r<ParsedChunk> popChunk) | 402 size_t HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Par
sedChunk> popChunk) |
405 { | 403 { |
406 TRACE_EVENT_WITH_FLOW0("blink,loading", "HTMLDocumentParser::processParsedCh
unkFromBackgroundParser", popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); | 404 TRACE_EVENT_WITH_FLOW0("blink,loading", "HTMLDocumentParser::processParsedCh
unkFromBackgroundParser", popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); |
407 TemporaryChange<bool> hasLineNumber(m_isParsingAtLineNumber, true); | 405 TemporaryChange<bool> hasLineNumber(m_isParsingAtLineNumber, true); |
408 | 406 |
409 ASSERT_WITH_SECURITY_IMPLICATION(m_pumpSpeculationsSessionNestingLevel == 1)
; | 407 ASSERT_WITH_SECURITY_IMPLICATION(m_pumpSpeculationsSessionNestingLevel == 1)
; |
410 ASSERT_WITH_SECURITY_IMPLICATION(!inPumpSession()); | 408 ASSERT_WITH_SECURITY_IMPLICATION(!inPumpSession()); |
411 ASSERT(!isParsingFragment()); | 409 ASSERT(!isParsingFragment()); |
412 ASSERT(!isWaitingForScripts()); | 410 ASSERT(!isWaitingForScripts()); |
413 ASSERT(!isStopped()); | 411 ASSERT(!isStopped()); |
414 ASSERT(shouldUseThreading()); | 412 ASSERT(shouldUseThreading()); |
415 ASSERT(!m_tokenizer); | 413 ASSERT(!m_tokenizer); |
416 ASSERT(!m_token); | 414 ASSERT(!m_token); |
417 ASSERT(!m_lastChunkBeforeScript); | 415 ASSERT(!m_lastChunkBeforeScript); |
418 | 416 |
419 std::unique_ptr<ParsedChunk> chunk(std::move(popChunk)); | 417 OwnPtr<ParsedChunk> chunk(std::move(popChunk)); |
420 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); | 418 OwnPtr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); |
421 size_t elementTokenCount = 0; | 419 size_t elementTokenCount = 0; |
422 | 420 |
423 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::s
tartedChunkWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); | 421 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::s
tartedChunkWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); |
424 | 422 |
425 for (const auto& xssInfo : chunk->xssInfos) { | 423 for (const auto& xssInfo : chunk->xssInfos) { |
426 m_textPosition = xssInfo->m_textPosition; | 424 m_textPosition = xssInfo->m_textPosition; |
427 m_xssAuditorDelegate.didBlockScript(*xssInfo); | 425 m_xssAuditorDelegate.didBlockScript(*xssInfo); |
428 if (isStopped()) | 426 if (isStopped()) |
429 break; | 427 break; |
430 } | 428 } |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), token())
; | 577 m_sourceTracker.start(m_input.current(), m_tokenizer.get(), token())
; |
580 | 578 |
581 if (!m_tokenizer->nextToken(m_input.current(), token())) | 579 if (!m_tokenizer->nextToken(m_input.current(), token())) |
582 break; | 580 break; |
583 | 581 |
584 if (m_xssAuditor.isEnabled()) { | 582 if (m_xssAuditor.isEnabled()) { |
585 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), token()); | 583 m_sourceTracker.end(m_input.current(), m_tokenizer.get(), token()); |
586 | 584 |
587 // We do not XSS filter innerHTML, which means we (intentionally) fa
il | 585 // We do not XSS filter innerHTML, which means we (intentionally) fa
il |
588 // http/tests/security/xssAuditor/dom-write-innerHTML.html | 586 // http/tests/security/xssAuditor/dom-write-innerHTML.html |
589 if (std::unique_ptr<XSSInfo> xssInfo = m_xssAuditor.filterToken(Filt
erTokenRequest(token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) | 587 if (OwnPtr<XSSInfo> xssInfo = m_xssAuditor.filterToken(FilterTokenRe
quest(token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) |
590 m_xssAuditorDelegate.didBlockScript(*xssInfo); | 588 m_xssAuditorDelegate.didBlockScript(*xssInfo); |
591 } | 589 } |
592 | 590 |
593 constructTreeFromHTMLToken(); | 591 constructTreeFromHTMLToken(); |
594 ASSERT(isStopped() || token().isUninitialized()); | 592 ASSERT(isStopped() || token().isUninitialized()); |
595 } | 593 } |
596 | 594 |
597 if (isStopped()) | 595 if (isStopped()) |
598 return; | 596 return; |
599 | 597 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 void HTMLDocumentParser::insert(const SegmentedString& source) | 666 void HTMLDocumentParser::insert(const SegmentedString& source) |
669 { | 667 { |
670 if (isStopped()) | 668 if (isStopped()) |
671 return; | 669 return; |
672 | 670 |
673 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", source.
length()); | 671 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", source.
length()); |
674 | 672 |
675 if (!m_tokenizer) { | 673 if (!m_tokenizer) { |
676 ASSERT(!inPumpSession()); | 674 ASSERT(!inPumpSession()); |
677 ASSERT(m_haveBackgroundParser || wasCreatedByScript()); | 675 ASSERT(m_haveBackgroundParser || wasCreatedByScript()); |
678 m_token = wrapUnique(new HTMLToken); | 676 m_token = adoptPtr(new HTMLToken); |
679 m_tokenizer = HTMLTokenizer::create(m_options); | 677 m_tokenizer = HTMLTokenizer::create(m_options); |
680 } | 678 } |
681 | 679 |
682 SegmentedString excludedLineNumberSource(source); | 680 SegmentedString excludedLineNumberSource(source); |
683 excludedLineNumberSource.setExcludeLineNumbers(); | 681 excludedLineNumberSource.setExcludeLineNumbers(); |
684 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); | 682 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); |
685 pumpTokenizerIfPossible(); | 683 pumpTokenizerIfPossible(); |
686 | 684 |
687 if (isWaitingForScripts()) { | 685 if (isWaitingForScripts()) { |
688 // Check the document.write() output with a separate preload scanner as | 686 // Check the document.write() output with a separate preload scanner as |
(...skipping 15 matching lines...) Expand all Loading... |
704 ASSERT(document()); | 702 ASSERT(document()); |
705 m_haveBackgroundParser = true; | 703 m_haveBackgroundParser = true; |
706 | 704 |
707 // Make sure that a resolver is set up, so that the correct viewport dimensi
ons will be fed to the background parser and preload scanner. | 705 // Make sure that a resolver is set up, so that the correct viewport dimensi
ons will be fed to the background parser and preload scanner. |
708 if (document()->loader()) | 706 if (document()->loader()) |
709 document()->ensureStyleResolver(); | 707 document()->ensureStyleResolver(); |
710 | 708 |
711 RefPtr<WeakReference<BackgroundHTMLParser>> reference = WeakReference<Backgr
oundHTMLParser>::createUnbound(); | 709 RefPtr<WeakReference<BackgroundHTMLParser>> reference = WeakReference<Backgr
oundHTMLParser>::createUnbound(); |
712 m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference); | 710 m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference); |
713 | 711 |
714 std::unique_ptr<BackgroundHTMLParser::Configuration> config = wrapUnique(new
BackgroundHTMLParser::Configuration); | 712 OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new Background
HTMLParser::Configuration); |
715 config->options = m_options; | 713 config->options = m_options; |
716 config->parser = m_weakFactory.createWeakPtr(); | 714 config->parser = m_weakFactory.createWeakPtr(); |
717 config->xssAuditor = wrapUnique(new XSSAuditor); | 715 config->xssAuditor = adoptPtr(new XSSAuditor); |
718 config->xssAuditor->init(document(), &m_xssAuditorDelegate); | 716 config->xssAuditor->init(document(), &m_xssAuditorDelegate); |
719 | 717 |
720 config->decoder = takeDecoder(); | 718 config->decoder = takeDecoder(); |
721 config->parsedChunkQueue = m_parsedChunkQueue.get(); | 719 config->parsedChunkQueue = m_parsedChunkQueue.get(); |
722 if (document()->settings()) { | 720 if (document()->settings()) { |
723 if (document()->settings()->backgroundHtmlParserOutstandingTokenLimit()) | 721 if (document()->settings()->backgroundHtmlParserOutstandingTokenLimit()) |
724 config->outstandingTokenLimit = document()->settings()->backgroundHt
mlParserOutstandingTokenLimit(); | 722 config->outstandingTokenLimit = document()->settings()->backgroundHt
mlParserOutstandingTokenLimit(); |
725 if (document()->settings()->backgroundHtmlParserPendingTokenLimit()) | 723 if (document()->settings()->backgroundHtmlParserPendingTokenLimit()) |
726 config->pendingTokenLimit = document()->settings()->backgroundHtmlPa
rserPendingTokenLimit(); | 724 config->pendingTokenLimit = document()->settings()->backgroundHtmlPa
rserPendingTokenLimit(); |
727 } | 725 } |
728 | 726 |
729 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); | 727 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); |
730 HTMLParserThread::shared()->postTask(threadSafeBind( | 728 HTMLParserThread::shared()->postTask(threadSafeBind( |
731 &BackgroundHTMLParser::start, | 729 &BackgroundHTMLParser::start, |
732 reference.release(), | 730 reference.release(), |
733 passed(std::move(config)), | 731 passed(std::move(config)), |
734 document()->url(), | 732 document()->url(), |
735 passed(CachedDocumentParameters::create(document())), | 733 passed(CachedDocumentParameters::create(document())), |
736 MediaValuesCached::MediaValuesCachedData(*document()), | 734 MediaValuesCached::MediaValuesCachedData(*document()), |
737 passed(wrapUnique(m_loadingTaskRunner->clone())))); | 735 passed(adoptPtr(m_loadingTaskRunner->clone())))); |
738 } | 736 } |
739 | 737 |
740 void HTMLDocumentParser::stopBackgroundParser() | 738 void HTMLDocumentParser::stopBackgroundParser() |
741 { | 739 { |
742 ASSERT(shouldUseThreading()); | 740 ASSERT(shouldUseThreading()); |
743 ASSERT(m_haveBackgroundParser); | 741 ASSERT(m_haveBackgroundParser); |
744 m_haveBackgroundParser = false; | 742 m_haveBackgroundParser = false; |
745 | 743 |
746 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::s
top, m_backgroundParser)); | 744 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParser::s
top, m_backgroundParser)); |
747 m_weakFactory.revokeAll(); | 745 m_weakFactory.revokeAll(); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 m_input.closeWithoutMarkingEndOfFile(); | 851 m_input.closeWithoutMarkingEndOfFile(); |
854 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse
r::finish, m_backgroundParser)); | 852 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse
r::finish, m_backgroundParser)); |
855 return; | 853 return; |
856 } | 854 } |
857 | 855 |
858 if (!m_tokenizer) { | 856 if (!m_tokenizer) { |
859 ASSERT(!m_token); | 857 ASSERT(!m_token); |
860 // We're finishing before receiving any data. Rather than booting up | 858 // We're finishing before receiving any data. Rather than booting up |
861 // the background parser just to spin it down, we finish parsing | 859 // the background parser just to spin it down, we finish parsing |
862 // synchronously. | 860 // synchronously. |
863 m_token = wrapUnique(new HTMLToken); | 861 m_token = adoptPtr(new HTMLToken); |
864 m_tokenizer = HTMLTokenizer::create(m_options); | 862 m_tokenizer = HTMLTokenizer::create(m_options); |
865 } | 863 } |
866 | 864 |
867 // We're not going to get any more data off the network, so we tell the | 865 // We're not going to get any more data off the network, so we tell the |
868 // input stream we've reached the end of file. finish() can be called more | 866 // input stream we've reached the end of file. finish() can be called more |
869 // than once, if the first time does not call end(). | 867 // than once, if the first time does not call end(). |
870 if (!m_input.haveSeenEndOfFile()) | 868 if (!m_input.haveSeenEndOfFile()) |
871 m_input.markEndOfFile(); | 869 m_input.markEndOfFile(); |
872 | 870 |
873 attemptToEnd(); | 871 attemptToEnd(); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1005 | 1003 |
1006 void HTMLDocumentParser::appendBytes(const char* data, size_t length) | 1004 void HTMLDocumentParser::appendBytes(const char* data, size_t length) |
1007 { | 1005 { |
1008 if (!length || isStopped()) | 1006 if (!length || isStopped()) |
1009 return; | 1007 return; |
1010 | 1008 |
1011 if (shouldUseThreading()) { | 1009 if (shouldUseThreading()) { |
1012 if (!m_haveBackgroundParser) | 1010 if (!m_haveBackgroundParser) |
1013 startBackgroundParser(); | 1011 startBackgroundParser(); |
1014 | 1012 |
1015 std::unique_ptr<Vector<char>> buffer = wrapUnique(new Vector<char>(lengt
h)); | 1013 OwnPtr<Vector<char>> buffer = adoptPtr(new Vector<char>(length)); |
1016 memcpy(buffer->data(), data, length); | 1014 memcpy(buffer->data(), data, length); |
1017 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentPars
er::appendBytes", "size", (unsigned)length); | 1015 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), "HTMLDocumentPars
er::appendBytes", "size", (unsigned)length); |
1018 | 1016 |
1019 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse
r::appendRawBytesFromMainThread, m_backgroundParser, passed(std::move(buffer))))
; | 1017 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse
r::appendRawBytesFromMainThread, m_backgroundParser, passed(std::move(buffer))))
; |
1020 return; | 1018 return; |
1021 } | 1019 } |
1022 | 1020 |
1023 DecodedDataDocumentParser::appendBytes(data, length); | 1021 DecodedDataDocumentParser::appendBytes(data, length); |
1024 } | 1022 } |
1025 | 1023 |
1026 void HTMLDocumentParser::flush() | 1024 void HTMLDocumentParser::flush() |
1027 { | 1025 { |
1028 // If we've got no decoder, we never received any data. | 1026 // If we've got no decoder, we never received any data. |
1029 if (isDetached() || needsDecoder()) | 1027 if (isDetached() || needsDecoder()) |
1030 return; | 1028 return; |
1031 | 1029 |
1032 if (shouldUseThreading()) { | 1030 if (shouldUseThreading()) { |
1033 // In some cases, flush() is called without any invocation of | 1031 // In some cases, flush() is called without any invocation of |
1034 // appendBytes. Fallback to synchronous parsing in that case. | 1032 // appendBytes. Fallback to synchronous parsing in that case. |
1035 if (!m_haveBackgroundParser) { | 1033 if (!m_haveBackgroundParser) { |
1036 m_shouldUseThreading = false; | 1034 m_shouldUseThreading = false; |
1037 m_token = wrapUnique(new HTMLToken); | 1035 m_token = adoptPtr(new HTMLToken); |
1038 m_tokenizer = HTMLTokenizer::create(m_options); | 1036 m_tokenizer = HTMLTokenizer::create(m_options); |
1039 DecodedDataDocumentParser::flush(); | 1037 DecodedDataDocumentParser::flush(); |
1040 return; | 1038 return; |
1041 } | 1039 } |
1042 | 1040 |
1043 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse
r::flush, m_backgroundParser)); | 1041 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse
r::flush, m_backgroundParser)); |
1044 } else { | 1042 } else { |
1045 DecodedDataDocumentParser::flush(); | 1043 DecodedDataDocumentParser::flush(); |
1046 } | 1044 } |
1047 } | 1045 } |
1048 | 1046 |
1049 void HTMLDocumentParser::setDecoder(std::unique_ptr<TextResourceDecoder> decoder
) | 1047 void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder) |
1050 { | 1048 { |
1051 ASSERT(decoder); | 1049 ASSERT(decoder); |
1052 DecodedDataDocumentParser::setDecoder(std::move(decoder)); | 1050 DecodedDataDocumentParser::setDecoder(std::move(decoder)); |
1053 | 1051 |
1054 if (m_haveBackgroundParser) | 1052 if (m_haveBackgroundParser) |
1055 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse
r::setDecoder, m_backgroundParser, passed(takeDecoder()))); | 1053 HTMLParserThread::shared()->postTask(threadSafeBind(&BackgroundHTMLParse
r::setDecoder, m_backgroundParser, passed(takeDecoder()))); |
1056 } | 1054 } |
1057 | 1055 |
1058 void HTMLDocumentParser::documentElementAvailable() | 1056 void HTMLDocumentParser::documentElementAvailable() |
1059 { | 1057 { |
1060 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable")
; | 1058 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable")
; |
1061 DCHECK(document()->documentElement()); | 1059 DCHECK(document()->documentElement()); |
1062 for (const String& scriptSource : m_queuedDocumentWriteScripts) { | 1060 for (const String& scriptSource : m_queuedDocumentWriteScripts) { |
1063 evaluateAndPreloadScriptForDocumentWrite(scriptSource); | 1061 evaluateAndPreloadScriptForDocumentWrite(scriptSource); |
1064 } | 1062 } |
1065 | 1063 |
1066 m_queuedDocumentWriteScripts.clear(); | 1064 m_queuedDocumentWriteScripts.clear(); |
1067 if (!m_queuedPreloads.isEmpty()) | 1065 if (!m_queuedPreloads.isEmpty()) |
1068 m_preloader->takeAndPreload(m_queuedPreloads); | 1066 m_preloader->takeAndPreload(m_queuedPreloads); |
1069 } | 1067 } |
1070 | 1068 |
1071 std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::createPreloadScanner() | 1069 PassOwnPtr<HTMLPreloadScanner> HTMLDocumentParser::createPreloadScanner() |
1072 { | 1070 { |
1073 return HTMLPreloadScanner::create( | 1071 return HTMLPreloadScanner::create( |
1074 m_options, | 1072 m_options, |
1075 document()->url(), | 1073 document()->url(), |
1076 CachedDocumentParameters::create(document()), | 1074 CachedDocumentParameters::create(document()), |
1077 MediaValuesCached::MediaValuesCachedData(*document())); | 1075 MediaValuesCached::MediaValuesCachedData(*document())); |
1078 } | 1076 } |
1079 | 1077 |
1080 void HTMLDocumentParser::evaluateAndPreloadScriptForDocumentWrite(const String&
source) | 1078 void HTMLDocumentParser::evaluateAndPreloadScriptForDocumentWrite(const String&
source) |
1081 { | 1079 { |
1082 if (!m_evaluator->shouldEvaluate(source)) | 1080 if (!m_evaluator->shouldEvaluate(source)) |
1083 return; | 1081 return; |
1084 document()->loader()->didObserveLoadingBehavior(WebLoadingBehaviorFlag::WebL
oadingBehaviorDocumentWriteEvaluator); | 1082 document()->loader()->didObserveLoadingBehavior(WebLoadingBehaviorFlag::WebL
oadingBehaviorDocumentWriteEvaluator); |
1085 if (!RuntimeEnabledFeatures::documentWriteEvaluatorEnabled()) | 1083 if (!RuntimeEnabledFeatures::documentWriteEvaluatorEnabled()) |
1086 return; | 1084 return; |
1087 TRACE_EVENT0("blink", "HTMLDocumentParser::evaluateAndPreloadScriptForDocume
ntWrite"); | 1085 TRACE_EVENT0("blink", "HTMLDocumentParser::evaluateAndPreloadScriptForDocume
ntWrite"); |
1088 | 1086 |
1089 double initializeStartTime = monotonicallyIncreasingTimeMS(); | 1087 double initializeStartTime = monotonicallyIncreasingTimeMS(); |
1090 bool neededInitialization = m_evaluator->ensureEvaluationContext(); | 1088 bool neededInitialization = m_evaluator->ensureEvaluationContext(); |
1091 double initializationDuration = monotonicallyIncreasingTimeMS() - initialize
StartTime; | 1089 double initializationDuration = monotonicallyIncreasingTimeMS() - initialize
StartTime; |
1092 | 1090 |
1093 double startTime = monotonicallyIncreasingTimeMS(); | 1091 double startTime = monotonicallyIncreasingTimeMS(); |
1094 String writtenSource = m_evaluator->evaluateAndEmitWrittenSource(source); | 1092 String writtenSource = m_evaluator->evaluateAndEmitWrittenSource(source); |
1095 double duration = monotonicallyIncreasingTimeMS() - startTime; | 1093 double duration = monotonicallyIncreasingTimeMS() - startTime; |
1096 | 1094 |
1097 int currentPreloadCount = document()->loader()->fetcher()->countPreloads(); | 1095 int currentPreloadCount = document()->loader()->fetcher()->countPreloads(); |
1098 std::unique_ptr<HTMLPreloadScanner> scanner = createPreloadScanner(); | 1096 OwnPtr<HTMLPreloadScanner> scanner = createPreloadScanner(); |
1099 scanner->appendToEnd(SegmentedString(writtenSource)); | 1097 scanner->appendToEnd(SegmentedString(writtenSource)); |
1100 scanner->scanAndPreload(m_preloader.get(), document()->baseElementURL(), nul
lptr); | 1098 scanner->scanAndPreload(m_preloader.get(), document()->baseElementURL(), nul
lptr); |
1101 int numPreloads = document()->loader()->fetcher()->countPreloads() - current
PreloadCount; | 1099 int numPreloads = document()->loader()->fetcher()->countPreloads() - current
PreloadCount; |
1102 | 1100 |
1103 TRACE_EVENT_INSTANT2("blink", "HTMLDocumentParser::evaluateAndPreloadScriptF
orDocumentWrite.data", TRACE_EVENT_SCOPE_THREAD, "numPreloads", numPreloads, "sc
riptLength", source.length()); | 1101 TRACE_EVENT_INSTANT2("blink", "HTMLDocumentParser::evaluateAndPreloadScriptF
orDocumentWrite.data", TRACE_EVENT_SCOPE_THREAD, "numPreloads", numPreloads, "sc
riptLength", source.length()); |
1104 | 1102 |
1105 if (neededInitialization) { | 1103 if (neededInitialization) { |
1106 DEFINE_STATIC_LOCAL(CustomCountHistogram, initializeHistograms, ("Preloa
dScanner.DocumentWrite.InitializationTime", 1, 10000, 50)); | 1104 DEFINE_STATIC_LOCAL(CustomCountHistogram, initializeHistograms, ("Preloa
dScanner.DocumentWrite.InitializationTime", 1, 10000, 50)); |
1107 initializeHistograms.count(initializationDuration); | 1105 initializeHistograms.count(initializationDuration); |
1108 } | 1106 } |
1109 | 1107 |
1110 if (numPreloads) { | 1108 if (numPreloads) { |
1111 DEFINE_STATIC_LOCAL(CustomCountHistogram, successHistogram, ("PreloadSca
nner.DocumentWrite.ExecutionTime.Success", 1, 10000, 50)); | 1109 DEFINE_STATIC_LOCAL(CustomCountHistogram, successHistogram, ("PreloadSca
nner.DocumentWrite.ExecutionTime.Success", 1, 10000, 50)); |
1112 successHistogram.count(duration); | 1110 successHistogram.count(duration); |
1113 } else { | 1111 } else { |
1114 DEFINE_STATIC_LOCAL(CustomCountHistogram, failureHistogram, ("PreloadSca
nner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); | 1112 DEFINE_STATIC_LOCAL(CustomCountHistogram, failureHistogram, ("PreloadSca
nner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); |
1115 failureHistogram.count(duration); | 1113 failureHistogram.count(duration); |
1116 } | 1114 } |
1117 | 1115 |
1118 } | 1116 } |
1119 | 1117 |
1120 } // namespace blink | 1118 } // namespace blink |
OLD | NEW |