nsHtml5StreamParser.h (21025B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef nsHtml5StreamParser_h 7 #define nsHtml5StreamParser_h 8 9 #include <tuple> 10 11 #include "MainThreadUtils.h" 12 #include "mozilla/AlreadyAddRefed.h" 13 #include "mozilla/Assertions.h" 14 #include "mozilla/Atomics.h" 15 #include "mozilla/Encoding.h" 16 #include "mozilla/Mutex.h" 17 #include "mozilla/NotNull.h" 18 #include "mozilla/ReentrantMonitor.h" 19 #include "mozilla/RefPtr.h" 20 #include "mozilla/Span.h" 21 #include "mozilla/TimeStamp.h" 22 #include "mozilla/UniquePtr.h" 23 #include "nsCharsetSource.h" 24 #include "nsCOMPtr.h" 25 #include "nsCycleCollectionParticipant.h" 26 #include "nsDebug.h" 27 #include "nsHtml5AtomTable.h" 28 #include "nsIRequestObserver.h" 29 #include "nsISerialEventTarget.h" 30 #include "nsISupports.h" 31 #include "nsStringFwd.h" 32 #include "nsTArray.h" 33 #include "nscore.h" 34 35 class nsCycleCollectionTraversalCallback; 36 class nsHtml5OwningUTF16Buffer; 37 class nsHtml5Parser; 38 class nsHtml5Speculation; 39 class nsHtml5String; 40 class nsHtml5Tokenizer; 41 class nsHtml5TreeBuilder; 42 class nsHtml5TreeOpExecutor; 43 class nsIChannel; 44 class nsIInputStream; 45 class nsIRequest; 46 class nsIRunnable; 47 class nsITimer; 48 class nsIURI; 49 50 namespace mozilla { 51 class EncodingDetector; 52 template <typename T> 53 class Buffer; 54 55 namespace dom { 56 class DocGroup; 57 } 58 } // namespace mozilla 59 60 enum eParserMode { 61 /** 62 * Parse a document normally as HTML. 63 */ 64 NORMAL, 65 66 /** 67 * View document as HTML source. 68 */ 69 VIEW_SOURCE_HTML, 70 71 /** 72 * View document as XML source 73 */ 74 VIEW_SOURCE_XML, 75 76 /** 77 * View document as plain text source 78 */ 79 VIEW_SOURCE_PLAIN, 80 81 /** 82 * View document as plain text 83 */ 84 PLAIN_TEXT, 85 86 /** 87 * Load as data (XHR) 88 */ 89 LOAD_AS_DATA, 90 91 /** 92 * Parse (non-initial) about:blank for normal viewing (not View Source or 93 * data). 94 */ 95 ABOUT_BLANK, 96 }; 97 98 enum eBomState { 99 /** 100 * BOM sniffing hasn't started. 101 */ 102 BOM_SNIFFING_NOT_STARTED, 103 104 /** 105 * BOM sniffing is ongoing, and the first byte of an UTF-16LE BOM has been 106 * seen. 107 */ 108 SEEN_UTF_16_LE_FIRST_BYTE, 109 110 /** 111 * BOM sniffing is ongoing, and the first byte of an UTF-16BE BOM has been 112 * seen. 113 */ 114 SEEN_UTF_16_BE_FIRST_BYTE, 115 116 /** 117 * BOM sniffing is ongoing, and the first byte of an UTF-8 BOM has been 118 * seen. 119 */ 120 SEEN_UTF_8_FIRST_BYTE, 121 122 /** 123 * BOM sniffing is ongoing, and the first and second bytes of an UTF-8 BOM 124 * have been seen. 125 */ 126 SEEN_UTF_8_SECOND_BYTE, 127 128 /** 129 * Seen \x00 in UTF-16BE bogo-XML declaration. 130 */ 131 SEEN_UTF_16_BE_XML_FIRST, 132 133 /** 134 * Seen \x00< in UTF-16BE bogo-XML declaration. 135 */ 136 SEEN_UTF_16_BE_XML_SECOND, 137 138 /** 139 * Seen \x00<\x00 in UTF-16BE bogo-XML declaration. 140 */ 141 SEEN_UTF_16_BE_XML_THIRD, 142 143 /** 144 * Seen \x00<\x00? in UTF-16BE bogo-XML declaration. 145 */ 146 SEEN_UTF_16_BE_XML_FOURTH, 147 148 /** 149 * Seen \x00<\x00?\x00 in UTF-16BE bogo-XML declaration. 150 */ 151 SEEN_UTF_16_BE_XML_FIFTH, 152 153 /** 154 * Seen < in UTF-16BE bogo-XML declaration. 155 */ 156 SEEN_UTF_16_LE_XML_FIRST, 157 158 /** 159 * Seen <\x00 in UTF-16BE bogo-XML declaration. 160 */ 161 SEEN_UTF_16_LE_XML_SECOND, 162 163 /** 164 * Seen <\x00? in UTF-16BE bogo-XML declaration. 165 */ 166 SEEN_UTF_16_LE_XML_THIRD, 167 168 /** 169 * Seen <\x00?\x00 in UTF-16BE bogo-XML declaration. 170 */ 171 SEEN_UTF_16_LE_XML_FOURTH, 172 173 /** 174 * Seen <\x00?\x00x in UTF-16BE bogo-XML declaration. 175 */ 176 SEEN_UTF_16_LE_XML_FIFTH, 177 178 /** 179 * BOM sniffing was started but is now over for whatever reason. 180 */ 181 BOM_SNIFFING_OVER, 182 }; 183 184 enum eHtml5StreamState { 185 STREAM_NOT_STARTED = 0, 186 STREAM_BEING_READ = 1, 187 STREAM_ENDED = 2 188 }; 189 190 class nsHtml5StreamParser final : public nsISupports { 191 template <typename T> 192 using NotNull = mozilla::NotNull<T>; 193 using Encoding = mozilla::Encoding; 194 195 const uint32_t UNCONDITIONAL_META_SCAN_BOUNDARY = 1024; 196 const uint32_t READ_BUFFER_SIZE = 1024; 197 const uint32_t LOCAL_FILE_UTF_8_BUFFER_SIZE = 1024 * 1024 * 4; // 4 MB 198 199 friend class nsHtml5RequestStopper; 200 friend class nsHtml5DataAvailable; 201 friend class nsHtml5StreamParserContinuation; 202 friend class nsHtml5TimerKungFu; 203 friend class nsHtml5StreamParserPtr; 204 friend class nsHtml5StreamListener; 205 206 public: 207 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 208 NS_DECL_CYCLE_COLLECTION_CLASS(nsHtml5StreamParser) 209 210 nsHtml5StreamParser(nsHtml5TreeOpExecutor* aExecutor, nsHtml5Parser* aOwner, 211 eParserMode aMode); 212 213 nsresult OnStartRequest(nsIRequest* aRequest); 214 215 nsresult OnDataAvailable(nsIRequest* aRequest, nsIInputStream* aInStream, 216 uint64_t aSourceOffset, uint32_t aLength); 217 /** 218 * ReentrantMonitorAutoEnter is used for protecting access to 219 * nsHtml5StreamParser::mOnStopCalled and should be obtained from 220 * nsHtml5StreamListener::mDelegateMonitor 221 */ 222 nsresult OnStopRequest( 223 nsIRequest* aRequest, nsresult status, 224 const mozilla::ReentrantMonitorAutoEnter& aProofOfLock); 225 226 // EncodingDeclarationHandler 227 // https://hg.mozilla.org/projects/htmlparser/file/tip/src/nu/validator/htmlparser/common/EncodingDeclarationHandler.java 228 /** 229 * Tree builder uses this to report a late <meta charset> 230 */ 231 bool internalEncodingDeclaration(nsHtml5String aEncoding); 232 233 bool TemplatePushedOrHeadPopped(); 234 235 void RememberGt(int32_t aPos); 236 237 // Not from an external interface 238 239 /** 240 * Post a runnable to the main thread to perform the speculative load 241 * operations without performing the tree operations. 242 * 243 * This should be called at the end of each data available or stop 244 * request runnable running on the parser thread. 245 */ 246 void PostLoadFlusher(); 247 248 /** 249 * Pass a buffer to chardetng. 250 */ 251 void FeedDetector(mozilla::Span<const uint8_t> aBuffer); 252 253 /** 254 * Report EOF to chardetng. 255 */ 256 void DetectorEof(); 257 258 /** 259 * Call this method once you've created a parser, and want to instruct it 260 * about what charset to load 261 * 262 * @param aEncoding the charset of a document 263 * @param aCharsetSource the source of the charset 264 */ 265 inline void SetDocumentCharset(NotNull<const Encoding*> aEncoding, 266 nsCharsetSource aSource, 267 bool aForceAutoDetection) { 268 MOZ_ASSERT(mStreamState == STREAM_NOT_STARTED, 269 "SetDocumentCharset called too late."); 270 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); 271 MOZ_ASSERT(!(aForceAutoDetection && aSource >= kCharsetFromOtherComponent), 272 "Can't force with high-ranking source."); 273 mEncoding = aEncoding; 274 mCharsetSource = aSource; 275 mForceAutoDetection = aForceAutoDetection; 276 mChannelHadCharset = (aSource == kCharsetFromChannel); 277 } 278 279 nsresult GetChannel(nsIChannel** aChannel); 280 281 /** 282 * The owner parser must call this after script execution 283 * when no scripts are executing and the document.written 284 * buffer has been exhausted. 285 * 286 * If the first two arguments are nullptr, instead of 287 * continuing after scripts, this method commits to an 288 * internally-discovered encoding. 289 */ 290 void ContinueAfterScriptsOrEncodingCommitment( 291 nsHtml5Tokenizer* aTokenizer, nsHtml5TreeBuilder* aTreeBuilder, 292 bool aLastWasCR); 293 294 /** 295 * Continues the stream parser if the charset switch failed. 296 */ 297 void ContinueAfterFailedCharsetSwitch(); 298 299 void Terminate() { mTerminated = true; } 300 301 void DropTimer(); 302 303 /** 304 * Sets the URL for View Source title in case this parser ends up being 305 * used for View Source. If aURL is a view-source: URL, takes the inner 306 * URL. data: URLs are shown with an ellipsis instead of the actual data. 307 */ 308 void SetViewSourceTitle(nsIURI* aURL); 309 310 private: 311 virtual ~nsHtml5StreamParser(); 312 313 #ifdef DEBUG 314 bool IsParserThread() { return mEventTarget->IsOnCurrentThread(); } 315 #endif 316 317 void MarkAsBroken(nsresult aRv); 318 319 /** 320 * Marks the stream parser as interrupted. If you ever add calls to this 321 * method, be sure to review Uninterrupt usage very, very carefully to 322 * avoid having a previous in-flight runnable cancel your Interrupt() 323 * call on the other thread too soon. 324 */ 325 void Interrupt() { 326 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); 327 mInterrupted = true; 328 } 329 330 void Uninterrupt() MOZ_NO_THREAD_SAFETY_ANALYSIS { 331 MOZ_ASSERT(IsParserThread(), "Wrong thread!"); 332 mTokenizerMutex.AssertCurrentThreadOwns(); 333 mInterrupted = false; 334 } 335 336 /** 337 * Flushes the tree ops from the tree builder and disarms the flush 338 * timer. 339 */ 340 void FlushTreeOpsAndDisarmTimer(); 341 342 void SwitchDecoderIfAsciiSoFar(NotNull<const Encoding*> aEncoding) 343 MOZ_REQUIRES(mTokenizerMutex); 344 ; 345 346 size_t CountGts(); 347 348 void DiscardMetaSpeculation(); 349 350 bool ProcessLookingForMetaCharset(bool aEof) MOZ_REQUIRES(mTokenizerMutex); 351 352 void ParseAvailableData(); 353 354 void DoStopRequest(); 355 356 void DoDataAvailableBuffer(mozilla::Buffer<uint8_t>&& aBuffer) 357 MOZ_REQUIRES(mTokenizerMutex); 358 359 void DoDataAvailable(mozilla::Span<const uint8_t> aBuffer) 360 MOZ_REQUIRES(mTokenizerMutex); 361 362 static nsresult CopySegmentsToParser(nsIInputStream* aInStream, 363 void* aClosure, const char* aFromSegment, 364 uint32_t aToOffset, uint32_t aCount, 365 uint32_t* aWriteCount) 366 MOZ_REQUIRES(mTokenizerMutex); 367 368 bool IsTerminatedOrInterrupted() { return mTerminated || mInterrupted; } 369 370 bool IsTerminated() { return mTerminated; } 371 372 /** 373 * True when there is a Unicode decoder already 374 */ 375 inline bool HasDecoder() { return !!mUnicodeDecoder; } 376 377 /** 378 * Returns 0 if 1) there aren't at least 2 buffers in mBufferedBytes 379 * or 2) there is no byte '>' in the second buffer. 380 * Otherwise, returns the length of the prefix of the second buffer 381 * that is long enough to contain the first byte '>' in the second 382 * buffer (including the '>' byte). 383 */ 384 size_t LengthOfLtContainingPrefixInSecondBuffer(); 385 386 /** 387 * Push bytes from network when there is no Unicode decoder yet 388 */ 389 nsresult SniffStreamBytes(mozilla::Span<const uint8_t> aFromSegment, 390 bool aEof) MOZ_REQUIRES(mTokenizerMutex); 391 392 /** 393 * Push bytes from network when there is a Unicode decoder already 394 */ 395 nsresult WriteStreamBytes(mozilla::Span<const uint8_t> aFromSegment) 396 MOZ_REQUIRES(mTokenizerMutex); 397 398 /** 399 * Set up the Unicode decoder and write the sniffing buffer into it 400 * followed by the current network buffer. 401 * 402 * @param aPrefix the part of the stream that has already been seen 403 * prior to aFromSegment. In practice, these are the 404 * bytes that are baked into the state of the BOM 405 * and UTF-16 XML declaration-like sniffing state 406 * machine state. 407 * @param aFromSegment The current network buffer 408 */ 409 nsresult SetupDecodingAndWriteSniffingBufferAndCurrentSegment( 410 mozilla::Span<const uint8_t> aPrefix, 411 mozilla::Span<const uint8_t> aFromSegment) MOZ_REQUIRES(mTokenizerMutex); 412 413 /** 414 * Initialize the Unicode decoder, mark the BOM as the source and 415 * drop the sniffer. 416 * 417 * @param aDecoderCharsetName The name for the decoder's charset 418 * (UTF-16BE, UTF-16LE or UTF-8; the BOM has 419 * been swallowed) 420 */ 421 void SetupDecodingFromBom(NotNull<const Encoding*> aEncoding); 422 423 void SetupDecodingFromUtf16BogoXml(NotNull<const Encoding*> aEncoding); 424 425 /** 426 * When speculatively decoding from file: URL as UTF-8, commit 427 * to UTF-8 as the non-speculative encoding and start processing 428 * the decoded data. 429 */ 430 [[nodiscard]] nsresult CommitLocalFileToEncoding(); 431 432 /** 433 * When speculatively decoding from file: URL as UTF-8, redecode 434 * using fallback and then continue normally with the fallback. 435 */ 436 [[nodiscard]] nsresult ReDecodeLocalFile() MOZ_REQUIRES(mTokenizerMutex); 437 438 /** 439 * Potentially guess the encoding using mozilla::EncodingDetector. 440 * Returns the guessed encoding and a telemetry-appropriate source. 441 */ 442 std::tuple<NotNull<const Encoding*>, nsCharsetSource> GuessEncoding( 443 bool aInitial); 444 445 /** 446 * Become confident or resolve and encoding name to its preferred form. 447 * @param aEncoding the value of an internal encoding decl. Acts as an 448 * out param, too, when the method returns true. 449 * @return true if the parser needs to start using the new value of 450 * aEncoding and false if the parser became confident or if 451 * the encoding name did not specify a usable encoding 452 */ 453 const Encoding* PreferredForInternalEncodingDecl(const nsAString& aEncoding); 454 455 /** 456 * Callback for mFlushTimer. 457 */ 458 static void TimerCallback(nsITimer* aTimer, void* aClosure); 459 460 /** 461 * Parser thread entry point for (maybe) flushing the ops and posting 462 * a flush runnable back on the main thread. 463 */ 464 void TimerFlush(); 465 466 /** 467 * Called when speculation fails. 468 */ 469 void MaybeDisableFutureSpeculation() { mSpeculationFailureCount++; } 470 471 /** 472 * Used to check whether we're getting too many speculation failures and 473 * should just stop trying. The 100 is picked pretty randomly to be not too 474 * small (so most pages are not affected) but small enough that we don't end 475 * up with failed speculations over and over in pathological cases. 476 */ 477 bool IsSpeculationEnabled() { return mSpeculationFailureCount < 100; } 478 479 /** 480 * Dispatch an event to a Quantum DOM main thread-ish thread. 481 * (Not the parser thread.) 482 */ 483 nsresult DispatchToMain(already_AddRefed<nsIRunnable>&& aRunnable); 484 485 /** 486 * Notify any devtools listeners about content newly received for parsing. 487 */ 488 inline void OnNewContent(mozilla::Span<const char16_t> aData); 489 490 /** 491 * Notify any devtools listeners after all parse content has been received. 492 */ 493 inline void OnContentComplete(); 494 495 nsCOMPtr<nsIRequest> mRequest; 496 497 /** 498 * The document title to use if this turns out to be a View Source parser. 499 */ 500 nsCString mViewSourceTitle; 501 502 /** 503 * The Unicode decoder 504 */ 505 mozilla::UniquePtr<mozilla::Decoder> mUnicodeDecoder; 506 507 /** 508 * BOM sniffing state 509 */ 510 eBomState mBomState; 511 512 // encoding-related stuff 513 /** 514 * The source (confidence) of the character encoding in use 515 */ 516 nsCharsetSource mCharsetSource; 517 518 nsCharsetSource mEncodingSwitchSource; 519 520 /** 521 * The character encoding in use 522 */ 523 NotNull<const Encoding*> mEncoding; 524 525 const Encoding* mNeedsEncodingSwitchTo; 526 527 bool mSeenEligibleMetaCharset; 528 529 bool mChardetEof; 530 531 #ifdef DEBUG 532 533 bool mStartedFeedingDetector; 534 535 bool mStartedFeedingDevTools; 536 537 #endif 538 539 /** 540 * Whether reparse is forbidden 541 */ 542 bool mReparseForbidden; 543 544 /** 545 * Whether the Repair Text Encoding menu item was invoked 546 */ 547 bool mForceAutoDetection; 548 549 /** 550 * Whether there was a valid charset parameter on the HTTP layer. 551 */ 552 bool mChannelHadCharset; 553 554 /** 555 * We are in the process of looking for <meta charset> 556 */ 557 bool mLookingForMetaCharset; 558 559 /** 560 * Whether the byte stream started with ASCII <? 561 */ 562 bool mStartsWithLtQuestion; 563 564 /** 565 * If we are viewing XML source and are waiting for a '>' form the network. 566 */ 567 bool mLookingForXmlDeclarationForXmlViewSource; 568 569 /** 570 * Whether template has been pushed or head popped within the first 1024 571 * bytes. 572 */ 573 bool mTemplatePushedOrHeadPopped; 574 575 // Portable parser objects 576 /** 577 * The first buffer in the pending UTF-16 buffer queue 578 */ 579 RefPtr<nsHtml5OwningUTF16Buffer> mFirstBuffer; 580 581 /** 582 * Non-owning pointer to the most recent buffer that contains the most recent 583 * remembered greater-than sign. Used only while mLookingForMetaCharset is 584 * true. While mLookingForMetaCharset is true, mFirstBuffer is not changed and 585 * keeps the whole linked list of buffers alive. This pointer is non-owning to 586 * avoid frequent refcounting. 587 */ 588 nsHtml5OwningUTF16Buffer* mGtBuffer; 589 590 int32_t mGtPos; 591 592 /** 593 * The last buffer in the pending UTF-16 buffer queue 594 */ 595 nsHtml5OwningUTF16Buffer* 596 mLastBuffer; // weak ref; always points to 597 // a buffer of the size 598 // NS_HTML5_STREAM_PARSER_READ_BUFFER_SIZE 599 600 /** 601 * The first buffer of the document if looking for <meta charset> or 602 * nullptr afterwards. 603 */ 604 RefPtr<nsHtml5OwningUTF16Buffer> mFirstBufferOfMetaScan; 605 606 /** 607 * The tree operation executor 608 */ 609 nsHtml5TreeOpExecutor* mExecutor; 610 611 /** 612 * The HTML5 tree builder 613 */ 614 mozilla::UniquePtr<nsHtml5TreeBuilder> mTreeBuilder; 615 616 /** 617 * The HTML5 tokenizer 618 */ 619 mozilla::UniquePtr<nsHtml5Tokenizer> mTokenizer; 620 621 /** 622 * Makes sure the main thread can't mess the tokenizer state while it's 623 * tokenizing. This mutex also protects the current speculation. 624 */ 625 mozilla::Mutex mTokenizerMutex; 626 627 /** 628 * The scoped atom table 629 */ 630 nsHtml5AtomTable mAtomTable; 631 632 /** 633 * The owner parser. 634 */ 635 RefPtr<nsHtml5Parser> mOwner; 636 637 /** 638 * Whether the last character tokenized was a carriage return (for CRLF) 639 */ 640 bool mLastWasCR; 641 642 /** 643 * For tracking stream life cycle 644 */ 645 eHtml5StreamState mStreamState; 646 647 /** 648 * Whether we are speculating. 649 */ 650 bool mSpeculating; 651 652 /** 653 * Whether the tokenizer has reached EOF. (Reset when stream rewinded.) 654 */ 655 bool mAtEOF; 656 657 /** 658 * The speculations. The mutex protects the nsTArray itself. 659 * To access the queue of current speculation, mTokenizerMutex must be 660 * obtained. 661 * The current speculation is the last element 662 */ 663 nsTArray<mozilla::UniquePtr<nsHtml5Speculation>> mSpeculations; 664 mozilla::Mutex mSpeculationMutex; 665 666 /** 667 * Number of times speculation has failed for this parser. 668 */ 669 mozilla::Atomic<uint32_t> mSpeculationFailureCount; 670 671 /** 672 * Number of bytes already buffered into mBufferedBytes. 673 */ 674 uint32_t mNumBytesBuffered; 675 676 nsTArray<mozilla::Buffer<uint8_t>> mBufferedBytes; 677 678 /** 679 * True to terminate early. 680 */ 681 mozilla::Atomic<bool> mTerminated; 682 683 /** 684 * True to release mTokenizerMutex early. 685 */ 686 mozilla::Atomic<bool> mInterrupted; 687 688 /** 689 * The thread this stream parser runs on. 690 */ 691 nsCOMPtr<nsISerialEventTarget> mEventTarget; 692 693 nsCOMPtr<nsIRunnable> mExecutorFlusher; 694 695 nsCOMPtr<nsIRunnable> mLoadFlusher; 696 697 /** 698 * This runnable is distinct from the regular flushers to 699 * signal the intent of encoding commitment without having to 700 * protect mPendingEncodingCommitment in the executer with a 701 * mutex. 702 */ 703 nsCOMPtr<nsIRunnable> mEncodingCommitter; 704 705 /** 706 * The generict detector. 707 */ 708 mozilla::UniquePtr<mozilla::EncodingDetector> mDetector; 709 710 /** 711 * The TLD we're loading from or empty if unknown. 712 */ 713 nsCString mTLD; 714 715 /** 716 * Whether the initial charset source was kCharsetFromParentFrame 717 */ 718 bool mInitialEncodingWasFromParentFrame; 719 720 bool mHasHadErrors; 721 722 bool mDetectorHasSeenNonAscii; 723 724 /** 725 * If true, we are decoding a local file that lacks an encoding 726 * declaration and we are not tokenizing yet. 727 */ 728 bool mDecodingLocalFileWithoutTokenizing; 729 730 /** 731 * Whether we are keeping the incoming bytes. 732 */ 733 bool mBufferingBytes; 734 735 /** 736 * Timer for flushing tree ops once in a while when not speculating. 737 */ 738 nsCOMPtr<nsITimer> mFlushTimer; 739 740 /** 741 * Mutex for protecting access to mFlushTimer (but not for the two 742 * mFlushTimerFoo booleans below). 743 */ 744 mozilla::Mutex mFlushTimerMutex; 745 746 /** 747 * Keeps track whether mFlushTimer has been armed. Unfortunately, 748 * nsITimer doesn't enable querying this from the timer itself. 749 */ 750 bool mFlushTimerArmed; 751 752 /** 753 * False initially and true after the timer has fired at least once. 754 */ 755 bool mFlushTimerEverFired; 756 757 /** 758 * Whether the parser is doing a normal parse, view source or plain text. 759 */ 760 eParserMode mMode; 761 762 /** 763 * If the associated docshell is being watched by the devtools, this is 764 * set to the URI associated with the parse. All parse data is sent to the 765 * devtools, along with this URI. This URI is cleared out after the parse has 766 * been marked as completed. 767 */ 768 nsCOMPtr<nsIURI> mURIToSendToDevtools; 769 770 /** 771 * If content is being sent to the devtools, an encoded UUID for the parser. 772 */ 773 nsString mUUIDForDevtools; 774 775 /** 776 * The browser element's Id for the currently parsed document communicated to 777 * devtools. 778 */ 779 uint64_t mBrowserIdForDevtools; 780 781 /** 782 * The BrowsingContext ID for the currently parsed document communicated to 783 * devtools. 784 */ 785 uint64_t mBrowsingContextIDForDevtools; 786 787 /** 788 * prevent multiple calls to OnStopRequest 789 * This field can be called from multiple threads and is protected by 790 * nsHtml5StreamListener::mDelegateMonitor passed in the OnStopRequest 791 */ 792 bool mOnStopCalled{false}; 793 }; 794 795 #endif // nsHtml5StreamParser_h