mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
9713f3db8b
In order to asynchronously load content scripts that need to run very early in the page load cycle, we need to be able to block further parsing from the document-element-inserted observer, before any page scripts are loaded. Interrupting the flush loop after the document element is inserted allows the observers to run, and temporarily block further parsing if necessary. MozReview-Commit-ID: A6D2T52Mlx4 --HG-- extra : rebase_source : 86f303a0bf298ac32b934290a7f960a2e1bac581
308 lines
7.6 KiB
C++
308 lines
7.6 KiB
C++
/* 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_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(mozilla::FlushType 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(bool* aInterrupted);
|
|
|
|
void PauseDocUpdate(bool* aInterrupted);
|
|
|
|
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
|