/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsHtml5TreeOpExecutor_h #define nsHtml5TreeOpExecutor_h #include "nsIAtom.h" #include "nsTraceRefcnt.h" #include "nsHtml5TreeOperation.h" #include "nsHtml5SpeculativeLoad.h" #include "nsTArray.h" #include "nsContentSink.h" #include "nsNodeInfoManager.h" #include "nsHtml5DocumentMode.h" #include "nsIScriptElement.h" #include "nsIParser.h" #include "nsAHtml5TreeOpSink.h" #include "nsHtml5TreeOpStage.h" #include "nsIURI.h" #include "nsTHashtable.h" #include "nsHashKeys.h" #include "mozilla/LinkedList.h" #include "nsHtml5DocumentBuilder.h" #include "mozilla/net/ReferrerPolicy.h" class nsHtml5Parser; class nsHtml5StreamParser; class nsIContent; class nsIDocument; class nsHtml5TreeOpExecutor final : public nsHtml5DocumentBuilder, public nsIContentSink, public nsAHtml5TreeOpSink, public mozilla::LinkedListElement<nsHtml5TreeOpExecutor> { friend class nsHtml5FlushLoopGuard; typedef mozilla::net::ReferrerPolicy ReferrerPolicy; public: NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW NS_DECL_ISUPPORTS_INHERITED private: static bool sExternalViewSource; #ifdef DEBUG_NS_HTML5_TREE_OP_EXECUTOR_FLUSH static uint32_t sAppendBatchMaxSize; static uint32_t sAppendBatchSlotsExamined; static uint32_t sAppendBatchExaminations; static uint32_t sLongestTimeOffTheEventLoop; static uint32_t sTimesFlushLoopInterrupted; #endif /** * Whether EOF needs to be suppressed */ bool mSuppressEOF; bool mReadingFromStage; nsTArray<nsHtml5TreeOperation> mOpQueue; nsHtml5StreamParser* mStreamParser; /** * URLs already preloaded/preloading. */ nsTHashtable<nsCStringHashKey> mPreloadedURLs; nsCOMPtr<nsIURI> mSpeculationBaseURI; /** * Speculative referrer policy */ ReferrerPolicy mSpeculationReferrerPolicy; nsCOMPtr<nsIURI> mViewSourceBaseURI; /** * Whether the parser has started */ bool mStarted; nsHtml5TreeOpStage mStage; bool mRunFlushLoopOnStack; bool mCallContinueInterruptedParsingIfEnabled; /** * Whether this executor has already complained about matters related * to character encoding declarations. */ bool mAlreadyComplainedAboutCharset; public: nsHtml5TreeOpExecutor(); protected: virtual ~nsHtml5TreeOpExecutor(); public: // nsIContentSink /** * Unimplemented. For interface compat only. */ NS_IMETHOD WillParse() override; /** * */ NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) override; /** * Emits EOF. */ NS_IMETHOD DidBuildModel(bool aTerminated) override; /** * Forwards to nsContentSink */ NS_IMETHOD WillInterrupt() override; /** * Unimplemented. For interface compat only. */ NS_IMETHOD WillResume() override; /** * Sets the parser. */ NS_IMETHOD SetParser(nsParserBase* aParser) override; /** * No-op for backwards compat. */ virtual void FlushPendingNotifications(mozFlushType aType) override; /** * Don't call. For interface compat only. */ NS_IMETHOD SetDocumentCharset(nsACString& aCharset) override { NS_NOTREACHED("No one should call this."); return NS_ERROR_NOT_IMPLEMENTED; } /** * Returns the document. */ virtual nsISupports *GetTarget() override; virtual void ContinueInterruptedParsingAsync() override; bool IsScriptExecuting() override { return IsScriptExecutingImpl(); } // Not from interface void SetStreamParser(nsHtml5StreamParser* aStreamParser) { mStreamParser = aStreamParser; } void InitializeDocWriteParserState(nsAHtml5TreeBuilderState* aState, int32_t aLine); bool IsScriptEnabled(); virtual nsresult MarkAsBroken(nsresult aReason) override; void StartLayout(); void FlushSpeculativeLoads(); void RunFlushLoop(); nsresult FlushDocumentWrite(); void MaybeSuspend(); void Start(); void NeedsCharsetSwitchTo(const char* aEncoding, int32_t aSource, uint32_t aLineNumber); void MaybeComplainAboutCharset(const char* aMsgId, bool aError, uint32_t aLineNumber); void ComplainAboutBogusProtocolCharset(nsIDocument* aDoc); bool IsComplete() { return !mParser; } bool HasStarted() { return mStarted; } bool IsFlushing() { return mFlushState >= eInFlush; } #ifdef DEBUG bool IsInFlushLoop() { return mRunFlushLoopOnStack; } #endif void RunScript(nsIContent* aScriptElement); /** * Flush the operations from the tree operations from the argument * queue unconditionally. (This is for the main thread case.) */ virtual void MoveOpsFrom(nsTArray<nsHtml5TreeOperation>& aOpQueue) override; nsHtml5TreeOpStage* GetStage() { return &mStage; } void StartReadingFromStage() { mReadingFromStage = true; } void StreamEnded(); #ifdef DEBUG void AssertStageEmpty() { mStage.AssertEmpty(); } #endif nsIURI* GetViewSourceBaseURI(); void PreloadScript(const nsAString& aURL, const nsAString& aCharset, const nsAString& aType, const nsAString& aCrossOrigin, const nsAString& aIntegrity, bool aScriptFromHead); void PreloadStyle(const nsAString& aURL, const nsAString& aCharset, const nsAString& aCrossOrigin, const nsAString& aIntegrity); void PreloadImage(const nsAString& aURL, const nsAString& aCrossOrigin, const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aImageReferrerPolicy); void PreloadOpenPicture(); void PreloadEndPicture(); void PreloadPictureSource(const nsAString& aSrcset, const nsAString& aSizes, const nsAString& aType, const nsAString& aMedia); void SetSpeculationBase(const nsAString& aURL); void SetSpeculationReferrerPolicy(ReferrerPolicy aReferrerPolicy); void SetSpeculationReferrerPolicy(const nsAString& aReferrerPolicy); void AddSpeculationCSP(const nsAString& aCSP); void AddBase(const nsAString& aURL); static void InitializeStatics(); private: nsHtml5Parser* GetParser(); bool IsExternalViewSource(); /** * Get a nsIURI for an nsString if the URL hasn't been preloaded yet. */ already_AddRefed<nsIURI> ConvertIfNotPreloadedYet(const nsAString& aURL); /** * The base URI we would use for current preload operations */ nsIURI* BaseURIForPreload(); /** * Returns true if we haven't preloaded this URI yet, and adds it to the * list of preloaded URIs */ bool ShouldPreloadURI(nsIURI *aURI); }; #endif // nsHtml5TreeOpExecutor_h