tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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