summaryrefslogtreecommitdiffstats
path: root/dom/base/Document.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/Document.h')
-rw-r--r--dom/base/Document.h5564
1 files changed, 5564 insertions, 0 deletions
diff --git a/dom/base/Document.h b/dom/base/Document.h
new file mode 100644
index 0000000000..6a2bd55a9c
--- /dev/null
+++ b/dom/base/Document.h
@@ -0,0 +1,5564 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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 mozilla_dom_Document_h___
+#define mozilla_dom_Document_h___
+
+#include <bitset>
+#include <cstddef>
+#include <cstdint>
+#include <new>
+#include <utility>
+#include "ErrorList.h"
+#include "MainThreadUtils.h"
+#include "Units.h"
+#include "imgIRequest.h"
+#include "js/RootingAPI.h"
+#include "js/friend/DOMProxy.h"
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/BasicEvents.h"
+#include "mozilla/BitSet.h"
+#include "mozilla/OriginTrials.h"
+#include "mozilla/ContentBlockingNotifier.h"
+#include "mozilla/CORSMode.h"
+#include "mozilla/CallState.h"
+#include "mozilla/FlushType.h"
+#include "mozilla/FunctionRef.h"
+#include "mozilla/HashTable.h"
+#include "mozilla/LinkedList.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/MozPromise.h"
+#include "mozilla/NotNull.h"
+#include "mozilla/PointerLockManager.h"
+#include "mozilla/PreloadService.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/Result.h"
+#include "mozilla/SegmentedVector.h"
+#include "mozilla/ServoStyleSet.h"
+#include "mozilla/StorageAccessAPIHelper.h"
+#include "mozilla/TimeStamp.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/UseCounter.h"
+#include "mozilla/WeakPtr.h"
+#include "mozilla/css/StylePreloadKind.h"
+#include "mozilla/dom/AnimationFrameProvider.h"
+#include "mozilla/dom/DocumentOrShadowRoot.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/EventTarget.h"
+#include "mozilla/dom/Nullable.h"
+#include "mozilla/dom/RadioGroupContainer.h"
+#include "mozilla/dom/TreeOrderedArray.h"
+#include "mozilla/dom/ViewportMetaData.h"
+#include "mozilla/dom/LargestContentfulPaint.h"
+#include "mozilla/dom/UserActivation.h"
+#include "mozilla/dom/WakeLockBinding.h"
+#include "mozilla/glean/GleanMetrics.h"
+#include "nsAtom.h"
+#include "nsCOMArray.h"
+#include "nsCOMPtr.h"
+#include "nsClassHashtable.h"
+#include "nsCompatibility.h"
+#include "nsContentListDeclarations.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsTHashMap.h"
+#include "nsDebug.h"
+#include "nsGkAtoms.h"
+#include "nsHashKeys.h"
+#include "nsIChannel.h"
+#include "nsIChannelEventSink.h"
+#include "nsID.h"
+#include "nsIDocumentViewer.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsILoadContext.h"
+#include "nsILoadGroup.h"
+#include "nsILoadInfo.h"
+#include "nsINode.h"
+#include "nsIObserver.h"
+#include "nsIParser.h"
+#include "nsIPrincipal.h"
+#include "nsIProgressEventSink.h"
+#include "nsIReferrerInfo.h"
+#include "nsIRequestObserver.h"
+#include "nsIScriptObjectPrincipal.h"
+#include "nsIStreamListener.h"
+#include "nsISupports.h"
+#include "nsISupportsUtils.h"
+#include "nsITransportSecurityInfo.h"
+#include "nsIURI.h"
+#include "nsIWeakReferenceUtils.h"
+#include "nsLiteralString.h"
+#include "nsPIDOMWindow.h"
+#include "nsPropertyTable.h"
+#include "nsRefPtrHashtable.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsTHashSet.h"
+#include "nsTLiteralString.h"
+#include "nsTObserverArray.h"
+#include "nsThreadUtils.h"
+#include "nsURIHashKey.h"
+#include "nsViewportInfo.h"
+#include "nsWeakReference.h"
+#include "nsWindowSizes.h"
+#include "nsXULElement.h"
+#include "nscore.h"
+
+// XXX We need to include this here to ensure that DefaultDeleter for Servo
+// types is specialized before the template is instantiated. Probably, this
+// should be included at some other place already that's generated by cbindgen.
+#include "mozilla/ServoBindingTypes.h"
+
+// windows.h #defines CreateEvent
+#ifdef CreateEvent
+# undef CreateEvent
+#endif
+
+#ifdef MOZILLA_INTERNAL_API
+# include "mozilla/dom/DocumentBinding.h"
+#else
+namespace mozilla {
+namespace dom {
+class ElementCreationOptionsOrString;
+} // namespace dom
+} // namespace mozilla
+#endif // MOZILLA_INTERNAL_API
+
+class InfallibleAllocPolicy;
+class JSObject;
+class JSTracer;
+class PLDHashTable;
+class gfxUserFontSet;
+class mozIDOMWindowProxy;
+class nsCachableElementsByNameNodeList;
+class nsCommandManager;
+class nsContentList;
+class nsCycleCollectionTraversalCallback;
+class nsDOMCaretPosition;
+class nsDOMNavigationTiming;
+class nsDocShell;
+class nsFrameLoader;
+class nsFrameLoaderOwner;
+class nsGenericHTMLElement;
+class nsGlobalWindowInner;
+class nsHTMLDocument;
+class nsHtml5TreeOpExecutor;
+class nsIAppWindow;
+class nsIAsyncVerifyRedirectCallback;
+class nsIBFCacheEntry;
+class nsIContent;
+class nsIContentSecurityPolicy;
+class nsIContentSink;
+class nsICookieJarSettings;
+class nsIDOMXULCommandDispatcher;
+class nsIDocShell;
+class nsIDocShellTreeItem;
+class nsIDocumentEncoder;
+class nsIDocumentObserver;
+class nsIEventTarget;
+class nsIFrame;
+class nsIGlobalObject;
+class nsIHTMLCollection;
+class nsIInputStream;
+class nsILayoutHistoryState;
+class nsIObjectLoadingContent;
+class nsIPermissionDelegateHandler;
+class nsIRadioVisitor;
+class nsIRequest;
+class nsIRunnable;
+class nsIScriptGlobalObject;
+class nsISecurityConsoleMessage;
+class nsISerialEventTarget;
+class nsIStructuredCloneContainer;
+class nsIVariant;
+class nsNodeInfoManager;
+class nsPIWindowRoot;
+class nsPresContext;
+class nsRange;
+class nsSimpleContentList;
+class nsTextNode;
+class nsViewManager;
+class nsXULPrototypeDocument;
+struct JSContext;
+struct nsFont;
+
+namespace mozilla {
+class AbstractThread;
+class AttributeStyles;
+class CanvasUsage;
+class StyleSheet;
+class EditorBase;
+class EditorCommand;
+class Encoding;
+class ErrorResult;
+class EventListenerManager;
+class FullscreenExit;
+class FullscreenRequest;
+class HTMLEditor;
+struct LangGroupFontPrefs;
+class PermissionDelegateHandler;
+class PresShell;
+class ScrollTimelineAnimationTracker;
+class ServoStyleSet;
+enum class StyleOrigin : uint8_t;
+class SMILAnimationController;
+enum class StyleCursorKind : uint8_t;
+class SVGContextPaint;
+enum class ColorScheme : uint8_t;
+enum class StyleRuleChangeKind : uint32_t;
+struct StyleUseCounters;
+template <typename>
+class OwningNonNull;
+struct URLExtraData;
+
+namespace css {
+class Loader;
+class ImageLoader;
+class Rule;
+} // namespace css
+
+namespace dom {
+class AnonymousContent;
+class Attr;
+class XULBroadcastManager;
+class XULPersist;
+class BrowserBridgeChild;
+class ChromeObserver;
+class ClientInfo;
+class ClientState;
+class CDATASection;
+class Comment;
+class CSSImportRule;
+class DocumentL10n;
+class DocumentFragment;
+class DocumentTimeline;
+class DocumentType;
+class DOMImplementation;
+class DOMIntersectionObserver;
+class DOMStringList;
+class Event;
+class EventListener;
+struct FailedCertSecurityInfo;
+class FeaturePolicy;
+class FontFaceSet;
+class FrameRequestCallback;
+class ImageTracker;
+class HighlightRegistry;
+class HTMLAllCollection;
+class HTMLBodyElement;
+class HTMLInputElement;
+class HTMLMetaElement;
+class HTMLDialogElement;
+class HTMLSharedElement;
+class HTMLImageElement;
+struct LifecycleCallbackArgs;
+class Link;
+class Location;
+class MediaQueryList;
+struct NetErrorInfo;
+class NodeFilter;
+class NodeInfo;
+class NodeIterator;
+enum class OrientationType : uint8_t;
+class ProcessingInstruction;
+class Promise;
+class ScriptLoader;
+class Selection;
+class ServiceWorkerDescriptor;
+class ShadowRoot;
+class SVGDocument;
+class SVGElement;
+class SVGSVGElement;
+class SVGUseElement;
+class ImageDocument;
+class Touch;
+class TouchList;
+class TreeWalker;
+enum class ViewportFitType : uint8_t;
+class WakeLockSentinel;
+class WindowContext;
+class WindowGlobalChild;
+class WindowProxyHolder;
+struct Wireframe;
+class WorkerDocumentListener;
+class XPathEvaluator;
+class XPathExpression;
+class XPathNSResolver;
+class XPathResult;
+class BrowsingContext;
+
+class nsUnblockOnloadEvent;
+
+template <typename, typename>
+class CallbackObjectHolder;
+
+enum class CallerType : uint32_t;
+
+enum BFCacheStatus {
+ NOT_ALLOWED = 1 << 0, // Status 0
+ EVENT_HANDLING_SUPPRESSED = 1 << 1, // Status 1
+ SUSPENDED = 1 << 2, // Status 2
+ UNLOAD_LISTENER = 1 << 3, // Status 3
+ REQUEST = 1 << 4, // Status 4
+ ACTIVE_GET_USER_MEDIA = 1 << 5, // Status 5
+ ACTIVE_PEER_CONNECTION = 1 << 6, // Status 6
+ CONTAINS_EME_CONTENT = 1 << 7, // Status 7
+ CONTAINS_MSE_CONTENT = 1 << 8, // Status 8
+ HAS_ACTIVE_SPEECH_SYNTHESIS = 1 << 9, // Status 9
+ HAS_USED_VR = 1 << 10, // Status 10
+ CONTAINS_REMOTE_SUBFRAMES = 1 << 11, // Status 11
+ NOT_ONLY_TOPLEVEL_IN_BCG = 1 << 12, // Status 12
+ ABOUT_PAGE = 1 << 13, // Status 13
+ RESTORING = 1 << 14, // Status 14
+ BEFOREUNLOAD_LISTENER = 1 << 15, // Status 15
+ ACTIVE_LOCK = 1 << 16, // Status 16
+ ACTIVE_WEBTRANSPORT = 1 << 17, // Status 17
+};
+
+} // namespace dom
+} // namespace mozilla
+
+namespace mozilla::net {
+class ChannelEventQueue;
+class EarlyHintConnectArgs;
+} // namespace mozilla::net
+
+// Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs
+#define NS_IDOCUMENT_IID \
+ { \
+ 0xce1f7627, 0x7109, 0x4977, { \
+ 0xba, 0x77, 0x49, 0x0f, 0xfd, 0xe0, 0x7a, 0xaa \
+ } \
+ }
+
+namespace mozilla::dom {
+
+class Document;
+class DOMStyleSheetSetList;
+class ResizeObserver;
+class ResizeObserverController;
+class PostMessageEvent;
+
+#define DEPRECATED_OPERATION(_op) e##_op,
+enum class DeprecatedOperations : uint16_t {
+#include "nsDeprecatedOperationList.h"
+ eDeprecatedOperationCount
+};
+#undef DEPRECATED_OPERATION
+
+class ExternalResourceMap {
+ using SubDocEnumFunc = FunctionRef<CallState(Document&)>;
+
+ public:
+ /**
+ * A class that represents an external resource load that has begun but
+ * doesn't have a document yet. Observers can be registered on this object,
+ * and will be notified after the document is created. Observers registered
+ * after the document has been created will NOT be notified. When observers
+ * are notified, the subject will be the newly-created document, the topic
+ * will be "external-resource-document-created", and the data will be null.
+ * If document creation fails for some reason, observers will still be
+ * notified, with a null document pointer.
+ */
+ class ExternalResourceLoad : public nsISupports {
+ public:
+ virtual ~ExternalResourceLoad() = default;
+
+ void AddObserver(nsIObserver* aObserver) {
+ MOZ_ASSERT(aObserver, "Must have observer");
+ mObservers.AppendElement(aObserver);
+ }
+
+ const nsTArray<nsCOMPtr<nsIObserver>>& Observers() { return mObservers; }
+
+ protected:
+ AutoTArray<nsCOMPtr<nsIObserver>, 8> mObservers;
+ };
+
+ ExternalResourceMap();
+
+ /**
+ * Request an external resource document. This does exactly what
+ * Document::RequestExternalResource is documented to do.
+ */
+ Document* RequestResource(nsIURI* aURI, nsIReferrerInfo* aReferrerInfo,
+ nsINode* aRequestingNode,
+ Document* aDisplayDocument,
+ ExternalResourceLoad** aPendingLoad);
+
+ /**
+ * Enumerate the resource documents. See
+ * Document::EnumerateExternalResources.
+ */
+ void EnumerateResources(SubDocEnumFunc aCallback);
+
+ /**
+ * Traverse ourselves for cycle-collection
+ */
+ void Traverse(nsCycleCollectionTraversalCallback* aCallback) const;
+
+ /**
+ * Shut ourselves down (used for cycle-collection unlink), as well
+ * as for document destruction.
+ */
+ void Shutdown() {
+ mPendingLoads.Clear();
+ mMap.Clear();
+ mHaveShutDown = true;
+ }
+
+ bool HaveShutDown() const { return mHaveShutDown; }
+
+ // Needs to be public so we can traverse them sanely
+ struct ExternalResource {
+ ~ExternalResource();
+ RefPtr<Document> mDocument;
+ nsCOMPtr<nsIDocumentViewer> mViewer;
+ nsCOMPtr<nsILoadGroup> mLoadGroup;
+ };
+
+ // Hide all our viewers
+ void HideViewers();
+
+ // Show all our viewers
+ void ShowViewers();
+
+ protected:
+ class PendingLoad : public ExternalResourceLoad, public nsIStreamListener {
+ ~PendingLoad() = default;
+
+ public:
+ explicit PendingLoad(Document* aDisplayDocument)
+ : mDisplayDocument(aDisplayDocument) {}
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSIREQUESTOBSERVER
+
+ /**
+ * Start aURI loading. This will perform the necessary security checks and
+ * so forth.
+ */
+ nsresult StartLoad(nsIURI* aURI, nsIReferrerInfo* aReferrerInfo,
+ nsINode* aRequestingNode);
+ /**
+ * Set up an nsIDocumentViewer based on aRequest. This is guaranteed to
+ * put null in *aViewer and *aLoadGroup on all failures.
+ */
+ nsresult SetupViewer(nsIRequest* aRequest, nsIDocumentViewer** aViewer,
+ nsILoadGroup** aLoadGroup);
+
+ private:
+ RefPtr<Document> mDisplayDocument;
+ nsCOMPtr<nsIStreamListener> mTargetListener;
+ nsCOMPtr<nsIURI> mURI;
+ };
+ friend class PendingLoad;
+
+ class LoadgroupCallbacks final : public nsIInterfaceRequestor {
+ ~LoadgroupCallbacks() = default;
+
+ public:
+ explicit LoadgroupCallbacks(nsIInterfaceRequestor* aOtherCallbacks)
+ : mCallbacks(aOtherCallbacks) {}
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIINTERFACEREQUESTOR
+ private:
+ // The only reason it's safe to hold a strong ref here without leaking is
+ // that the notificationCallbacks on a loadgroup aren't the docshell itself
+ // but a shim that holds a weak reference to the docshell.
+ nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
+
+ // Use shims for interfaces that docshell implements directly so that we
+ // don't hand out references to the docshell. The shims should all allow
+ // getInterface back on us, but other than that each one should only
+ // implement one interface.
+
+ // XXXbz I wish we could just derive the _allcaps thing from _i
+#define DECL_SHIM(_i, _allcaps) \
+ class _i##Shim final : public nsIInterfaceRequestor, public _i { \
+ ~_i##Shim() {} \
+ \
+ public: \
+ _i##Shim(nsIInterfaceRequestor* aIfreq, _i* aRealPtr) \
+ : mIfReq(aIfreq), mRealPtr(aRealPtr) { \
+ NS_ASSERTION(mIfReq, "Expected non-null here"); \
+ NS_ASSERTION(mRealPtr, "Expected non-null here"); \
+ } \
+ NS_DECL_ISUPPORTS \
+ NS_FORWARD_NSIINTERFACEREQUESTOR(mIfReq->) \
+ NS_FORWARD_##_allcaps(mRealPtr->) private \
+ : nsCOMPtr<nsIInterfaceRequestor> mIfReq; \
+ nsCOMPtr<_i> mRealPtr; \
+ };
+
+ DECL_SHIM(nsILoadContext, NSILOADCONTEXT)
+ DECL_SHIM(nsIProgressEventSink, NSIPROGRESSEVENTSINK)
+ DECL_SHIM(nsIChannelEventSink, NSICHANNELEVENTSINK)
+#undef DECL_SHIM
+ };
+
+ /**
+ * Add an ExternalResource for aURI. aViewer and aLoadGroup might be null
+ * when this is called if the URI didn't result in an XML document. This
+ * function makes sure to remove the pending load for aURI, if any, from our
+ * hashtable, and to notify its observers, if any.
+ */
+ nsresult AddExternalResource(nsIURI* aURI, nsIDocumentViewer* aViewer,
+ nsILoadGroup* aLoadGroup,
+ Document* aDisplayDocument);
+
+ nsClassHashtable<nsURIHashKey, ExternalResource> mMap;
+ nsRefPtrHashtable<nsURIHashKey, PendingLoad> mPendingLoads;
+ bool mHaveShutDown;
+};
+
+// The current status for a preload.
+enum class SheetPreloadStatus : uint8_t {
+ // There's no need to preload anything, the sheet is already in-memory.
+ AlreadyComplete,
+ // The load is in-progress. There's no guarantee that a load was started, it
+ // could be coalesced with other redundant loads.
+ InProgress,
+ // Something went wrong, and we errored out.
+ Errored,
+};
+
+//----------------------------------------------------------------------
+
+// Document interface. This is implemented by all document objects in
+// Gecko.
+class Document : public nsINode,
+ public DocumentOrShadowRoot,
+ public nsSupportsWeakReference,
+ public nsIScriptObjectPrincipal,
+ public SupportsWeakPtr {
+ friend class DocumentOrShadowRoot;
+
+ protected:
+ explicit Document(const char* aContentType);
+ virtual ~Document();
+
+ Document(const Document&) = delete;
+ Document& operator=(const Document&) = delete;
+
+ public:
+ using ExternalResourceLoad = dom::ExternalResourceMap::ExternalResourceLoad;
+ using ReferrerPolicyEnum = dom::ReferrerPolicy;
+ using AdoptedStyleSheetCloneCache =
+ nsRefPtrHashtable<nsPtrHashKey<const StyleSheet>, StyleSheet>;
+
+ // nsINode overrides the new operator for DOM Arena allocation.
+ // to use the default one, we need to bring it back again
+ void* operator new(size_t aSize) { return ::operator new(aSize); }
+
+ /**
+ * Called when XPCOM shutdown.
+ */
+ static void Shutdown();
+
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID)
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_IMETHOD_(void) DeleteCycleCollectable() override;
+
+ NS_DECL_ADDSIZEOFEXCLUDINGTHIS
+
+ NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Document,
+ nsINode)
+
+#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \
+ do { \
+ for (RefPtr obs : mObservers.ForwardRange()) { \
+ if (obs->IsCallbackEnabled(nsIMutationObserver::k##func_)) { \
+ obs->func_ params_; \
+ } \
+ } \
+ /* FIXME(emilio): Apparently we can keep observing from the BFCache? That \
+ looks bogus. */ \
+ if (PresShell* presShell = GetObservingPresShell()) { \
+ presShell->func_ params_; \
+ } \
+ } while (0)
+
+ nsIPrincipal* EffectiveCookiePrincipal() const;
+
+ nsIPrincipal* EffectiveStoragePrincipal() const;
+
+ // nsIScriptObjectPrincipal
+ nsIPrincipal* GetPrincipal() final { return NodePrincipal(); }
+
+ nsIPrincipal* GetEffectiveCookiePrincipal() final {
+ return EffectiveCookiePrincipal();
+ }
+
+ nsIPrincipal* GetEffectiveStoragePrincipal() final {
+ return EffectiveStoragePrincipal();
+ }
+
+ // You should probably not be using this function, since it performs no checks
+ // to ensure that the partitioned principal should really be used here. It is
+ // only designed to be used in very specific circumstances, such as when
+ // inheriting the document/storage principal.
+ nsIPrincipal* PartitionedPrincipal() final { return mPartitionedPrincipal; }
+
+ // Gets the appropriate principal to check the URI against a blocklist /
+ // allowlist.
+ nsIPrincipal* GetPrincipalForPrefBasedHacks() const;
+
+ void ClearActiveCookieAndStoragePrincipals() {
+ mActiveStoragePrincipal = nullptr;
+ mActiveCookiePrincipal = nullptr;
+ }
+
+ // EventTarget
+ void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
+ EventListenerManager* GetOrCreateListenerManager() override;
+ EventListenerManager* GetExistingListenerManager() const override;
+
+ // This helper class must be set when we dispatch beforeunload and unload
+ // events in order to avoid unterminate sync XHRs.
+ class MOZ_RAII PageUnloadingEventTimeStamp {
+ RefPtr<Document> mDocument;
+ bool mSet;
+
+ public:
+ explicit PageUnloadingEventTimeStamp(Document* aDocument)
+ : mDocument(aDocument), mSet(false) {
+ MOZ_ASSERT(aDocument);
+ if (mDocument->mPageUnloadingEventTimeStamp.IsNull()) {
+ mDocument->SetPageUnloadingEventTimeStamp();
+ mSet = true;
+ }
+ }
+
+ ~PageUnloadingEventTimeStamp() {
+ if (mSet) {
+ mDocument->CleanUnloadEventsTimeStamp();
+ }
+ }
+ };
+
+ /**
+ * Let the document know that we're starting to load data into it.
+ * @param aCommand The parser command. Must not be null.
+ * XXXbz It's odd to have that here.
+ * @param aChannel The channel the data will come from. The channel must be
+ * able to report its Content-Type.
+ * @param aLoadGroup The loadgroup this document should use from now on.
+ * Note that the document might not be the only thing using
+ * this loadgroup.
+ * @param aContainer The container this document is in. This may be null.
+ * XXXbz maybe we should make it more explicit (eg make the
+ * container an nsIWebNavigation or nsIDocShell or
+ * something)?
+ * @param [out] aDocListener the listener to pump data from the channel into.
+ * Generally this will be the parser this document
+ * sets up, or some sort of data-handler for media
+ * documents.
+ * @param aReset whether the document should call Reset() on itself. If this
+ * is false, the document will NOT set its principal to the
+ * channel's owner, will not clear any event listeners that are
+ * already set on it, etc.
+ *
+ * Once this has been called, the document will return false for
+ * MayStartLayout() until SetMayStartLayout(true) is called on it. Making
+ * sure this happens is the responsibility of the caller of
+ * StartDocumentLoad().
+ *
+ * This function has an implementation, and does some setup, but does NOT set
+ * *aDocListener; this is the job of subclasses.
+ */
+ virtual nsresult StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
+ nsILoadGroup* aLoadGroup,
+ nsISupports* aContainer,
+ nsIStreamListener** aDocListener,
+ bool aReset) = 0;
+ void StopDocumentLoad();
+
+ virtual void SetSuppressParserErrorElement(bool aSuppress) {}
+ virtual bool SuppressParserErrorElement() { return false; }
+
+ virtual void SetSuppressParserErrorConsoleMessages(bool aSuppress) {}
+ virtual bool SuppressParserErrorConsoleMessages() { return false; }
+
+ // nsINode
+ void InsertChildBefore(nsIContent* aKid, nsIContent* aBeforeThis,
+ bool aNotify, ErrorResult& aRv) override;
+ void RemoveChildNode(nsIContent* aKid, bool aNotify) final;
+ nsresult Clone(dom::NodeInfo* aNodeInfo, nsINode** aResult) const override {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+ nsresult CloneDocHelper(Document* clone) const;
+
+ Document* GetLatestStaticClone() const { return mLatestStaticClone; }
+
+ /**
+ * Signal that the document title may have changed
+ * (see Document::GetTitle).
+ * @param aBoundTitleElement true if an HTML or SVG <title> element
+ * has just been bound to the document.
+ */
+ virtual void NotifyPossibleTitleChange(bool aBoundTitleElement);
+
+ /**
+ * Return the URI for the document. May return null. If it ever stops being
+ * able to return null, we can make sure nsINode::GetBaseURI/GetBaseURIObject
+ * also never return null.
+ *
+ * The value returned corresponds to the "document's address" in
+ * HTML5. As such, it may change over the lifetime of the document, for
+ * instance as a result of the user navigating to a fragment identifier on
+ * the page, or as a result to a call to pushState() or replaceState().
+ *
+ * https://html.spec.whatwg.org/multipage/dom.html#the-document%27s-address
+ */
+ nsIURI* GetDocumentURI() const { return mDocumentURI; }
+
+ /**
+ * Return the original URI of the document. This is the same as the
+ * document's URI unless that has changed from its original value (for
+ * example, due to history.pushState() or replaceState() being invoked on the
+ * document).
+ *
+ * This method corresponds to the "creation URL" in HTML5 and, once set,
+ * doesn't change over the lifetime of the document.
+ *
+ * https://html.spec.whatwg.org/multipage/webappapis.html#creation-url
+ */
+ nsIURI* GetOriginalURI() const { return mOriginalURI; }
+
+ /**
+ * Return the base domain of the document. This has been computed using
+ * mozIThirdPartyUtil::GetBaseDomain() and can be used for third-party
+ * checks. When the URI of the document changes, this value is recomputed.
+ */
+ nsCString GetBaseDomain() const { return mBaseDomain; }
+
+ /**
+ * Set the URI for the document. This also sets the document's original URI,
+ * if it's null.
+ */
+ void SetDocumentURI(nsIURI* aURI);
+
+ /**
+ * Set the URI for the document loaded via XHR, when accessed from
+ * chrome privileged script.
+ */
+ void SetChromeXHRDocURI(nsIURI* aURI) { mChromeXHRDocURI = aURI; }
+
+ /**
+ * Set the base URI for the document loaded via XHR, when accessed from
+ * chrome privileged script.
+ */
+ void SetChromeXHRDocBaseURI(nsIURI* aURI) { mChromeXHRDocBaseURI = aURI; }
+
+ /**
+ * The CSP in general is stored in the ClientInfo, but we also cache
+ * the CSP on the document so subresources loaded within a document
+ * can query that cached CSP instead of having to deserialize the CSP
+ * from the Client.
+ *
+ * Please note that at the time of CSP parsing the Client is not
+ * available yet, hence we sync CSP of document and Client when the
+ * Client becomes available within nsGlobalWindowInner::EnsureClientSource().
+ */
+ nsIContentSecurityPolicy* GetCsp() const;
+ void SetCsp(nsIContentSecurityPolicy* aCSP);
+
+ nsIContentSecurityPolicy* GetPreloadCsp() const;
+ void SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP);
+
+ void GetCspJSON(nsString& aJSON);
+
+ /**
+ * Set referrer policy and upgrade-insecure-requests flags
+ */
+ void ApplySettingsFromCSP(bool aSpeculative);
+
+ already_AddRefed<nsIParser> CreatorParserOrNull() {
+ nsCOMPtr<nsIParser> parser = mParser;
+ return parser.forget();
+ }
+
+ /**
+ * ReferrerInfo getter for Document.webidl.
+ */
+ nsIReferrerInfo* ReferrerInfo() const { return GetReferrerInfo(); }
+
+ nsIReferrerInfo* GetReferrerInfo() const { return mReferrerInfo; }
+
+ nsIReferrerInfo* GetPreloadReferrerInfo() const {
+ return mPreloadReferrerInfo;
+ }
+ /**
+ * Return the referrer policy of the document. Return "default" if there's no
+ * valid meta referrer tag found in the document.
+ * Referrer policy should be inherited from parent if the iframe is srcdoc
+ */
+ ReferrerPolicyEnum GetReferrerPolicy() const;
+
+ /**
+ * GetReferrerPolicy() for Document.webidl.
+ */
+ ReferrerPolicyEnum ReferrerPolicy() const { return GetReferrerPolicy(); }
+
+ /**
+ * If true, this flag indicates that all mixed content subresource
+ * loads for this document (and also embeded browsing contexts) will
+ * be blocked.
+ */
+ bool GetBlockAllMixedContent(bool aPreload) const {
+ if (aPreload) {
+ return mBlockAllMixedContentPreloads;
+ }
+ return mBlockAllMixedContent;
+ }
+
+ /**
+ * If true, this flag indicates that all subresource loads for this
+ * document need to be upgraded from http to https.
+ * This flag becomes true if the CSP of the document itself, or any
+ * of the document's ancestors up to the toplevel document makes use
+ * of the CSP directive 'upgrade-insecure-requests'.
+ */
+ bool GetUpgradeInsecureRequests(bool aPreload) const {
+ if (aPreload) {
+ return mUpgradeInsecurePreloads;
+ }
+ return mUpgradeInsecureRequests;
+ }
+
+ void SetReferrerInfo(nsIReferrerInfo*);
+
+ /*
+ * Referrer policy from <meta name="referrer" content=`policy`>
+ * will have higher priority than referrer policy from Referrer-Policy
+ * header. So override the old ReferrerInfo if we get one from meta
+ */
+ void UpdateReferrerInfoFromMeta(const nsAString& aMetaReferrer,
+ bool aPreload);
+
+ /**
+ * Set the principals responsible for this document. Chances are, you do not
+ * want to be using this.
+ */
+ void SetPrincipals(nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal);
+
+ /**
+ * Returns true if exempt from HTTPS-Only Mode upgrade.
+ */
+ uint32_t HttpsOnlyStatus() const { return mHttpsOnlyStatus; }
+
+ /**
+ * Return the LoadGroup for the document. May return null.
+ */
+ already_AddRefed<nsILoadGroup> GetDocumentLoadGroup() const {
+ nsCOMPtr<nsILoadGroup> group = do_QueryReferent(mDocumentLoadGroup);
+ return group.forget();
+ }
+
+ /**
+ * Return the fallback base URL for this document, as defined in the HTML
+ * specification. Note that this can return null if there is no document URI.
+ *
+ * XXXbz: This doesn't implement the bits for about:blank yet.
+ */
+ nsIURI* GetFallbackBaseURI() const {
+ if (mIsSrcdocDocument && mParentDocument) {
+ return mParentDocument->GetDocBaseURI();
+ }
+ return mDocumentURI;
+ }
+
+ /**
+ * Return the referrer from document URI as defined in the Referrer Policy
+ * specification.
+ * https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
+ * While document is an iframe srcdoc document, let document be document's
+ * browsing context's browsing context container's node document.
+ * Then referrer should be document's URL
+ */
+
+ nsIURI* GetDocumentURIAsReferrer() const {
+ if (mIsSrcdocDocument && mParentDocument) {
+ return mParentDocument->GetDocumentURIAsReferrer();
+ }
+ return mDocumentURI;
+ }
+
+ /**
+ * Return the base URI for relative URIs in the document (the document uri
+ * unless it's overridden by SetBaseURI, HTML <base> tags, etc.). The
+ * returned URI could be null if there is no document URI. If the document is
+ * a srcdoc document and has no explicit base URL, return the parent
+ * document's base URL.
+ */
+ nsIURI* GetDocBaseURI() const {
+ if (mDocumentBaseURI) {
+ return mDocumentBaseURI;
+ }
+ return GetFallbackBaseURI();
+ }
+
+ nsIURI* GetBaseURI(bool aTryUseXHRDocBaseURI = false) const final;
+
+ void SetBaseURI(nsIURI* aURI);
+
+ /**
+ * Resolves a URI based on the document's base URI.
+ */
+ Result<OwningNonNull<nsIURI>, nsresult> ResolveWithBaseURI(
+ const nsAString& aURI);
+
+ /**
+ * Return the URL data which style system needs for resolving url value.
+ * This method attempts to use the cached object in mCachedURLData, but
+ * if the base URI, document URI, or principal has changed since last
+ * call to this function, or the function is called the first time for
+ * the document, a new one is created.
+ */
+ URLExtraData* DefaultStyleAttrURLData();
+ nsIReferrerInfo* ReferrerInfoForInternalCSSAndSVGResources();
+
+ /**
+ * Get/Set the base target of a link in a document.
+ */
+ void GetBaseTarget(nsAString& aBaseTarget) const {
+ aBaseTarget = mBaseTarget;
+ }
+
+ void SetBaseTarget(const nsString& aBaseTarget) { mBaseTarget = aBaseTarget; }
+
+ /**
+ * Return a standard name for the document's character set.
+ */
+ NotNull<const Encoding*> GetDocumentCharacterSet() const {
+ return mCharacterSet;
+ }
+
+ /**
+ * Set the document's character encoding.
+ */
+ void SetDocumentCharacterSet(NotNull<const Encoding*> aEncoding);
+
+ int32_t GetDocumentCharacterSetSource() const { return mCharacterSetSource; }
+
+ // This method MUST be called before SetDocumentCharacterSet if
+ // you're planning to call both.
+ void SetDocumentCharacterSetSource(int32_t aCharsetSource) {
+ mCharacterSetSource = aCharsetSource;
+ }
+
+ /**
+ * Get the Content-Type of this document.
+ */
+ void GetContentType(nsAString& aContentType);
+
+ /**
+ * Set the Content-Type of this document.
+ */
+ void SetContentType(const nsACString& aContentType);
+
+ /**
+ * Return the language of this document, or null if not set.
+ */
+ nsAtom* GetContentLanguage() const { return mContentLanguage.get(); }
+
+ void GetContentLanguageForBindings(DOMString&) const;
+
+ // The states BidiEnabled and MathMLEnabled should persist across multiple
+ // views (screen, print) of the same document.
+
+ /**
+ * Check if the document contains bidi data.
+ * If so, we have to apply the Unicode Bidi Algorithm.
+ */
+ bool GetBidiEnabled() const { return mBidiEnabled; }
+
+ /**
+ * Indicate the document contains bidi data.
+ * Currently, we cannot disable bidi, because once bidi is enabled,
+ * it affects a frame model irreversibly, and plays even though
+ * the document no longer contains bidi data.
+ */
+ void SetBidiEnabled() { mBidiEnabled = true; }
+
+ void SetMathMLEnabled() { mMathMLEnabled = true; }
+
+ /**
+ * Ask this document whether it's the initial document in its window.
+ */
+ bool IsInitialDocument() const { return mIsInitialDocumentInWindow; }
+
+ /**
+ * Ask this document whether it has ever been a initial document in its
+ * window.
+ */
+ bool IsEverInitialDocument() const { return mIsEverInitialDocumentInWindow; }
+
+ /**
+ * Tell this document that it's the initial document in its window. See
+ * comments on mIsInitialDocumentInWindow for when this should be called.
+ */
+ void SetIsInitialDocument(bool aIsInitialDocument);
+
+ void SetLoadedAsData(bool aLoadedAsData, bool aConsiderForMemoryReporting);
+
+ TimeStamp GetLoadingOrRestoredFromBFCacheTimeStamp() const {
+ return mLoadingOrRestoredFromBFCacheTimeStamp;
+ }
+ void SetLoadingOrRestoredFromBFCacheTimeStampToNow() {
+ mLoadingOrRestoredFromBFCacheTimeStamp = TimeStamp::Now();
+ }
+
+ /**
+ * Normally we assert if a runnable labeled with one DocGroup touches data
+ * from another DocGroup. Calling IgnoreDocGroupMismatches() on a document
+ * means that we can touch that document from any DocGroup without asserting.
+ */
+ void IgnoreDocGroupMismatches() { mIgnoreDocGroupMismatches = true; }
+
+ /**
+ * Get the bidi options for this document.
+ * @see nsBidiUtils.h
+ */
+ uint32_t GetBidiOptions() const { return mBidiOptions; }
+
+ /**
+ * Set the bidi options for this document. This just sets the bits;
+ * callers are expected to take action as needed if they want this
+ * change to actually change anything immediately.
+ * @see nsBidiUtils.h
+ */
+ void SetBidiOptions(uint32_t aBidiOptions) { mBidiOptions = aBidiOptions; }
+
+ /**
+ * Returns true if the document holds a CSP
+ * delivered through an HTTP Header.
+ */
+ bool GetHasCSPDeliveredThroughHeader() {
+ return mHasCSPDeliveredThroughHeader;
+ }
+
+ /**
+ * Return a promise which resolves to the content blocking events.
+ */
+ using GetContentBlockingEventsPromise = MozPromise<uint32_t, bool, true>;
+ [[nodiscard]] RefPtr<GetContentBlockingEventsPromise>
+ GetContentBlockingEvents();
+
+ /**
+ * Get the sandbox flags for this document.
+ * @see nsSandboxFlags.h for the possible flags
+ */
+ uint32_t GetSandboxFlags() const { return mSandboxFlags; }
+
+ Maybe<nsILoadInfo::CrossOriginEmbedderPolicy> GetEmbedderPolicy() const {
+ return mEmbedderPolicy;
+ }
+
+ void SetEmbedderPolicy(
+ const Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCOEP) {
+ mEmbedderPolicy = aCOEP;
+ }
+
+ /**
+ * Get string representation of sandbox flags (null if no flags are set)
+ */
+ void GetSandboxFlagsAsString(nsAString& aFlags);
+
+ /**
+ * Set the sandbox flags for this document.
+ * @see nsSandboxFlags.h for the possible flags
+ */
+ void SetSandboxFlags(uint32_t sandboxFlags) { mSandboxFlags = sandboxFlags; }
+
+ /**
+ * Called when the document was decoded as UTF-8 and decoder encountered no
+ * errors.
+ */
+ void EnableEncodingMenu() { mEncodingMenuDisabled = false; }
+
+ /**
+ * Called to disable client access to cookies through the document.cookie API
+ * from user JavaScript code.
+ */
+ void DisableCookieAccess() { mDisableCookieAccess = true; }
+
+ void SetLinkHandlingEnabled(bool aValue) { mLinksEnabled = aValue; }
+ bool LinkHandlingEnabled() { return mLinksEnabled; }
+
+ /**
+ * Set compatibility mode for this document
+ */
+ void SetCompatibilityMode(nsCompatibility aMode);
+
+ /**
+ * Called to disable client access to document.write() API from user
+ * JavaScript code.
+ */
+ void SetDocWriteDisabled(bool aDisabled) { mDisableDocWrite = aDisabled; }
+
+ /**
+ * Whether a document.write() call is in progress.
+ */
+ bool IsWriting() const { return mWriteLevel != uint32_t(0); }
+
+ /**
+ * Access HTTP header data (this may also get set from other
+ * sources, like HTML META tags).
+ */
+ void GetHeaderData(nsAtom* aHeaderField, nsAString& aData) const;
+ void SetHeaderData(nsAtom* aheaderField, const nsAString& aData);
+
+ /**
+ * Set Early Hint data, moves the arrays into the function, leaving the
+ * passed variables empty
+ */
+ void SetEarlyHints(nsTArray<net::EarlyHintConnectArgs>&& aEarlyHints);
+ const nsTArray<net::EarlyHintConnectArgs>& GetEarlyHints() const {
+ return mEarlyHints;
+ }
+
+ /**
+ * Create a new presentation shell that will use aContext for its
+ * presentation context (presentation contexts <b>must not</b> be
+ * shared among multiple presentation shells). The caller of this
+ * method is responsible for calling BeginObservingDocument() on the
+ * presshell if the presshell should observe document mutations.
+ */
+ MOZ_CAN_RUN_SCRIPT already_AddRefed<PresShell> CreatePresShell(
+ nsPresContext* aContext, nsViewManager* aViewManager);
+ void DeletePresShell();
+
+ PresShell* GetPresShell() const {
+ return GetBFCacheEntry() ? nullptr : mPresShell;
+ }
+
+ inline PresShell* GetObservingPresShell() const;
+
+ // Return whether the presshell for this document is safe to flush.
+ bool IsSafeToFlush() const;
+
+ inline nsPresContext* GetPresContext() const;
+
+ bool HasShellOrBFCacheEntry() const { return mPresShell || mBFCacheEntry; }
+
+ // Instead using this method, what you probably want is
+ // RemoveFromBFCacheSync() as we do in MessagePort and BroadcastChannel.
+ void DisallowBFCaching(uint32_t aStatus = BFCacheStatus::NOT_ALLOWED);
+
+ bool IsBFCachingAllowed() const { return !mBFCacheDisallowed; }
+
+ // Accepts null to clear the BFCache entry too.
+ void SetBFCacheEntry(nsIBFCacheEntry* aEntry);
+
+ nsIBFCacheEntry* GetBFCacheEntry() const { return mBFCacheEntry; }
+
+ // Removes this document from the BFCache, if it is cached, and returns
+ // true if it was.
+ bool RemoveFromBFCacheSync();
+
+ /**
+ * Return the parent document of this document. Will return null
+ * unless this document is within a compound document and has a
+ * parent. Note that this parent chain may cross chrome boundaries.
+ */
+ Document* GetInProcessParentDocument() const { return mParentDocument; }
+
+ /**
+ * Set the parent document of this document.
+ */
+ void SetParentDocument(Document* aParent) {
+ mParentDocument = aParent;
+ if (aParent) {
+ RecomputeResistFingerprinting();
+ mIgnoreDocGroupMismatches = aParent->mIgnoreDocGroupMismatches;
+ }
+ }
+
+ void SetCurrentContextPaint(const SVGContextPaint* aContextPaint) {
+ mCurrentContextPaint = aContextPaint;
+ }
+
+ const SVGContextPaint* GetCurrentContextPaint() const {
+ return mCurrentContextPaint;
+ }
+
+ /**
+ * Set the sub document for aContent to aSubDoc.
+ */
+ nsresult SetSubDocumentFor(Element* aContent, Document* aSubDoc);
+
+ /**
+ * Get the sub document for aContent
+ */
+ Document* GetSubDocumentFor(nsIContent* aContent) const;
+
+ /**
+ * Get the content node for which this document is a sub document.
+ */
+ Element* GetEmbedderElement() const;
+
+ /**
+ * Return the doctype for this document.
+ */
+ DocumentType* GetDoctype() const;
+
+ /**
+ * Return the root element for this document.
+ */
+ Element* GetRootElement() const;
+
+ Selection* GetSelection(ErrorResult& aRv);
+
+ void MakeBrowsingContextNonSynthetic();
+ nsresult HasStorageAccessSync(bool& aHasStorageAccess);
+ already_AddRefed<Promise> HasStorageAccess(ErrorResult& aRv);
+
+ StorageAccessAPIHelper::PerformPermissionGrant CreatePermissionGrantPromise(
+ nsPIDOMWindowInner* aInnerWindow, nsIPrincipal* aPrincipal,
+ bool aHasUserInteraction, bool aRequireUserInteraction,
+ const Maybe<nsCString>& aTopLevelBaseDomain, bool aFrameOnly);
+
+ already_AddRefed<Promise> RequestStorageAccess(ErrorResult& aRv);
+
+ already_AddRefed<Promise> RequestStorageAccessForOrigin(
+ const nsAString& aThirdPartyOrigin, const bool aRequireUserInteraction,
+ ErrorResult& aRv);
+
+ already_AddRefed<Promise> RequestStorageAccessUnderSite(
+ const nsAString& aSerializedSite, ErrorResult& aRv);
+ already_AddRefed<Promise> CompleteStorageAccessRequestFromSite(
+ const nsAString& aSerializedOrigin, ErrorResult& aRv);
+
+ bool UseRegularPrincipal() const;
+
+ /**
+ * Gets the event target to dispatch key events to if there is no focused
+ * content in the document.
+ */
+ virtual Element* GetUnfocusedKeyEventTarget();
+
+ /**
+ * Retrieve information about the viewport as a data structure.
+ * This will return information in the viewport META data section
+ * of the document. This can be used in lieu of ProcessViewportInfo(),
+ * which places the viewport information in the document header instead
+ * of returning it directly.
+ *
+ * @param aDisplaySize size of the on-screen display area for this
+ * document, in device pixels.
+ *
+ * NOTE: If the site is optimized for mobile (via the doctype), this
+ * will return viewport information that specifies default information.
+ */
+ nsViewportInfo GetViewportInfo(const ScreenIntSize& aDisplaySize);
+
+ void SetMetaViewportData(UniquePtr<ViewportMetaData> aData);
+
+ // Returns a ViewportMetaData for this document.
+ ViewportMetaData GetViewportMetaData() const;
+
+ /**
+ * True iff this doc will ignore manual character encoding overrides.
+ */
+ virtual bool WillIgnoreCharsetOverride() { return true; }
+
+ /**
+ * Return whether the document was created by a srcdoc iframe.
+ */
+ bool IsSrcdocDocument() const { return mIsSrcdocDocument; }
+
+ /**
+ * Sets whether the document was created by a srcdoc iframe.
+ */
+ void SetIsSrcdocDocument(bool aIsSrcdocDocument) {
+ mIsSrcdocDocument = aIsSrcdocDocument;
+ }
+
+ /*
+ * Gets the srcdoc string from within the channel (assuming both exist).
+ * Returns a void string if this isn't a srcdoc document or if
+ * the channel has not been set.
+ */
+ nsresult GetSrcdocData(nsAString& aSrcdocData);
+
+ already_AddRefed<AnonymousContent> InsertAnonymousContent(bool aForce,
+ ErrorResult&);
+ void RemoveAnonymousContent(AnonymousContent&);
+ /**
+ * If aNode is a descendant of anonymous content inserted by
+ * InsertAnonymousContent, this method returns the root element of the
+ * inserted anonymous content (in other words, the clone of the aElement
+ * that was passed to InsertAnonymousContent).
+ */
+ Element* GetAnonRootIfInAnonymousContentContainer(nsINode* aNode) const;
+ nsTArray<RefPtr<AnonymousContent>>& GetAnonymousContents() {
+ return mAnonymousContents;
+ }
+
+ TimeStamp GetPageUnloadingEventTimeStamp() const {
+ if (!mParentDocument) {
+ return mPageUnloadingEventTimeStamp;
+ }
+
+ TimeStamp parentTimeStamp(
+ mParentDocument->GetPageUnloadingEventTimeStamp());
+ if (parentTimeStamp.IsNull()) {
+ return mPageUnloadingEventTimeStamp;
+ }
+
+ if (!mPageUnloadingEventTimeStamp ||
+ parentTimeStamp < mPageUnloadingEventTimeStamp) {
+ return parentTimeStamp;
+ }
+
+ return mPageUnloadingEventTimeStamp;
+ }
+
+ void NotifyLayerManagerRecreated();
+
+ // Add an element to the list of elements that need their mapped attributes
+ // resolved to a declaration block.
+ //
+ // These are weak pointers, manually unschedule them when an element is
+ // removed from the tree.
+ void ScheduleForPresAttrEvaluation(Element* aElement);
+
+ // Un-schedule an element scheduled by ScheduleForPresAttrEvaluation,
+ // generally when it's unbound from the tree.
+ void UnscheduleForPresAttrEvaluation(Element* aElement);
+
+ // Resolve all presentational attributes scheduled in
+ // ScheduleForPresAttrEvaluation
+ void ResolveScheduledPresAttrs() {
+ if (mLazyPresElements.IsEmpty()) {
+ return;
+ }
+ DoResolveScheduledPresAttrs();
+ }
+
+ Maybe<ClientInfo> GetClientInfo() const;
+ Maybe<ClientState> GetClientState() const;
+ Maybe<ServiceWorkerDescriptor> GetController() const;
+
+ // Given a node, get a weak reference to it and append that reference to
+ // mBlockedNodesByClassifier. Can be used later on to look up a node in it.
+ // (e.g., by the UI)
+ // /
+ void AddBlockedNodeByClassifier(nsINode* aNode) {
+ if (aNode) {
+ mBlockedNodesByClassifier.AppendElement(do_GetWeakReference(aNode));
+ }
+ }
+
+ // Returns the size of the mBlockedNodesByClassifier array.
+ //
+ // This array contains nodes that have been blocked to prevent user tracking,
+ // fingerprinting, cryptomining, etc. They most likely have had their
+ // nsIChannel canceled by the URL classifier (Safebrowsing).
+ //
+ // A script can subsequently use GetBlockedNodesByClassifier()
+ // to get a list of references to these nodes.
+ //
+ // Note:
+ // This expresses how many tracking nodes have been blocked for this document
+ // since its beginning, not how many of them are still around in the DOM tree.
+ // Weak references to blocked nodes are added in the mBlockedNodesByClassifier
+ // array but they are not removed when those nodes are removed from the tree
+ // or even garbage collected.
+ size_t BlockedNodeByClassifierCount() const {
+ return mBlockedNodesByClassifier.Length();
+ }
+
+ // Returns strong references to mBlockedNodesByClassifier. (Document.h)
+ // This array contains nodes that have been blocked to prevent
+ // user tracking. They most likely have had their nsIChannel
+ // canceled by the URL classifier (Safebrowsing).
+ already_AddRefed<nsSimpleContentList> BlockedNodesByClassifier() const;
+
+ // Helper method that returns true if the document has storage-access sandbox
+ // flag.
+ bool StorageAccessSandboxed() const;
+
+ // Helper method that returns true if storage access API is enabled and
+ // the passed flag has storage-access sandbox flag.
+ static bool StorageAccessSandboxed(uint32_t aSandboxFlags);
+
+ // Returns the cookie jar settings for this and sub contexts.
+ nsICookieJarSettings* CookieJarSettings();
+
+ // Returns whether this document is using unpartitioned cookies
+ bool UsingStorageAccess();
+
+ // Returns whether the storage access permission of the document is granted by
+ // the allow list.
+ bool HasStorageAccessPermissionGrantedByAllowList();
+
+ // Increments the document generation.
+ inline void Changed() { ++mGeneration; }
+
+ // Returns the current generation.
+ inline int32_t GetGeneration() const { return mGeneration; }
+
+ // Adds cached sizes values to aSizes if there's any
+ // cached value and if the document generation hasn't
+ // changed since the cache was created.
+ // Returns true if sizes were added.
+ bool GetCachedSizes(nsTabSizes* aSizes);
+
+ // Sets the cache sizes for the current generation.
+ void SetCachedSizes(nsTabSizes* aSizes);
+
+ /**
+ * Should be called when an element's editable changes as a result of
+ * changing its contentEditable attribute/property.
+ *
+ * The change should be +1 if the contentEditable attribute/property was
+ * changed to true, -1 if it was changed to false.
+ */
+ void ChangeContentEditableCount(Element*, int32_t aChange);
+ MOZ_CAN_RUN_SCRIPT void DeferredContentEditableCountChange(Element*);
+
+ enum class EditingState : int8_t {
+ eTearingDown = -2,
+ eSettingUp = -1,
+ eOff = 0,
+ eDesignMode,
+ eContentEditable
+ };
+
+ /**
+ * Returns the editing state of the document (not editable, contentEditable or
+ * designMode).
+ */
+ EditingState GetEditingState() const { return mEditingState; }
+
+ /**
+ * Returns whether the document is editable.
+ */
+ bool IsEditingOn() const {
+ return GetEditingState() == EditingState::eDesignMode ||
+ GetEditingState() == EditingState::eContentEditable;
+ }
+
+ class MOZ_STACK_CLASS nsAutoEditingState {
+ public:
+ nsAutoEditingState(Document* aDoc, EditingState aState)
+ : mDoc(aDoc), mSavedState(aDoc->mEditingState) {
+ aDoc->mEditingState = aState;
+ }
+ ~nsAutoEditingState() { mDoc->mEditingState = mSavedState; }
+
+ private:
+ RefPtr<Document> mDoc;
+ EditingState mSavedState;
+ };
+ friend class nsAutoEditingState;
+
+ /**
+ * Set the editing state of the document. Don't use this if you want
+ * to enable/disable editing, call EditingStateChanged() or
+ * SetDesignMode().
+ */
+ void SetEditingState(EditingState aState) { mEditingState = aState; }
+
+ /**
+ * Called when this Document's editor is destroyed.
+ */
+ void TearingDownEditor();
+
+ void SetKeyPressEventModel(uint16_t aKeyPressEventModel);
+
+ // Gets the next form number.
+ //
+ // Used by nsContentUtils::GenerateStateKey to get a unique number for each
+ // parser inserted form element.
+ int32_t GetNextFormNumber() { return mNextFormNumber++; }
+
+ // Gets the next form control number.
+ //
+ // Used by nsContentUtils::GenerateStateKey to get a unique number for each
+ // parser inserted form control element.
+ int32_t GetNextControlNumber() { return mNextControlNumber++; }
+
+ PreloadService& Preloads() { return mPreloadService; }
+
+ bool HasThirdPartyChannel();
+
+ bool ShouldIncludeInTelemetry() const;
+
+ void AddMediaElementWithMSE();
+ void RemoveMediaElementWithMSE();
+
+ void DoNotifyPossibleTitleChange();
+
+ void InitFeaturePolicy();
+ nsresult InitFeaturePolicy(nsIChannel* aChannel);
+
+ void EnsureNotEnteringAndExitFullscreen();
+
+ protected:
+ friend class nsUnblockOnloadEvent;
+
+ nsresult InitCSP(nsIChannel* aChannel);
+ nsresult InitCOEP(nsIChannel* aChannel);
+
+ nsresult InitReferrerInfo(nsIChannel* aChannel);
+
+ void PostUnblockOnloadEvent();
+
+ void DoUnblockOnload();
+
+ void DoResolveScheduledPresAttrs();
+
+ void RetrieveRelevantHeaders(nsIChannel* aChannel);
+
+ void TryChannelCharset(nsIChannel* aChannel, int32_t& aCharsetSource,
+ NotNull<const Encoding*>& aEncoding,
+ nsHtml5TreeOpExecutor* aExecutor);
+
+ MOZ_CAN_RUN_SCRIPT void DispatchContentLoadedEvents();
+
+ // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void DispatchPageTransition(
+ EventTarget* aDispatchTarget, const nsAString& aType, bool aInFrameSwap,
+ bool aPersisted, bool aOnlySystemGroup);
+
+ // Call this before the document does something that will unbind all content.
+ // That will stop us from doing a lot of work as each element is removed.
+ void DestroyElementMaps();
+
+ Element* GetRootElementInternal() const;
+
+ void SetPageUnloadingEventTimeStamp() {
+ MOZ_ASSERT(!mPageUnloadingEventTimeStamp);
+ mPageUnloadingEventTimeStamp = TimeStamp::NowLoRes();
+ }
+
+ void CleanUnloadEventsTimeStamp() {
+ MOZ_ASSERT(mPageUnloadingEventTimeStamp);
+ mPageUnloadingEventTimeStamp = TimeStamp();
+ }
+
+ /**
+ * Clears any Servo element data stored on Elements in the document.
+ */
+ void ClearStaleServoData();
+
+ /**
+ * Do the tree-disconnection that ResetToURI and document.open need to do.
+ */
+ void DisconnectNodeTree();
+
+ /**
+ * MaybeDispatchCheckKeyPressEventModelEvent() dispatches
+ * "CheckKeyPressEventModel" event to check whether we should dispatch
+ * keypress events in confluent model or split model. This should be
+ * called only when mEditingState is changed to eDesignMode or
+ * eConentEditable at first time.
+ */
+ void MaybeDispatchCheckKeyPressEventModelEvent();
+
+ /* Midas implementation */
+ nsCommandManager* GetMidasCommandManager();
+
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult TurnEditingOff();
+
+ // MOZ_CAN_RUN_SCRIPT_BOUNDARY because this is called from all sorts
+ // of places, and I'm pretty sure the exact ExecCommand call it
+ // makes cannot actually run script.
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult EditingStateChanged();
+
+ void MaybeEditingStateChanged();
+
+ public:
+ // Get the root <html> element, or return null if there isn't one (e.g.
+ // if the root isn't <html>)
+ Element* GetHtmlElement() const;
+ // Returns the first child of GetHtmlContent which has the given tag,
+ // or nullptr if that doesn't exist.
+ Element* GetHtmlChildElement(nsAtom* aTag);
+ // Get the canonical <body> element, or return null if there isn't one (e.g.
+ // if the root isn't <html> or if the <body> isn't there)
+ HTMLBodyElement* GetBodyElement();
+ // Get the canonical <head> element, or return null if there isn't one (e.g.
+ // if the root isn't <html> or if the <head> isn't there)
+ Element* GetHeadElement() { return GetHtmlChildElement(nsGkAtoms::head); }
+ // Get the "body" in the sense of document.body: The first <body> or
+ // <frameset> that's a child of a root <html>
+ nsGenericHTMLElement* GetBody();
+ // Set the "body" in the sense of document.body.
+ void SetBody(nsGenericHTMLElement* aBody, ErrorResult& rv);
+ // Get the "head" element in the sense of document.head.
+ HTMLSharedElement* GetHead();
+
+ ServoStyleSet* StyleSetForPresShell() const {
+ MOZ_ASSERT(!!mStyleSet.get());
+ return mStyleSet.get();
+ }
+
+ inline ServoStyleSet& EnsureStyleSet() const;
+
+ // ShadowRoot has APIs that can change styles. This notifies the shell that
+ // stlyes applicable in the shadow tree have potentially changed.
+ void RecordShadowStyleChange(ShadowRoot&);
+
+ // Needs to be called any time the applicable style can has changed, in order
+ // to schedule a style flush and setup all the relevant state.
+ //
+ // If we know the stylesheet change applies only to a shadow tree we can avoid
+ // some work (like updating the font-face-set / counter-styles / etc, as those
+ // are global).
+ void ApplicableStylesChanged(bool aKnownInShadowTree = false);
+
+ // Whether we filled the style set with any style sheet. Only meant to be used
+ // from DocumentOrShadowRoot::Traverse.
+ bool StyleSetFilled() const { return mStyleSetFilled; }
+
+ /**
+ * Accessors to the collection of stylesheets owned by this document.
+ * Style sheets are ordered, most significant last.
+ */
+
+ void InsertSheetAt(size_t aIndex, StyleSheet&);
+
+ /**
+ * Add a stylesheet to the document
+ *
+ * TODO(emilio): This is only used by parts of editor that are no longer in
+ * use by m-c or c-c, so remove.
+ */
+ void AddStyleSheet(StyleSheet* aSheet) {
+ MOZ_ASSERT(aSheet);
+ InsertSheetAt(SheetCount(), *aSheet);
+ }
+
+ /**
+ * Notify the document that the applicable state of the sheet changed
+ * and that observers should be notified and style sets updated
+ */
+ void StyleSheetApplicableStateChanged(StyleSheet&);
+ void PostStyleSheetApplicableStateChangeEvent(StyleSheet&);
+ void PostStyleSheetRemovedEvent(StyleSheet&);
+ void PostCustomPropertyRegistered(const dom::PropertyDefinition&);
+
+ enum additionalSheetType {
+ eAgentSheet,
+ eUserSheet,
+ eAuthorSheet,
+ AdditionalSheetTypeCount
+ };
+
+ nsresult LoadAdditionalStyleSheet(additionalSheetType aType,
+ nsIURI* aSheetURI);
+ nsresult AddAdditionalStyleSheet(additionalSheetType aType,
+ StyleSheet* aSheet);
+ void RemoveAdditionalStyleSheet(additionalSheetType aType, nsIURI* sheetURI);
+
+ StyleSheet* GetFirstAdditionalAuthorSheet() {
+ return mAdditionalSheets[eAuthorSheet].SafeElementAt(0);
+ }
+
+ /**
+ * Returns the index that aSheet should be inserted at to maintain document
+ * ordering.
+ */
+ size_t FindDocStyleSheetInsertionPoint(const StyleSheet& aSheet);
+
+ /**
+ * Get this document's CSSLoader. This is guaranteed to not return null.
+ */
+ css::Loader* CSSLoader() const { return mCSSLoader; }
+
+ /**
+ * Get this document's StyleImageLoader. This is guaranteed to not return
+ * null.
+ */
+ css::ImageLoader* StyleImageLoader() const { return mStyleImageLoader; }
+
+ /**
+ * Get the channel that was passed to StartDocumentLoad or Reset for this
+ * document. Note that this may be null in some cases (eg if
+ * StartDocumentLoad or Reset were never called)
+ */
+ nsIChannel* GetChannel() const { return mChannel; }
+
+ /**
+ * Get this document's attribute stylesheet. May return null if
+ * there isn't one.
+ */
+ AttributeStyles* GetAttributeStyles() const { return mAttributeStyles.get(); }
+
+ virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject);
+
+ /**
+ * Get/set the object from which the context for the event/script handling can
+ * be got. Normally GetScriptHandlingObject() returns the same object as
+ * GetScriptGlobalObject(), but if the document is loaded as data,
+ * non-null may be returned, even if GetScriptGlobalObject() returns null.
+ * aHasHadScriptHandlingObject is set true if document has had the object
+ * for event/script handling. Do not process any events/script if the method
+ * returns null, but aHasHadScriptHandlingObject is true.
+ */
+ nsIScriptGlobalObject* GetScriptHandlingObject(
+ bool& aHasHadScriptHandlingObject) const {
+ aHasHadScriptHandlingObject = mHasHadScriptHandlingObject;
+ return mScriptGlobalObject ? mScriptGlobalObject.get()
+ : GetScriptHandlingObjectInternal();
+ }
+ void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject);
+
+ /**
+ * Get the object that is used as the scope for all of the content
+ * wrappers whose owner document is this document. Unlike the script global
+ * object, this will only return null when the global object for this
+ * document is truly gone. Use this object when you're trying to find a
+ * content wrapper in XPConnect.
+ */
+ nsIGlobalObject* GetScopeObject() const;
+ void SetScopeObject(nsIGlobalObject* aGlobal);
+
+ /**
+ * Return the window containing the document (the outer window).
+ */
+ nsPIDOMWindowOuter* GetWindow() const {
+ return mWindow ? mWindow->GetOuterWindow() : GetWindowInternal();
+ }
+
+ bool IsInBackgroundWindow() const {
+ auto* outer = mWindow ? mWindow->GetOuterWindow() : nullptr;
+ return outer && outer->IsBackground();
+ }
+
+ /**
+ * Return the inner window used as the script compilation scope for
+ * this document. If you're not absolutely sure you need this, use
+ * GetWindow().
+ */
+ nsPIDOMWindowInner* GetInnerWindow() const {
+ return mRemovedFromDocShell ? nullptr : mWindow;
+ }
+
+ /**
+ * Return the outer window ID.
+ */
+ uint64_t OuterWindowID() const {
+ nsPIDOMWindowOuter* window = GetWindow();
+ return window ? window->WindowID() : 0;
+ }
+
+ /**
+ * Return the inner window ID.
+ */
+ uint64_t InnerWindowID() const {
+ nsPIDOMWindowInner* window = GetInnerWindow();
+ return window ? window->WindowID() : 0;
+ }
+
+ /**
+ * Return WindowGlobalChild that is associated with the inner window.
+ */
+ WindowGlobalChild* GetWindowGlobalChild() {
+ return GetInnerWindow() ? GetInnerWindow()->GetWindowGlobalChild()
+ : nullptr;
+ }
+
+ /**
+ * Return WindowContext associated with the inner window.
+ */
+ WindowContext* GetWindowContext() const {
+ return GetInnerWindow() ? GetInnerWindow()->GetWindowContext() : nullptr;
+ }
+
+ bool IsTopLevelWindowInactive() const {
+ return mState.HasState(DocumentState::WINDOW_INACTIVE);
+ }
+
+ /**
+ * Get the script loader for this document
+ */
+ dom::ScriptLoader* ScriptLoader() { return mScriptLoader; }
+
+ /**
+ * Add/Remove an element to the document's id and name hashes
+ */
+ void AddToIdTable(Element* aElement, nsAtom* aId);
+ void RemoveFromIdTable(Element* aElement, nsAtom* aId);
+ void AddToNameTable(Element* aElement, nsAtom* aName);
+ void RemoveFromNameTable(Element* aElement, nsAtom* aName);
+
+ /**
+ * Returns all elements in the top layer in the insertion order.
+ */
+ nsTArray<Element*> GetTopLayer() const;
+
+ bool TopLayerContains(Element&) const;
+
+ // Do the "fullscreen element ready check" from the fullscreen spec.
+ // It returns true if the given element is allowed to go into fullscreen.
+ // It is responsive to dispatch "fullscreenerror" event when necessary.
+ bool FullscreenElementReadyCheck(FullscreenRequest&);
+
+ /**
+ * When this is called on content process, this asynchronously requests that
+ * the document make aElement the fullscreen element, and move into fullscreen
+ * mode. The current fullscreen element (if any) is pushed onto the top layer,
+ * and it can be returned to fullscreen status by calling
+ * RestorePreviousFullscreenState().
+ * If on chrome process, this is synchronously.
+ *
+ * Note that requesting fullscreen in a document also makes the element which
+ * contains this document in this document's parent document fullscreen. i.e.
+ * the <iframe> or <browser> that contains this document is also mode
+ * fullscreen. This happens recursively in all ancestor documents.
+ */
+ void RequestFullscreen(UniquePtr<FullscreenRequest> aRequest,
+ bool aApplyFullscreenDirectly = false);
+
+ private:
+ void RequestFullscreenInContentProcess(UniquePtr<FullscreenRequest> aRequest,
+ bool aApplyFullscreenDirectly);
+ void RequestFullscreenInParentProcess(UniquePtr<FullscreenRequest> aRequest,
+ bool aApplyFullscreenDirectly);
+
+ // Pushes aElement onto the top layer
+ void TopLayerPush(Element&);
+
+ // Removes the topmost element for which aPredicate returns true from the top
+ // layer. The removed element, if any, is returned.
+ Element* TopLayerPop(FunctionRef<bool(Element*)> aPredicate);
+
+ // Removes the given element from the top layer. The removed element, if any,
+ // is returned.
+ Element* TopLayerPop(Element&);
+
+ MOZ_CAN_RUN_SCRIPT bool TryAutoFocusCandidate(Element& aElement);
+
+ public:
+ // Removes all the elements with fullscreen flag set from the top layer, and
+ // clears their fullscreen flag.
+ void CleanupFullscreenState();
+
+ // Pops the fullscreen element from the top layer and clears its
+ // fullscreen flag. Returns whether there was any fullscreen element.
+ enum class UpdateViewport : bool { No, Yes };
+ bool PopFullscreenElement(UpdateViewport = UpdateViewport::Yes);
+
+ // Pushes the given element into the top of top layer and set fullscreen
+ // flag.
+ void SetFullscreenElement(Element&);
+
+ // Whether we has pending fullscreen request.
+ bool HasPendingFullscreenRequests();
+
+ /**
+ * When Esc key is pressed, cancel the dialog element if the document is
+ * blocked by the dialog or hide popover if popover is shown.
+ */
+ MOZ_CAN_RUN_SCRIPT void HandleEscKey();
+
+ void AddModalDialog(HTMLDialogElement&);
+ void RemoveModalDialog(HTMLDialogElement&);
+
+ /**
+ * Called when a frame in a child process has entered fullscreen or when a
+ * fullscreen frame in a child process changes to another origin.
+ * aFrameElement is the frame element which contains the child-process
+ * fullscreen document.
+ */
+ void RemoteFrameFullscreenChanged(Element* aFrameElement);
+
+ /**
+ * Called when a frame in a remote child document has rolled back fullscreen
+ * so that all its top layer are empty; we must continue the
+ * rollback in this parent process' doc tree branch which is fullscreen.
+ * Note that only one branch of the document tree can have its documents in
+ * fullscreen state at one time. We're in inconsistent state if a
+ * fullscreen document has a parent and that parent isn't fullscreen. We
+ * preserve this property across process boundaries.
+ */
+ void RemoteFrameFullscreenReverted();
+
+ /**
+ * Restores the previous fullscreen element to fullscreen status. If there
+ * is no former fullscreen element, this exits fullscreen, moving the
+ * top-level browser window out of fullscreen mode.
+ */
+ void RestorePreviousFullscreenState(UniquePtr<FullscreenExit>);
+
+ /**
+ * Returns true if this document is a fullscreen leaf document, i.e. it
+ * is in fullscreen mode and has no fullscreen children.
+ */
+ bool IsFullscreenLeaf();
+
+ /**
+ * Returns the document which is at the root of this document's branch
+ * in the in-process document tree. Returns nullptr if the document isn't
+ * fullscreen.
+ */
+ Document* GetFullscreenRoot() const { return mFullscreenRoot; }
+
+ size_t CountFullscreenElements() const;
+
+ /**
+ * Sets the fullscreen root to aRoot. This stores a weak reference to aRoot
+ * in this document.
+ */
+ void SetFullscreenRoot(Document* aRoot) { mFullscreenRoot = aRoot; }
+
+ /**
+ * Synchronously cleans up the fullscreen state on the given document.
+ *
+ * Calling this without performing fullscreen transition could lead
+ * to undesired effect (the transition happens after document state
+ * flips), hence it should only be called either by nsGlobalWindow
+ * when we have performed the transition, or when it is necessary to
+ * clean up the state immediately. Otherwise, AsyncExitFullscreen()
+ * should be called instead.
+ *
+ * aDocument must not be null.
+ */
+ static void ExitFullscreenInDocTree(Document* aDocument);
+
+ /**
+ * Ask the document to exit fullscreen state asynchronously.
+ *
+ * Different from ExitFullscreenInDocTree(), this allows the window
+ * to perform fullscreen transition first if any.
+ *
+ * If aDocument is null, it will exit fullscreen from all documents
+ * in all windows.
+ */
+ static void AsyncExitFullscreen(Document* aDocument);
+
+ /**
+ * Handles any pending fullscreen in aDocument or its subdocuments.
+ *
+ * Returns whether there is any fullscreen request handled.
+ */
+ static bool HandlePendingFullscreenRequests(Document* aDocument);
+
+ /**
+ * Clear pending fullscreen in aDocument.
+ */
+ static void ClearPendingFullscreenRequests(Document* aDocument);
+
+ // ScreenOrientation related APIs
+
+ void ClearOrientationPendingPromise();
+ bool SetOrientationPendingPromise(Promise* aPromise);
+ Promise* GetOrientationPendingPromise() const {
+ return mOrientationPendingPromise;
+ }
+
+ //----------------------------------------------------------------------
+
+ // Document notification API's
+
+ /**
+ * Add a new observer of document change notifications. Whenever
+ * content is changed, appended, inserted or removed the observers are
+ * informed. An observer that is already observing the document must
+ * not be added without being removed first.
+ */
+ void AddObserver(nsIDocumentObserver* aObserver);
+
+ /**
+ * Remove an observer of document change notifications. This will
+ * return false if the observer cannot be found.
+ */
+ bool RemoveObserver(nsIDocumentObserver* aObserver);
+
+ // Observation hooks used to propagate notifications to document observers.
+ // BeginUpdate must be called before any batch of modifications of the
+ // content model or of style data, EndUpdate must be called afterward.
+ // To make this easy and painless, use the mozAutoDocUpdate helper class.
+ void BeginUpdate();
+ void EndUpdate();
+ uint32_t UpdateNestingLevel() { return mUpdateNestLevel; }
+
+ void BeginLoad();
+ virtual void EndLoad();
+
+ enum ReadyState {
+ READYSTATE_UNINITIALIZED = 0,
+ READYSTATE_LOADING = 1,
+ READYSTATE_INTERACTIVE = 3,
+ READYSTATE_COMPLETE = 4
+ };
+ // Set the readystate of the document. If aUpdateTimingInformation is true,
+ // this will record relevant timestamps in the document's performance timing.
+ // Some consumers (document.open is the only one right now, actually) don't
+ // want to do that, though.
+ void SetReadyStateInternal(ReadyState, bool aUpdateTimingInformation = true);
+ ReadyState GetReadyStateEnum() { return mReadyState; }
+
+ void NotifyLoading(bool aNewParentIsLoading, const ReadyState& aCurrentState,
+ ReadyState aNewState);
+
+ void NotifyAbortedLoad();
+
+ // Notify that an element changed state. This must happen under a
+ // scriptblocker but NOT within a begin/end update.
+ void ElementStateChanged(Element*, ElementState);
+
+ // Update a set of document states that may have changed.
+ // This should only be called by callers whose state is also reflected in the
+ // implementation of Document::State.
+ //
+ // aNotify controls whether we notify our DocumentStatesChanged observers.
+ void UpdateDocumentStates(DocumentState aMaybeChangedStates, bool aNotify);
+
+ void ResetDocumentDirection();
+
+ // Observation hooks for style data to propagate notifications
+ // to document observers
+ void RuleChanged(StyleSheet&, css::Rule*, StyleRuleChangeKind);
+ void RuleAdded(StyleSheet&, css::Rule&);
+ void RuleRemoved(StyleSheet&, css::Rule&);
+ void SheetCloned(StyleSheet&) {}
+ void ImportRuleLoaded(CSSImportRule&, StyleSheet&);
+
+ /**
+ * Flush notifications for this document and its parent documents
+ * (since those may affect the layout of this one).
+ */
+ void FlushPendingNotifications(FlushType aType);
+
+ /**
+ * Another variant of the above FlushPendingNotifications. This function
+ * takes a ChangesToFlush to specify whether throttled animations are flushed
+ * or not.
+ * If in doubt, use the above FlushPendingNotifications.
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY
+ void FlushPendingNotifications(ChangesToFlush aFlush);
+
+ /**
+ * Calls FlushPendingNotifications on any external resources this document
+ * has. If this document has no external resources or is an external resource
+ * itself this does nothing. This should only be called with
+ * aType >= FlushType::Style.
+ */
+ void FlushExternalResources(FlushType aType);
+
+ void AddWorkerDocumentListener(WorkerDocumentListener* aListener);
+ void RemoveWorkerDocumentListener(WorkerDocumentListener* aListener);
+
+ // Triggers an update of <svg:use> element shadow trees.
+ void UpdateSVGUseElementShadowTrees() {
+ if (mSVGUseElementsNeedingShadowTreeUpdate.IsEmpty()) {
+ return;
+ }
+ DoUpdateSVGUseElementShadowTrees();
+ }
+
+ /**
+ * Only to be used inside Gecko, you can't really do anything with the
+ * pointer outside Gecko anyway.
+ */
+ nsNodeInfoManager* NodeInfoManager() const { return mNodeInfoManager; }
+
+ /**
+ * Reset the document using the given channel and loadgroup. This works
+ * like ResetToURI, but also sets the document's channel to aChannel.
+ * The principal of the document will be set from the channel.
+ */
+ virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup);
+
+ /**
+ * Reset this document to aURI, aLoadGroup, aPrincipal and
+ * aPartitionedPrincipal. aURI must not be null. If aPrincipal is null, a
+ * content principal based on aURI will be used.
+ */
+ virtual void ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup,
+ nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal);
+
+ /**
+ * Set the container (docshell) for this document. Virtual so that
+ * docshell can call it.
+ */
+ virtual void SetContainer(nsDocShell* aContainer);
+
+ /**
+ * Get the container (docshell) for this document.
+ */
+ nsISupports* GetContainer() const;
+
+ /**
+ * Get the container's load context for this document.
+ */
+ nsILoadContext* GetLoadContext() const;
+
+ /**
+ * Get docshell the for this document.
+ */
+ nsIDocShell* GetDocShell() const;
+
+ /**
+ * Set and get XML declaration. If aVersion is null there is no declaration.
+ * aStandalone takes values -1, 0 and 1 indicating respectively that there
+ * was no standalone parameter in the declaration, that it was given as no,
+ * or that it was given as yes.
+ */
+ void SetXMLDeclaration(const char16_t* aVersion, const char16_t* aEncoding,
+ const int32_t aStandalone);
+ void GetXMLDeclaration(nsAString& aVersion, nsAString& aEncoding,
+ nsAString& Standalone);
+
+ /**
+ * Returns the bits for the color-scheme specified by the
+ * <meta name="color-scheme">.
+ */
+ uint8_t GetColorSchemeBits() const { return mColorSchemeBits; }
+
+ /**
+ * Traverses the DOM and computes the supported color schemes as per
+ * https://html.spec.whatwg.org/#meta-color-scheme
+ */
+ void RecomputeColorScheme();
+ void AddColorSchemeMeta(HTMLMetaElement&);
+ void RemoveColorSchemeMeta(HTMLMetaElement&);
+
+ /**
+ * Returns true if this is what HTML 5 calls an "HTML document" (for example
+ * regular HTML document with Content-Type "text/html", image documents and
+ * media documents). Returns false for XHTML and any other documents parsed
+ * by the XML parser.
+ */
+ bool IsHTMLDocument() const { return mType == eHTML; }
+ bool IsHTMLOrXHTML() const { return mType == eHTML || mType == eXHTML; }
+ bool IsImageDocument() const {
+ return MediaDocumentKind() == MediaDocumentKind::Image;
+ }
+ bool IsXMLDocument() const { return !IsHTMLDocument(); }
+ bool IsSVGDocument() const { return mType == eSVG; }
+ bool IsUnstyledDocument() { return IsLoadedAsData(); }
+ bool LoadsFullXULStyleSheetUpFront() {
+ if (IsSVGDocument()) {
+ return false;
+ }
+ return AllowXULXBL();
+ }
+
+ bool IsScriptEnabled() const;
+
+ /**
+ * Returns true if this document was created from a nsXULPrototypeDocument.
+ */
+ bool LoadedFromPrototype() const { return mPrototypeDocument; }
+ /**
+ * Returns the prototype the document was created from, or null if it was not
+ * created from a prototype.
+ */
+ nsXULPrototypeDocument* GetPrototype() const { return mPrototypeDocument; }
+
+ bool IsTopLevelContentDocument() const { return mIsTopLevelContentDocument; }
+ void SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument) {
+ mIsTopLevelContentDocument = aIsTopLevelContentDocument;
+ }
+
+ bool IsContentDocument() const { return mIsContentDocument; }
+ void SetIsContentDocument(bool aIsContentDocument) {
+ mIsContentDocument = aIsContentDocument;
+ }
+
+ void ProcessMETATag(HTMLMetaElement* aMetaElement);
+ /**
+ * Create an element with the specified name, prefix and namespace ID.
+ * Returns null if element name parsing failed.
+ */
+ already_AddRefed<Element> CreateElem(const nsAString& aName, nsAtom* aPrefix,
+ int32_t aNamespaceID,
+ const nsAString* aIs = nullptr);
+
+ /**
+ * Get the security info (i.e. SSL state etc) that the document got
+ * from the channel/document that created the content of the
+ * document.
+ *
+ * @see nsIChannel
+ */
+ nsITransportSecurityInfo* GetSecurityInfo() { return mSecurityInfo; }
+
+ /**
+ * Get the channel that failed to load and resulted in an error page, if it
+ * exists. This is only relevant to error pages.
+ */
+ nsIChannel* GetFailedChannel() const { return mFailedChannel; }
+
+ /**
+ * This function checks if the document that is trying to access
+ * GetNetErrorInfo is a trusted about net error page or not.
+ */
+ static bool CallerIsTrustedAboutNetError(JSContext* aCx, JSObject* aObject);
+
+ /**
+ * This function checks if the document that is trying to access
+ * ReloadWithHttpsOnlyException is a trusted HTTPS only error page.
+ */
+ static bool CallerIsTrustedAboutHttpsOnlyError(JSContext* aCx,
+ JSObject* aObject);
+
+ /**
+ * Get security info like error code for a failed channel. This
+ * property is only exposed to about:neterror documents.
+ */
+ void GetNetErrorInfo(mozilla::dom::NetErrorInfo& aInfo, ErrorResult& aRv);
+
+ /**
+ * This function checks if the document that is trying to access
+ * GetFailedCertSecurityInfo is a trusted cert error page or not.
+ */
+ static bool CallerIsTrustedAboutCertError(JSContext* aCx, JSObject* aObject);
+
+ /**
+ * This function checks if the privilege storage access api is available for
+ * the caller. We only allow privilege SSA to be called by system principal
+ * and webcompat extension.
+ */
+ static bool CallerCanAccessPrivilegeSSA(JSContext* aCx, JSObject* aObject);
+
+ /**
+ * Get the security info (i.e. certificate validity, errorCode, etc) for a
+ * failed Channel. This property is only exposed for about:certerror
+ * documents.
+ */
+ void GetFailedCertSecurityInfo(mozilla::dom::FailedCertSecurityInfo& aInfo,
+ ErrorResult& aRv);
+
+ /**
+ * Set the channel that failed to load and resulted in an error page.
+ * This is only relevant to error pages.
+ */
+ void SetFailedChannel(nsIChannel* aChannel) { mFailedChannel = aChannel; }
+
+ /**
+ * Returns the default namespace ID used for elements created in this
+ * document.
+ */
+ int32_t GetDefaultNamespaceID() const { return mDefaultElementType; }
+
+ void RemoveAllProperties();
+ void RemoveAllPropertiesFor(nsINode* aNode);
+
+ nsPropertyTable& PropertyTable() { return mPropertyTable; }
+
+ /**
+ * Sets the ID used to identify this part of the multipart document
+ */
+ void SetPartID(uint32_t aID) { mPartID = aID; }
+
+ /**
+ * Return the ID used to identify this part of the multipart document
+ */
+ uint32_t GetPartID() const { return mPartID; }
+
+ /**
+ * Sanitize the document by resetting all input elements and forms that have
+ * autocomplete=off to their default values.
+ * TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void Sanitize();
+
+ /**
+ * Enumerate all subdocuments.
+ * The enumerator callback should return CallState::Continue to continue
+ * enumerating, or CallState::Stop to stop. This will never get passed a null
+ * aDocument.
+ */
+ using SubDocEnumFunc = FunctionRef<CallState(Document&)>;
+ void EnumerateSubDocuments(SubDocEnumFunc aCallback);
+
+ /**
+ * Collect all the descendant documents for which |aCalback| returns true.
+ * The callback function must not mutate any state for the given document.
+ */
+ using nsDocTestFunc = bool (*)(const Document* aDocument);
+ void CollectDescendantDocuments(nsTArray<RefPtr<Document>>& aDescendants,
+ nsDocTestFunc aCallback) const;
+
+ /**
+ * Check whether it is safe to cache the presentation of this document
+ * and all of its subdocuments (depending on the 3rd param). This method
+ * checks the following conditions recursively:
+ * - Some document types, such as plugin documents, cannot be safely cached.
+ * - If there are any pending requests, we don't allow the presentation
+ * to be cached. Ideally these requests would be suspended and resumed,
+ * but that is difficult in some cases, such as XMLHttpRequest.
+ * - If there are any beforeunload or unload listeners, we must fire them
+ * for correctness, but this likely puts the document into a state where
+ * it would not function correctly if restored.
+ *
+ * |aNewRequest| should be the request for a new document which will
+ * replace this document in the docshell. The new document's request
+ * will be ignored when checking for active requests. If there is no
+ * request associated with the new document, this parameter may be null.
+ *
+ * |aBFCacheCombo| is used as a bitmask to indicate what the status
+ * combination is when we try to BFCache aNewRequest
+ */
+ virtual bool CanSavePresentation(nsIRequest* aNewRequest,
+ uint32_t& aBFCacheCombo,
+ bool aIncludeSubdocuments,
+ bool aAllowUnloadListeners = true);
+
+ /**
+ * Pass principals if the correct ones are known when calling Init. That way
+ * NodeInfoManager doesn't need to create a temporary null principal.
+ */
+ virtual nsresult Init(nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal);
+
+ /**
+ * Notify the document that its associated ContentViewer is being destroyed.
+ * This releases circular references so that the document can go away.
+ * Destroy() is only called on documents that have a content viewer.
+ */
+ virtual void Destroy();
+
+ /**
+ * Notify the document that its associated ContentViewer is no longer
+ * the current viewer for the docshell. The document might still
+ * be rendered in "zombie state" until the next document is ready.
+ * The document should save form control state.
+ */
+ void RemovedFromDocShell();
+
+ /**
+ * Get the layout history state that should be used to save and restore state
+ * for nodes in this document. This may return null; if that happens state
+ * saving and restoration is not possible.
+ */
+ already_AddRefed<nsILayoutHistoryState> GetLayoutHistoryState() const;
+
+ /**
+ * Methods that can be used to prevent onload firing while an event that
+ * should block onload is posted. onload is guaranteed to not fire until
+ * either all calls to BlockOnload() have been matched by calls to
+ * UnblockOnload() or the load has been stopped altogether (by the user
+ * pressing the Stop button, say).
+ */
+ void BlockOnload();
+ /**
+ * @param aFireSync whether to fire onload synchronously. If false,
+ * onload will fire asynchronously after all onload blocks have been
+ * removed. It will NOT fire from inside UnblockOnload. If true,
+ * onload may fire from inside UnblockOnload.
+ */
+ void UnblockOnload(bool aFireSync);
+
+ // Only BlockOnload should call this!
+ void AsyncBlockOnload();
+
+ void BlockDOMContentLoaded() { ++mBlockDOMContentLoaded; }
+
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void UnblockDOMContentLoaded();
+
+ /**
+ * Notification that the page has been shown, for documents which are loaded
+ * into a DOM window. This corresponds to the completion of document load,
+ * or to the page's presentation being restored into an existing DOM window.
+ * This notification fires applicable DOM events to the content window. See
+ * PageTransitionEvent.webidl for a description of the |aPersisted|
+ * parameter. If aDispatchStartTarget is null, the pageshow event is
+ * dispatched on the ScriptGlobalObject for this document, otherwise it's
+ * dispatched on aDispatchStartTarget. If |aOnlySystemGroup| is true, the
+ * event is only dispatched to listeners in the system group.
+ * Note: if aDispatchStartTarget isn't null, the showing state of the
+ * document won't be altered.
+ */
+ virtual void OnPageShow(bool aPersisted, EventTarget* aDispatchStartTarget,
+ bool aOnlySystemGroup = false);
+
+ /**
+ * Notification that the page has been hidden, for documents which are loaded
+ * into a DOM window. This corresponds to the unloading of the document, or
+ * to the document's presentation being saved but removed from an existing
+ * DOM window. This notification fires applicable DOM events to the content
+ * window. See PageTransitionEvent.webidl for a description of the
+ * |aPersisted| parameter. If aDispatchStartTarget is null, the pagehide
+ * event is dispatched on the ScriptGlobalObject for this document,
+ * otherwise it's dispatched on aDispatchStartTarget. If |aOnlySystemGroup| is
+ * true, the event is only dispatched to listeners in the system group.
+ * Note: if aDispatchStartTarget isn't null, the showing state of the
+ * document won't be altered.
+ */
+ void OnPageHide(bool aPersisted, EventTarget* aDispatchStartTarget,
+ bool aOnlySystemGroup = false);
+
+ /*
+ * We record the set of links in the document that are relevant to
+ * style.
+ */
+ /**
+ * Notification that an element is a link that is relevant to style.
+ */
+ void AddStyleRelevantLink(Link* aLink) {
+ NS_ASSERTION(aLink, "Passing in a null link. Expect crashes RSN!");
+#ifdef DEBUG
+ NS_ASSERTION(!mStyledLinks.Contains(aLink),
+ "Document already knows about this Link!");
+ mStyledLinksCleared = false;
+#endif
+ mStyledLinks.Insert(aLink);
+ }
+
+ /**
+ * Notification that an element is a link and its URI might have been
+ * changed or the element removed. If the element is still a link relevant
+ * to style, then someone must ensure that AddStyleRelevantLink is
+ * (eventually) called on it again.
+ */
+ void ForgetLink(Link* aLink) {
+ MOZ_ASSERT(aLink, "Passing in a null link. Expect crashes RSN!");
+ MOZ_ASSERT(mStyledLinks.Contains(aLink) || mStyledLinksCleared,
+ "Document knows nothing about this Link!");
+ mStyledLinks.Remove(aLink);
+ }
+
+ // Refreshes the hrefs of all the links in the document.
+ void RefreshLinkHrefs();
+
+ /**
+ * Support for window.matchMedia()
+ */
+
+ already_AddRefed<MediaQueryList> MatchMedia(const nsACString& aMediaQueryList,
+ CallerType aCallerType);
+
+ LinkedList<MediaQueryList>& MediaQueryLists() { return mDOMMediaQueryLists; }
+
+ nsTHashtable<LCPEntryHashEntry>& ContentIdentifiersForLCP() {
+ return mContentIdentifiersForLCP;
+ }
+
+ /**
+ * Get the compatibility mode for this document
+ */
+ nsCompatibility GetCompatibilityMode() const { return mCompatMode; }
+
+ /**
+ * Check whether we've ever fired a DOMTitleChanged event for this
+ * document.
+ */
+ bool HaveFiredDOMTitleChange() const { return mHaveFiredTitleChange; }
+
+ /**
+ * To batch DOMSubtreeModified, document needs to be informed when
+ * a mutation event might be dispatched, even if the event isn't actually
+ * created because there are no listeners for it.
+ *
+ * @param aTarget is the target for the mutation event.
+ */
+ void MayDispatchMutationEvent(nsINode* aTarget) {
+ if (mSubtreeModifiedDepth > 0) {
+ mSubtreeModifiedTargets.AppendObject(aTarget);
+ }
+ }
+
+ /**
+ * Marks as not-going-to-be-collected for the given generation of
+ * cycle collection.
+ */
+ void MarkUncollectableForCCGeneration(uint32_t aGeneration) {
+ mMarkedCCGeneration = aGeneration;
+ }
+
+ /**
+ * Gets the cycle collector generation this document is marked for.
+ */
+ uint32_t GetMarkedCCGeneration() { return mMarkedCCGeneration; }
+
+ /**
+ * Returns whether this document is cookie averse. See
+ * https://html.spec.whatwg.org/multipage/dom.html#cookie-averse-document-object
+ */
+ bool IsCookieAverse() const {
+ // If we are a document that "has no browsing context."
+ if (!GetInnerWindow()) {
+ return true;
+ }
+
+ // If we are a document "whose URL's scheme is not a network scheme."
+ // NB: Explicitly allow file: URIs to store cookies.
+
+ return !NodePrincipal()->SchemeIs("http") &&
+ !NodePrincipal()->SchemeIs("https") &&
+ !NodePrincipal()->SchemeIs("file");
+ }
+
+ bool IsLoadedAsData() { return mLoadedAsData; }
+
+ void SetAddedToMemoryReportAsDataDocument() {
+ mAddedToMemoryReportingAsDataDocument = true;
+ }
+
+ void UnregisterFromMemoryReportingForDataDocument();
+
+ bool MayStartLayout() { return mMayStartLayout; }
+
+ void SetMayStartLayout(bool aMayStartLayout);
+
+ already_AddRefed<nsIDocumentEncoder> GetCachedEncoder();
+
+ void SetCachedEncoder(already_AddRefed<nsIDocumentEncoder> aEncoder);
+
+ // In case of failure, the document really can't initialize the frame loader.
+ nsresult InitializeFrameLoader(nsFrameLoader* aLoader);
+ // In case of failure, the caller must handle the error, for example by
+ // finalizing frame loader asynchronously.
+ nsresult FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer);
+ // Removes the frame loader of aShell from the initialization list.
+ void TryCancelFrameLoaderInitialization(nsIDocShell* aShell);
+
+ /**
+ * Check whether this document is a root document that is not an
+ * external resource.
+ */
+ bool IsRootDisplayDocument() const {
+ return !mParentDocument && !mDisplayDocument;
+ }
+
+ bool ChromeRulesEnabled() const { return mChromeRulesEnabled; }
+
+ bool IsInChromeDocShell() const {
+ const Document* root = this;
+ while (const Document* displayDoc = root->GetDisplayDocument()) {
+ root = displayDoc;
+ }
+ return root->mInChromeDocShell;
+ }
+
+ bool IsBeingUsedAsImage() const { return mIsBeingUsedAsImage; }
+
+ void SetIsBeingUsedAsImage() { mIsBeingUsedAsImage = true; }
+
+ bool IsSVGGlyphsDocument() const { return mIsSVGGlyphsDocument; }
+
+ void SetIsSVGGlyphsDocument() { mIsSVGGlyphsDocument = true; }
+
+ bool IsResourceDoc() const {
+ return IsBeingUsedAsImage() || // Are we a helper-doc for an SVG image?
+ mHasDisplayDocument; // Are we an external resource doc?
+ }
+
+ /**
+ * Get the document for which this document is an external resource. This
+ * will be null if this document is not an external resource. Otherwise,
+ * GetDisplayDocument() will return a non-null document, and
+ * GetDisplayDocument()->GetDisplayDocument() is guaranteed to be null.
+ */
+ Document* GetDisplayDocument() const { return mDisplayDocument; }
+
+ /**
+ * Set the display document for this document. aDisplayDocument must not be
+ * null.
+ */
+ void SetDisplayDocument(Document* aDisplayDocument) {
+ MOZ_ASSERT(!GetPresShell() && !GetContainer() && !GetWindow(),
+ "Shouldn't set mDisplayDocument on documents that already "
+ "have a presentation or a docshell or a window");
+ MOZ_ASSERT(aDisplayDocument, "Must not be null");
+ MOZ_ASSERT(aDisplayDocument != this, "Should be different document");
+ MOZ_ASSERT(!aDisplayDocument->GetDisplayDocument(),
+ "Display documents should not nest");
+ mDisplayDocument = aDisplayDocument;
+ mHasDisplayDocument = !!aDisplayDocument;
+ }
+
+ /**
+ * Request an external resource document for aURI. This will return the
+ * resource document if available. If one is not available yet, it will
+ * start loading as needed, and the pending load object will be returned in
+ * aPendingLoad so that the caller can register an observer to wait for the
+ * load. If this function returns null and doesn't return a pending load,
+ * that means that there is no resource document for this URI and won't be
+ * one in the future.
+ *
+ * @param aURI the URI to get
+ * @param aReferrerInfo the referrerInfo of the request
+ * @param aRequestingNode the node making the request
+ * @param aPendingLoad the pending load for this request, if any
+ */
+ Document* RequestExternalResource(nsIURI* aURI,
+ nsIReferrerInfo* aReferrerInfo,
+ nsINode* aRequestingNode,
+ ExternalResourceLoad** aPendingLoad);
+
+ /**
+ * Enumerate the external resource documents associated with this document.
+ * The enumerator callback should return CallState::Continue to continue
+ * enumerating, or CallState::Stop to stop. This callback will never get
+ * passed a null aDocument.
+ */
+ void EnumerateExternalResources(SubDocEnumFunc aCallback);
+
+ dom::ExternalResourceMap& ExternalResourceMap() {
+ return mExternalResourceMap;
+ }
+
+ /**
+ * Return whether the document is currently showing (in the sense of
+ * OnPageShow() having been called already and OnPageHide() not having been
+ * called yet.
+ */
+ bool IsShowing() const { return mIsShowing; }
+ /**
+ * Return whether the document is currently visible (in the sense of
+ * OnPageHide having been called and OnPageShow not yet having been called)
+ */
+ bool IsVisible() const { return mVisible; }
+
+ void SetSuppressedEventListener(EventListener* aListener);
+
+ EventListener* GetSuppressedEventListener() {
+ return mSuppressedEventListener;
+ }
+
+ /**
+ * Return true when this document is active, i.e., an active document
+ * in a content viewer and not in the bfcache.
+ * This does NOT match the "active document" concept in the WHATWG spec -
+ * see IsCurrentActiveDocument.
+ */
+ bool IsActive() const;
+
+ /**
+ * Return true if this is the current active document for its
+ * docshell. Note that a docshell may have multiple active documents
+ * due to the bfcache -- this should be used when you need to
+ * differentiate the *current* active document from any active
+ * documents.
+ */
+ bool IsCurrentActiveDocument() const {
+ nsPIDOMWindowInner* inner = GetInnerWindow();
+ return inner && inner->IsCurrentInnerWindow() && inner->GetDoc() == this;
+ }
+
+ /**
+ * Returns whether this document should perform image loads.
+ */
+ bool ShouldLoadImages() const {
+ // We check IsBeingUsedAsImage() so that SVG documents loaded as
+ // images can themselves have data: URL image references.
+ return IsCurrentActiveDocument() || IsBeingUsedAsImage() ||
+ IsStaticDocument();
+ }
+
+ void SetHasPrintCallbacks() {
+ MOZ_DIAGNOSTIC_ASSERT(IsStaticDocument());
+ mHasPrintCallbacks = true;
+ }
+
+ bool HasPrintCallbacks() const { return mHasPrintCallbacks; }
+
+ /**
+ * Register/Unregister the ActivityObserver into mActivityObservers to listen
+ * the document's activity changes such as OnPageHide, visibility, activity.
+ * The ActivityObserver objects can be nsIObjectLoadingContent or
+ * nsIDocumentActivity or HTMLMEdiaElement.
+ */
+ void RegisterActivityObserver(nsISupports* aSupports);
+ bool UnregisterActivityObserver(nsISupports* aSupports);
+ // Enumerate all the observers in mActivityObservers by the aEnumerator.
+ using ActivityObserverEnumerator = FunctionRef<void(nsISupports*)>;
+ void EnumerateActivityObservers(ActivityObserverEnumerator aEnumerator);
+
+ void NotifyActivityChanged();
+
+ // Indicates whether mAnimationController has been (lazily) initialized.
+ // If this returns true, we're promising that GetAnimationController()
+ // will have a non-null return value.
+ bool HasAnimationController() { return !!mAnimationController; }
+
+ // Getter for this document's SMIL Animation Controller. Performs lazy
+ // initialization, if this document supports animation and if
+ // mAnimationController isn't yet initialized.
+ //
+ // If HasAnimationController is true, this is guaranteed to return non-null.
+ SMILAnimationController* GetAnimationController();
+
+ // Gets the tracker for scroll-driven animations that are waiting to start.
+ // Returns nullptr if there is no scroll-driven animation tracker for this
+ // document which will be the case if there have never been any scroll-driven
+ // animations in the document.
+ ScrollTimelineAnimationTracker* GetScrollTimelineAnimationTracker() {
+ return mScrollTimelineAnimationTracker;
+ }
+
+ // Gets the tracker for scroll-driven animations that are waiting to start and
+ // creates it if it doesn't already exist. As a result, the return value
+ // will never be nullptr.
+ ScrollTimelineAnimationTracker* GetOrCreateScrollTimelineAnimationTracker();
+
+ /**
+ * Prevents user initiated events from being dispatched to the document and
+ * subdocuments.
+ */
+ void SuppressEventHandling(uint32_t aIncrease = 1);
+
+ /**
+ * Unsuppress event handling.
+ * @param aFireEvents If true, delayed events (focus/blur) will be fired
+ * asynchronously.
+ */
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void UnsuppressEventHandlingAndFireEvents(
+ bool aFireEvents);
+
+ uint32_t EventHandlingSuppressed() const { return mEventsSuppressed; }
+
+ bool IsEventHandlingEnabled() const {
+ return !EventHandlingSuppressed() && mScriptGlobalObject;
+ }
+
+ bool WouldScheduleFrameRequestCallbacks() const {
+ // If this function changes to depend on some other variable, make sure to
+ // call UpdateFrameRequestCallbackSchedulingState() calls to the places
+ // where that variable can change.
+ return mPresShell && IsEventHandlingEnabled();
+ }
+
+ void DecreaseEventSuppression() {
+ MOZ_ASSERT(mEventsSuppressed);
+ --mEventsSuppressed;
+ UpdateFrameRequestCallbackSchedulingState();
+ }
+
+ /**
+ * Some clipboard commands are unconditionally enabled on some documents, so
+ * as to always dispatch copy / paste events even though you'd normally not be
+ * able to copy.
+ */
+ bool AreClipboardCommandsUnconditionallyEnabled() const;
+
+ /**
+ * Note a ChannelEventQueue which has been suspended on the document's behalf
+ * to prevent XHRs from running content scripts while event handling is
+ * suppressed. The document is responsible for resuming the queue after
+ * event handling is unsuppressed.
+ */
+ void AddSuspendedChannelEventQueue(net::ChannelEventQueue* aQueue);
+
+ /**
+ * Returns true if a postMessage event should be suspended instead of running.
+ * The document is responsible for running the event later, in the order they
+ * were received.
+ */
+ bool SuspendPostMessageEvent(PostMessageEvent* aEvent);
+
+ /**
+ * Run any suspended postMessage events, or clear them.
+ */
+ void FireOrClearPostMessageEvents(bool aFireEvents);
+
+ void SetHasDelayedRefreshEvent() { mHasDelayedRefreshEvent = true; }
+
+ /**
+ * Flag whether we're about to fire the window's load event for this document.
+ */
+ void SetLoadEventFiring(bool aFiring) { mLoadEventFiring = aFiring; }
+
+ /**
+ * Test whether we should be firing a load event for this document after a
+ * document.close(). This is public and on Document, instead of being private
+ * to Document, because we need to go through the normal docloader logic
+ * for the readystate change to READYSTATE_COMPLETE with the normal timing and
+ * semantics of firing the load event; we just don't want to fire the load
+ * event if this tests true. So we need the docloader to be able to access
+ * this state.
+ *
+ * This method should only be called at the point when the load event is about
+ * to be fired. It resets the "skip" flag, so it is not idempotent.
+ */
+ bool SkipLoadEventAfterClose() {
+ bool skip = mSkipLoadEventAfterClose;
+ mSkipLoadEventAfterClose = false;
+ return skip;
+ }
+
+ /**
+ * Increment https://html.spec.whatwg.org/#ignore-destructive-writes-counter
+ */
+ void IncrementIgnoreDestructiveWritesCounter() {
+ ++mIgnoreDestructiveWritesCounter;
+ }
+
+ /**
+ * Decrement https://html.spec.whatwg.org/#ignore-destructive-writes-counter
+ */
+ void DecrementIgnoreDestructiveWritesCounter() {
+ --mIgnoreDestructiveWritesCounter;
+ }
+
+ bool IsDNSPrefetchAllowed() const { return mAllowDNSPrefetch; }
+
+ /**
+ * Returns true if this document is allowed to contain XUL element and
+ * use non-builtin XBL bindings.
+ */
+ bool AllowXULXBL() {
+ return mAllowXULXBL == eTriTrue ? true
+ : mAllowXULXBL == eTriFalse ? false
+ : InternalAllowXULXBL();
+ }
+
+ /**
+ * Returns true if this document is allowed to load DTDs from UI resources
+ * no matter what.
+ */
+ bool SkipDTDSecurityChecks() { return mSkipDTDSecurityChecks; }
+
+ void ForceEnableXULXBL() { mAllowXULXBL = eTriTrue; }
+
+ void ForceSkipDTDSecurityChecks() { mSkipDTDSecurityChecks = true; }
+
+ /**
+ * Returns the template content owner document that owns the content of
+ * HTMLTemplateElement.
+ */
+ Document* GetTemplateContentsOwner();
+
+ Document* GetTemplateContentsOwnerIfExists() const {
+ return mTemplateContentsOwner.get();
+ }
+
+ bool IsTemplateContentsOwner() const {
+ // Template contents owner documents are the template contents owner of
+ // themselves.
+ return mTemplateContentsOwner == this;
+ }
+
+ /**
+ * Returns true if this document is a static clone of a normal document.
+ *
+ * We create static clones for print preview and printing (possibly other
+ * things in future).
+ *
+ * Note that static documents are also "loaded as data" (if this method
+ * returns true, IsLoadedAsData() will also return true).
+ */
+ bool IsStaticDocument() const { return mIsStaticDocument; }
+
+ /**
+ * Clones the document along with any subdocuments, stylesheet, etc.
+ *
+ * The resulting document and everything it contains (including any
+ * sub-documents) are created purely via cloning. The returned documents and
+ * any sub-documents are "loaded as data" documents to preserve the state as
+ * it was during the clone process (we don't want external resources to load
+ * and replace the cloned resources).
+ *
+ * @param aCloneContainer The container for the clone document.
+ * @param aDocumentViewer The viewer for the clone document. Must be the
+ * viewer of aCloneContainer, but callers must have a
+ * reference to it already and ensure it's not null.
+ * @param aPrintSettings The print settings for this clone.
+ * @param aOutHasInProcessPrintCallbacks Self-descriptive.
+ */
+ already_AddRefed<Document> CreateStaticClone(
+ nsIDocShell* aCloneContainer, nsIDocumentViewer* aDocumentViewer,
+ nsIPrintSettings* aPrintSettings, bool* aOutHasInProcessPrintCallbacks);
+
+ /**
+ * If this document is a static clone, this returns the original
+ * document.
+ */
+ Document* GetOriginalDocument() const {
+ MOZ_ASSERT(!mOriginalDocument || !mOriginalDocument->GetOriginalDocument());
+ return mOriginalDocument;
+ }
+
+ /**
+ * If this document is a static clone, let the original document know that
+ * we're going away and then release our reference to it.
+ */
+ void UnlinkOriginalDocumentIfStatic();
+
+ /**
+ * These are called by the parser as it encounters <picture> tags, the end of
+ * said tags, and possible picture <source srcset> sources respectively. These
+ * are used to inform ResolvePreLoadImage() calls. Unset attributes are
+ * expected to be marked void.
+ *
+ * NOTE that the parser does not attempt to track the current picture nesting
+ * level or whether the given <source> tag is within a picture -- it is only
+ * guaranteed to order these calls properly with respect to
+ * ResolvePreLoadImage.
+ */
+
+ void PreloadPictureOpened() { mPreloadPictureDepth++; }
+
+ void PreloadPictureClosed();
+
+ void PreloadPictureImageSource(const nsAString& aSrcsetAttr,
+ const nsAString& aSizesAttr,
+ const nsAString& aTypeAttr,
+ const nsAString& aMediaAttr);
+
+ /**
+ * Called by the parser to resolve an image for preloading. The parser will
+ * call the PreloadPicture* functions to inform us of possible <picture>
+ * nesting and possible sources, which are used to inform URL selection
+ * responsive <picture> or <img srcset> images. Unset attributes are expected
+ * to be marked void.
+ * If this image is for <picture> or <img srcset>, aIsImgSet will be set to
+ * true, false otherwise.
+ */
+ already_AddRefed<nsIURI> ResolvePreloadImage(nsIURI* aBaseURI,
+ const nsAString& aSrcAttr,
+ const nsAString& aSrcsetAttr,
+ const nsAString& aSizesAttr,
+ bool* aIsImgSet);
+ /**
+ * Called by nsParser to preload images. Can be removed and code moved
+ * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
+ * parser-module is linked with gklayout-module. aCrossOriginAttr should
+ * be a void string if the attr is not present.
+ * aIsImgSet is the value got from calling ResolvePreloadImage, it is true
+ * when this image is for loading <picture> or <img srcset> images.
+ */
+ void MaybePreLoadImage(nsIURI* uri, const nsAString& aCrossOriginAttr,
+ ReferrerPolicyEnum aReferrerPolicy, bool aIsImgSet,
+ bool aLinkPreload);
+ void PreLoadImage(nsIURI* uri, const nsAString& aCrossOriginAttr,
+ ReferrerPolicyEnum aReferrerPolicy, bool aIsImgSet,
+ bool aLinkPreload, uint64_t aEarlyHintPreloaderId);
+
+ /**
+ * Called by images to forget an image preload when they start doing
+ * the real load.
+ */
+ void ForgetImagePreload(nsIURI* aURI);
+
+ /**
+ * Called by the parser or the preload service to preload style sheets.
+ * aCrossOriginAttr should be a void string if the attr is not present.
+ */
+ SheetPreloadStatus PreloadStyle(nsIURI* aURI, const Encoding* aEncoding,
+ const nsAString& aCrossOriginAttr,
+ ReferrerPolicyEnum aReferrerPolicy,
+ const nsAString& aNonce,
+ const nsAString& aIntegrity,
+ css::StylePreloadKind,
+ uint64_t aEarlyHintPreloaderId,
+ const nsAString& aFetchPriority);
+
+ /**
+ * Called by the chrome registry to load style sheets.
+ *
+ * This always does a synchronous load, and parses as a normal document sheet.
+ */
+ RefPtr<StyleSheet> LoadChromeSheetSync(nsIURI* aURI);
+
+ /**
+ * Returns true if the locale used for the document specifies a direction of
+ * right to left. For chrome documents, this comes from the chrome registry.
+ * This is used to determine the current state for the :-moz-locale-dir
+ * pseudoclass so once can know whether a document is expected to be rendered
+ * left-to-right or right-to-left.
+ */
+ bool IsDocumentRightToLeft();
+
+ /**
+ * Called by Parser for link rel=preconnect
+ */
+ void MaybePreconnect(nsIURI* uri, CORSMode aCORSMode);
+
+ /**
+ * Set the document's pending state object (as serialized using structured
+ * clone).
+ */
+ void SetStateObject(nsIStructuredCloneContainer* scContainer);
+
+ /**
+ * Set the document's pending state object to the same state object as
+ * aDocument.
+ */
+ void SetStateObjectFrom(Document* aDocument) {
+ SetStateObject(aDocument->mStateObjectContainer);
+ }
+
+ /**
+ * Returns true if there is a lightweight theme specified. This is used to
+ * determine the state of the :-moz-lwtheme pseudo-class.
+ */
+ bool ComputeDocumentLWTheme() const;
+ void ResetDocumentLWTheme() {
+ UpdateDocumentStates(DocumentState::LWTHEME, true);
+ }
+
+ // Whether we're a media document or not.
+ enum class MediaDocumentKind {
+ NotMedia,
+ Video,
+ Image,
+ Plugin,
+ };
+
+ virtual enum MediaDocumentKind MediaDocumentKind() const {
+ return MediaDocumentKind::NotMedia;
+ }
+
+ DocumentState State() const { return mState; }
+
+ nsISupports* GetCurrentContentSink();
+
+ void ElementWithAutoFocusInserted(Element* aAutoFocusCandidate);
+ MOZ_CAN_RUN_SCRIPT void FlushAutoFocusCandidates();
+ void ScheduleFlushAutoFocusCandidates();
+ bool HasAutoFocusCandidates() const {
+ return !mAutoFocusCandidates.IsEmpty();
+ }
+
+ void SetAutoFocusFired();
+
+ void SetScrollToRef(nsIURI* aDocumentURI);
+ MOZ_CAN_RUN_SCRIPT void ScrollToRef();
+ void ResetScrolledToRefAlready() { mScrolledToRefAlready = false; }
+
+ void SetChangeScrollPosWhenScrollingToRef(bool aValue) {
+ mChangeScrollPosWhenScrollingToRef = aValue;
+ }
+
+ using DocumentOrShadowRoot::GetElementById;
+ using DocumentOrShadowRoot::GetElementsByClassName;
+ using DocumentOrShadowRoot::GetElementsByTagName;
+ using DocumentOrShadowRoot::GetElementsByTagNameNS;
+
+ DocumentTimeline* Timeline();
+ LinkedList<DocumentTimeline>& Timelines() { return mTimelines; }
+ void UpdateHiddenByContentVisibilityForAnimations();
+
+ SVGSVGElement* GetSVGRootElement() const;
+
+ nsresult ScheduleFrameRequestCallback(FrameRequestCallback& aCallback,
+ int32_t* aHandle);
+ void CancelFrameRequestCallback(int32_t aHandle);
+
+ /**
+ * Returns true if the handle refers to a callback that was canceled that
+ * we did not find in our list of callbacks (e.g. because it is one of those
+ * in the set of callbacks currently queued to be run).
+ */
+ bool IsCanceledFrameRequestCallback(int32_t aHandle) const;
+
+ /**
+ * Put this document's frame request callbacks into the provided
+ * list, and forget about them.
+ */
+ void TakeFrameRequestCallbacks(nsTArray<FrameRequest>& aCallbacks);
+
+ /**
+ * @return true if this document's frame request callbacks should be
+ * throttled. We throttle requestAnimationFrame for documents which aren't
+ * visible (e.g. scrolled out of the viewport).
+ */
+ bool ShouldThrottleFrameRequests() const;
+
+ // This returns true when the document tree is being teared down.
+ bool InUnlinkOrDeletion() { return mInUnlinkOrDeletion; }
+
+ dom::ImageTracker* ImageTracker();
+
+ // Adds an element to mResponsiveContent when the element is
+ // added to the tree.
+ void AddResponsiveContent(HTMLImageElement* aContent) {
+ MOZ_ASSERT(aContent);
+ mResponsiveContent.Insert(aContent);
+ }
+
+ // Removes an element from mResponsiveContent when the element is
+ // removed from the tree.
+ void RemoveResponsiveContent(HTMLImageElement* aContent) {
+ MOZ_ASSERT(aContent);
+ mResponsiveContent.Remove(aContent);
+ }
+
+ void ScheduleSVGUseElementShadowTreeUpdate(SVGUseElement&);
+ void UnscheduleSVGUseElementShadowTreeUpdate(SVGUseElement& aElement) {
+ mSVGUseElementsNeedingShadowTreeUpdate.Remove(&aElement);
+ }
+
+ bool SVGUseElementNeedsShadowTreeUpdate(SVGUseElement& aElement) const {
+ return mSVGUseElementsNeedingShadowTreeUpdate.Contains(&aElement);
+ }
+
+ using ShadowRootSet = nsTHashSet<ShadowRoot*>;
+
+ void AddComposedDocShadowRoot(ShadowRoot& aShadowRoot) {
+ mComposedShadowRoots.Insert(&aShadowRoot);
+ }
+
+ void RemoveComposedDocShadowRoot(ShadowRoot& aShadowRoot) {
+ mComposedShadowRoots.Remove(&aShadowRoot);
+ }
+
+ // If you're considering using this, you probably want to use
+ // ShadowRoot::IsComposedDocParticipant instead. This is just for
+ // sanity-checking.
+ bool IsComposedDocShadowRoot(ShadowRoot& aShadowRoot) {
+ return mComposedShadowRoots.Contains(&aShadowRoot);
+ }
+
+ const ShadowRootSet& ComposedShadowRoots() const {
+ return mComposedShadowRoots;
+ }
+
+ // WebIDL method for chrome code.
+ void GetConnectedShadowRoots(nsTArray<RefPtr<ShadowRoot>>&) const;
+
+ // Notifies any responsive content added by AddResponsiveContent upon media
+ // features values changing.
+ void NotifyMediaFeatureValuesChanged();
+
+ nsresult GetStateObject(JS::MutableHandle<JS::Value> aState);
+
+ nsDOMNavigationTiming* GetNavigationTiming() const { return mTiming; }
+
+ void SetNavigationTiming(nsDOMNavigationTiming* aTiming);
+
+ nsContentList* ImageMapList();
+
+ // Add aLink to the set of links that need their status resolved.
+ void RegisterPendingLinkUpdate(Link* aLink);
+
+ // Update state on links in mLinksToUpdate.
+ void FlushPendingLinkUpdates();
+
+ bool HasWarnedAbout(DeprecatedOperations aOperation) const;
+ void WarnOnceAbout(
+ DeprecatedOperations aOperation, bool asError = false,
+ const nsTArray<nsString>& aParams = nsTArray<nsString>()) const;
+
+#define DOCUMENT_WARNING(_op) e##_op,
+ enum DocumentWarnings {
+#include "nsDocumentWarningList.h"
+ eDocumentWarningCount
+ };
+#undef DOCUMENT_WARNING
+ bool HasWarnedAbout(DocumentWarnings aWarning) const;
+ void WarnOnceAbout(
+ DocumentWarnings aWarning, bool asError = false,
+ const nsTArray<nsString>& aParams = nsTArray<nsString>()) const;
+
+ // This method may fire a DOM event; if it does so it will happen
+ // synchronously.
+ //
+ // Whether the event fires is controlled by the argument.
+ enum class DispatchVisibilityChange { No, Yes };
+ void UpdateVisibilityState(
+ DispatchVisibilityChange = DispatchVisibilityChange::Yes);
+
+ // Posts an event to call UpdateVisibilityState.
+ void PostVisibilityUpdateEvent();
+
+ bool IsSyntheticDocument() const { return mIsSyntheticDocument; }
+
+ // Adds the size of a given node, which must not be a document node, to the
+ // window sizes passed-in.
+ static void AddSizeOfNodeTree(nsINode&, nsWindowSizes&);
+
+ // Note: Document is a sub-class of nsINode, which has a
+ // SizeOfExcludingThis function. However, because Document objects can
+ // only appear at the top of the DOM tree, we have a specialized measurement
+ // function which returns multiple sizes.
+ virtual void DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const;
+ // DocAddSizeOfIncludingThis doesn't need to be overridden by sub-classes
+ // because Document inherits from nsINode; see the comment above the
+ // declaration of nsINode::SizeOfIncludingThis.
+ virtual void DocAddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const;
+
+ void ConstructUbiNode(void* storage) override;
+
+ bool MayHaveDOMMutationObservers() { return mMayHaveDOMMutationObservers; }
+
+ void SetMayHaveDOMMutationObservers() { mMayHaveDOMMutationObservers = true; }
+
+ bool MayHaveAnimationObservers() { return mMayHaveAnimationObservers; }
+
+ void SetMayHaveAnimationObservers() { mMayHaveAnimationObservers = true; }
+
+ bool IsInSyncOperation() { return mInSyncOperationCount != 0; }
+
+ void SetIsInSyncOperation(bool aSync);
+
+ bool CreatingStaticClone() const { return mCreatingStaticClone; }
+
+ /**
+ * Creates a new element in the HTML namespace with a local name given by
+ * aTag.
+ */
+ already_AddRefed<Element> CreateHTMLElement(nsAtom* aTag);
+
+ // WebIDL API
+ nsIGlobalObject* GetParentObject() const { return GetScopeObject(); }
+ static already_AddRefed<Document> Constructor(const GlobalObject& aGlobal,
+ ErrorResult& rv);
+ DOMImplementation* GetImplementation(ErrorResult& rv);
+ [[nodiscard]] nsresult GetURL(nsString& retval) const;
+ [[nodiscard]] nsresult GetDocumentURI(nsString& retval) const;
+ // Return the URI for the document.
+ // The returned value may differ if the document is loaded via XHR, and
+ // when accessed from chrome privileged script and
+ // from content privileged script for compatibility.
+ void GetDocumentURIFromJS(nsString& aDocumentURI, CallerType aCallerType,
+ ErrorResult& aRv) const;
+ void GetCompatMode(nsString& retval) const;
+ void GetCharacterSet(nsAString& retval) const;
+ // Skip GetContentType, because our NS_IMETHOD version above works fine here.
+ // GetDoctype defined above
+ Element* GetDocumentElement() const { return GetRootElement(); }
+
+ WindowContext* GetTopLevelWindowContext() const;
+
+ // If the top-level ancestor content document for this document is in the same
+ // process, returns it. Otherwise, returns null. This function is not
+ // Fission-compatible, and should not be used in new code.
+ Document* GetTopLevelContentDocumentIfSameProcess();
+ const Document* GetTopLevelContentDocumentIfSameProcess() const;
+
+ // Returns the associated app window if this is a top-level chrome document,
+ // null otherwise.
+ already_AddRefed<nsIAppWindow> GetAppWindowIfToplevelChrome() const;
+
+ already_AddRefed<Element> CreateElement(
+ const nsAString& aTagName, const ElementCreationOptionsOrString& aOptions,
+ ErrorResult& rv);
+ already_AddRefed<Element> CreateElementNS(
+ const nsAString& aNamespaceURI, const nsAString& aQualifiedName,
+ const ElementCreationOptionsOrString& aOptions, ErrorResult& rv);
+ already_AddRefed<Element> CreateXULElement(
+ const nsAString& aTagName, const ElementCreationOptionsOrString& aOptions,
+ ErrorResult& aRv);
+ already_AddRefed<DocumentFragment> CreateDocumentFragment() const;
+ already_AddRefed<nsTextNode> CreateTextNode(const nsAString& aData) const;
+ already_AddRefed<nsTextNode> CreateEmptyTextNode() const;
+ already_AddRefed<Comment> CreateComment(const nsAString& aData) const;
+ already_AddRefed<ProcessingInstruction> CreateProcessingInstruction(
+ const nsAString& target, const nsAString& data, ErrorResult& rv) const;
+ already_AddRefed<nsINode> ImportNode(nsINode& aNode, bool aDeep,
+ ErrorResult& rv) const;
+ // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsINode* AdoptNode(
+ nsINode& aAdoptedNode, ErrorResult& rv, bool aAcceptShadowRoot = false);
+ already_AddRefed<Event> CreateEvent(const nsAString& aEventType,
+ CallerType aCallerType,
+ ErrorResult& rv) const;
+ already_AddRefed<nsRange> CreateRange(ErrorResult& rv);
+ already_AddRefed<NodeIterator> CreateNodeIterator(nsINode& aRoot,
+ uint32_t aWhatToShow,
+ NodeFilter* aFilter,
+ ErrorResult& rv) const;
+ already_AddRefed<TreeWalker> CreateTreeWalker(nsINode& aRoot,
+ uint32_t aWhatToShow,
+ NodeFilter* aFilter,
+ ErrorResult& rv) const;
+ // Deprecated WebIDL bits
+ already_AddRefed<CDATASection> CreateCDATASection(const nsAString& aData,
+ ErrorResult& rv);
+ already_AddRefed<Attr> CreateAttribute(const nsAString& aName,
+ ErrorResult& rv);
+ already_AddRefed<Attr> CreateAttributeNS(const nsAString& aNamespaceURI,
+ const nsAString& aQualifiedName,
+ ErrorResult& rv);
+ void GetInputEncoding(nsAString& aInputEncoding) const;
+ already_AddRefed<Location> GetLocation() const;
+ void GetDomain(nsAString& aDomain);
+ void SetDomain(const nsAString& aDomain, mozilla::ErrorResult& rv);
+ void GetCookie(nsAString& aCookie, mozilla::ErrorResult& rv);
+ void SetCookie(const nsAString& aCookie, mozilla::ErrorResult& rv);
+ void GetReferrer(nsAString& aReferrer) const;
+ void GetLastModified(nsAString& aLastModified) const;
+ void GetReadyState(nsAString& aReadyState) const;
+
+ void GetTitle(nsAString& aTitle);
+ void SetTitle(const nsAString& aTitle, ErrorResult& rv);
+ void GetDir(nsAString& aDirection) const;
+ void SetDir(const nsAString& aDirection);
+ nsIHTMLCollection* Images();
+ nsIHTMLCollection* Embeds();
+ nsIHTMLCollection* Plugins() { return Embeds(); }
+ nsIHTMLCollection* Links();
+ nsIHTMLCollection* Forms();
+ nsIHTMLCollection* Scripts();
+ already_AddRefed<nsContentList> GetElementsByName(const nsAString& aName) {
+ return GetFuncStringContentList<nsCachableElementsByNameNodeList>(
+ this, MatchNameAttribute, nullptr, UseExistingNameString, aName);
+ }
+ Document* Open(const mozilla::dom::Optional<nsAString>& /* unused */,
+ const mozilla::dom::Optional<nsAString>& /* unused */,
+ mozilla::ErrorResult& aError);
+ mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> Open(
+ const nsAString& aURL, const nsAString& aName, const nsAString& aFeatures,
+ mozilla::ErrorResult& rv);
+ void Close(mozilla::ErrorResult& rv);
+ void Write(const mozilla::dom::Sequence<nsString>& aText,
+ mozilla::ErrorResult& rv);
+ void Writeln(const mozilla::dom::Sequence<nsString>& aText,
+ mozilla::ErrorResult& rv);
+ Nullable<WindowProxyHolder> GetDefaultView() const;
+ Element* GetActiveElement();
+ enum class IncludeChromeOnly : bool { No, Yes };
+ // TODO(emilio): Audit callers and remove the default argument, some seem like
+ // they could want the IncludeChromeOnly::Yes version.
+ nsIContent* GetUnretargetedFocusedContent(
+ IncludeChromeOnly = IncludeChromeOnly::No) const;
+ /**
+ * Return true if this document or a subdocument has focus.
+ */
+ bool HasFocus(ErrorResult& rv) const;
+
+ /**
+ * Return true if this document itself has focus.
+ */
+ bool ThisDocumentHasFocus() const;
+
+ void GetDesignMode(nsAString& aDesignMode);
+ void SetDesignMode(const nsAString& aDesignMode,
+ nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& rv);
+ void SetDesignMode(const nsAString& aDesignMode,
+ const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+ mozilla::ErrorResult& rv);
+ MOZ_CAN_RUN_SCRIPT
+ bool ExecCommand(const nsAString& aHTMLCommandName, bool aShowUI,
+ const nsAString& aValue, nsIPrincipal& aSubjectPrincipal,
+ mozilla::ErrorResult& aRv);
+ MOZ_CAN_RUN_SCRIPT bool QueryCommandEnabled(const nsAString& aHTMLCommandName,
+ nsIPrincipal& aSubjectPrincipal,
+ mozilla::ErrorResult& aRv);
+ MOZ_CAN_RUN_SCRIPT bool QueryCommandIndeterm(
+ const nsAString& aHTMLCommandName, mozilla::ErrorResult& aRv);
+ MOZ_CAN_RUN_SCRIPT bool QueryCommandState(const nsAString& aHTMLCommandName,
+ mozilla::ErrorResult& aRv);
+ MOZ_CAN_RUN_SCRIPT bool QueryCommandSupported(
+ const nsAString& aHTMLCommandName, mozilla::dom::CallerType aCallerType,
+ mozilla::ErrorResult& aRv);
+ MOZ_CAN_RUN_SCRIPT void QueryCommandValue(const nsAString& aHTMLCommandName,
+ nsAString& aValue,
+ mozilla::ErrorResult& aRv);
+ nsIHTMLCollection* Applets();
+ nsIHTMLCollection* Anchors();
+ TimeStamp LastFocusTime() const;
+ void SetLastFocusTime(const TimeStamp& aFocusTime);
+ // Event handlers are all on nsINode already
+ bool MozSyntheticDocument() const { return IsSyntheticDocument(); }
+ Element* GetCurrentScript();
+ void ReleaseCapture() const;
+ void MozSetImageElement(const nsAString& aImageElementId, Element* aElement);
+ nsIURI* GetDocumentURIObject() const;
+ // Not const because all the fullscreen goop is not const
+ const char* GetFullscreenError(CallerType);
+ bool FullscreenEnabled(CallerType aCallerType) {
+ return !GetFullscreenError(aCallerType);
+ }
+
+ void GetWireframeWithoutFlushing(bool aIncludeNodes, Nullable<Wireframe>&);
+
+ MOZ_CAN_RUN_SCRIPT void GetWireframe(bool aIncludeNodes,
+ Nullable<Wireframe>&);
+
+ // Hides all popovers until the given end point, see
+ // https://html.spec.whatwg.org/multipage/popover.html#hide-all-popovers-until
+ MOZ_CAN_RUN_SCRIPT void HideAllPopoversUntil(nsINode& aEndpoint,
+ bool aFocusPreviousElement,
+ bool aFireEvents);
+
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void HideAllPopoversWithoutRunningScript();
+ // Hides the given popover element, see
+ // https://html.spec.whatwg.org/multipage/popover.html#hide-popover-algorithm
+ MOZ_CAN_RUN_SCRIPT void HidePopover(Element& popover,
+ bool aFocusPreviousElement,
+ bool aFireEvents, ErrorResult& aRv);
+
+ // Returns a list of all the elements in the Document's top layer whose
+ // popover attribute is in the auto state.
+ // See https://html.spec.whatwg.org/multipage/popover.html#auto-popover-list
+ nsTArray<Element*> AutoPopoverList() const;
+
+ // Return document's auto popover list's last element.
+ // See
+ // https://html.spec.whatwg.org/multipage/popover.html#topmost-auto-popover
+ Element* GetTopmostAutoPopover() const;
+
+ // Adds/removes an element to/from the auto popover list.
+ void AddToAutoPopoverList(Element&);
+ void RemoveFromAutoPopoverList(Element&);
+
+ void AddPopoverToTopLayer(Element&);
+ void RemovePopoverFromTopLayer(Element&);
+
+ Element* GetTopLayerTop();
+ // Return the fullscreen element in the top layer
+ Element* GetUnretargetedFullscreenElement() const;
+ bool Fullscreen() const { return !!GetUnretargetedFullscreenElement(); }
+ already_AddRefed<Promise> ExitFullscreen(ErrorResult&);
+ void ExitPointerLock() { PointerLockManager::Unlock(this); }
+ void GetFgColor(nsAString& aFgColor);
+ void SetFgColor(const nsAString& aFgColor);
+ void GetLinkColor(nsAString& aLinkColor);
+ void SetLinkColor(const nsAString& aLinkColor);
+ void GetVlinkColor(nsAString& aAvlinkColor);
+ void SetVlinkColor(const nsAString& aVlinkColor);
+ void GetAlinkColor(nsAString& aAlinkColor);
+ void SetAlinkColor(const nsAString& aAlinkColor);
+ void GetBgColor(nsAString& aBgColor);
+ void SetBgColor(const nsAString& aBgColor);
+ void Clear() const {
+ // Deprecated
+ }
+ void CaptureEvents();
+ void ReleaseEvents();
+
+ mozilla::dom::HTMLAllCollection* All();
+
+ static bool DocumentSupportsL10n(JSContext* aCx, JSObject* aObject);
+ static bool AreWebAnimationsTimelinesEnabled(JSContext* aCx,
+ JSObject* aObject);
+ // Checks that the caller is either chrome or some addon.
+ static bool IsCallerChromeOrAddon(JSContext* aCx, JSObject* aObject);
+
+ bool Hidden() const { return mVisibilityState != VisibilityState::Visible; }
+ dom::VisibilityState VisibilityState() const { return mVisibilityState; }
+
+ public:
+ void GetSelectedStyleSheetSet(nsAString& aSheetSet);
+ void SetSelectedStyleSheetSet(const nsAString& aSheetSet);
+ void GetLastStyleSheetSet(nsAString& aSheetSet) {
+ aSheetSet = mLastStyleSheetSet;
+ }
+ const nsString& GetCurrentStyleSheetSet() const {
+ return mLastStyleSheetSet.IsEmpty() ? mPreferredStyleSheetSet
+ : mLastStyleSheetSet;
+ }
+ void SetPreferredStyleSheetSet(const nsAString&);
+ void GetPreferredStyleSheetSet(nsAString& aSheetSet) {
+ aSheetSet = mPreferredStyleSheetSet;
+ }
+ DOMStringList* StyleSheetSets();
+ void EnableStyleSheetsForSet(const nsAString& aSheetSet);
+
+ /**
+ * Retrieve the location of the caret position (DOM node and character
+ * offset within that node), given a point.
+ *
+ * @param aX Horizontal point at which to determine the caret position, in
+ * page coordinates.
+ * @param aY Vertical point at which to determine the caret position, in
+ * page coordinates.
+ */
+ already_AddRefed<nsDOMCaretPosition> CaretPositionFromPoint(float aX,
+ float aY);
+
+ Element* GetScrollingElement();
+ // A way to check whether a given element is what would get returned from
+ // GetScrollingElement. It can be faster than comparing to the return value
+ // of GetScrollingElement() due to being able to avoid flushes in various
+ // cases. This method assumes that null is NOT passed.
+ bool IsScrollingElement(Element* aElement);
+
+ // QuerySelector and QuerySelectorAll already defined on nsINode
+
+ UniquePtr<XPathExpression> CreateExpression(const nsAString& aExpression,
+ XPathNSResolver* aResolver,
+ ErrorResult& rv);
+ nsINode* CreateNSResolver(nsINode& aNodeResolver);
+ already_AddRefed<XPathResult> Evaluate(
+ JSContext* aCx, const nsAString& aExpression, nsINode& aContextNode,
+ XPathNSResolver* aResolver, uint16_t aType, JS::Handle<JSObject*> aResult,
+ ErrorResult& rv);
+ // Touch event handlers already on nsINode
+ already_AddRefed<Touch> CreateTouch(nsGlobalWindowInner* aView,
+ EventTarget* aTarget, int32_t aIdentifier,
+ int32_t aPageX, int32_t aPageY,
+ int32_t aScreenX, int32_t aScreenY,
+ int32_t aClientX, int32_t aClientY,
+ int32_t aRadiusX, int32_t aRadiusY,
+ float aRotationAngle, float aForce);
+ already_AddRefed<TouchList> CreateTouchList();
+ already_AddRefed<TouchList> CreateTouchList(
+ Touch& aTouch, const Sequence<OwningNonNull<Touch>>& aTouches);
+ already_AddRefed<TouchList> CreateTouchList(
+ const Sequence<OwningNonNull<Touch>>& aTouches);
+
+ void SetStyleSheetChangeEventsEnabled(bool aValue) {
+ mStyleSheetChangeEventsEnabled = aValue;
+ }
+
+ bool StyleSheetChangeEventsEnabled() const {
+ return mStyleSheetChangeEventsEnabled;
+ }
+
+ void SetDevToolsAnonymousAndShadowEventsEnabled(bool aValue) {
+ mDevToolsAnonymousAndShadowEventsEnabled = aValue;
+ }
+ bool DevToolsAnonymousAndShadowEventsEnabled() const {
+ return mDevToolsAnonymousAndShadowEventsEnabled;
+ }
+
+ already_AddRefed<Promise> BlockParsing(Promise& aPromise,
+ const BlockParsingOptions& aOptions,
+ ErrorResult& aRv);
+
+ already_AddRefed<nsIURI> GetMozDocumentURIIfNotForErrorPages();
+
+ Promise* GetDocumentReadyForIdle(ErrorResult& aRv);
+
+ void BlockUnblockOnloadForSystemOrPDFJS(bool aBlock) {
+ if (aBlock) {
+ BlockOnload();
+ } else {
+ UnblockOnload(/* aFireSync = */ false);
+ }
+ }
+
+ nsIDOMXULCommandDispatcher* GetCommandDispatcher();
+ bool HasXULBroadcastManager() const { return mXULBroadcastManager; };
+ void InitializeXULBroadcastManager();
+ XULBroadcastManager* GetXULBroadcastManager() const {
+ return mXULBroadcastManager;
+ }
+ nsINode* GetPopupRangeParent(ErrorResult& aRv);
+ int32_t GetPopupRangeOffset(ErrorResult& aRv);
+
+ bool DevToolsWatchingDOMMutations() const {
+ return mDevToolsWatchingDOMMutations;
+ }
+ void SetDevToolsWatchingDOMMutations(bool aValue);
+
+ void MaybeWarnAboutZoom();
+
+ // https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes
+ void EvaluateMediaQueriesAndReportChanges(bool aRecurse);
+
+ nsTHashSet<RefPtr<WakeLockSentinel>>& ActiveWakeLocks(WakeLockType aType);
+
+ void UnlockAllWakeLocks(WakeLockType aType);
+
+ // ParentNode
+ nsIHTMLCollection* Children();
+ uint32_t ChildElementCount();
+
+ /**
+ * Asserts IsHTMLOrXHTML, and can't return null.
+ * Defined inline in nsHTMLDocument.h
+ */
+ inline nsHTMLDocument* AsHTMLDocument();
+ inline const nsHTMLDocument* AsHTMLDocument() const;
+
+ /**
+ * Asserts IsSVGDocument, and can't return null.
+ * Defined inline in SVGDocument.h
+ */
+ inline SVGDocument* AsSVGDocument();
+ inline const SVGDocument* AsSVGDocument() const;
+
+ /**
+ * Asserts IsImageDocument, and can't return null.
+ * Defined inline in ImageDocument.h
+ */
+ inline ImageDocument* AsImageDocument();
+ inline const ImageDocument* AsImageDocument() const;
+
+ gfxUserFontSet* GetUserFontSet();
+ void FlushUserFontSet();
+ void MarkUserFontSetDirty();
+ FontFaceSet* GetFonts() { return mFontFaceSet; }
+
+ // FontFaceSource
+ FontFaceSet* GetFonts(ErrorResult&) { return Fonts(); }
+ FontFaceSet* Fonts();
+
+ bool DidFireDOMContentLoaded() const { return mDidFireDOMContentLoaded; }
+
+ bool IsSynthesized();
+
+ // Records whether we will track use counters for this document, and if so,
+ // which top-level document that page counters will be accumulated to.
+ //
+ // Informs the parent process that page use counters will be sent once the
+ // document goes away.
+ void InitUseCounters();
+
+ // Reports document use counters via telemetry. This method only has an
+ // effect once per document, and so is called during document destruction.
+ void ReportDocumentUseCounters();
+
+ // Reports largest contentful paint via telemetry. We want the most up to
+ // date value for LCP and so this is called during document destruction.
+ void ReportLCP();
+
+ // Report how lazyload performs for this document.
+ void ReportDocumentLazyLoadCounters();
+
+ // Sends page use counters to the parent process to accumulate against the
+ // top-level document. Must be called while we still have access to our
+ // WindowContext. This method has an effect each time it is called, and we
+ // call it just before the document loses its window.
+ void SendPageUseCounters();
+
+ void SetUseCounter(UseCounter aUseCounter) {
+ mUseCounters[aUseCounter] = true;
+ }
+
+ const StyleUseCounters* GetStyleUseCounters() {
+ return mStyleUseCounters.get();
+ }
+
+ // Propagate our use counters explicitly into the specified referencing
+ // document.
+ //
+ // This is used for SVG image documents, which cannot be enumerated in the
+ // referencing document's ReportUseCounters() like external resource documents
+ // can.
+ void PropagateImageUseCounters(Document* aReferencingDocument);
+
+ // Called to track whether this document has had any interaction.
+ // This is used to track whether we should permit "beforeunload".
+ void SetUserHasInteracted();
+ bool UserHasInteracted() { return mUserHasInteracted; }
+ void ResetUserInteractionTimer();
+
+ // Whether we're cloning the contents of an SVG use element.
+ bool CloningForSVGUse() const { return mCloningForSVGUse; }
+
+ // This should be called when this document receives events which are likely
+ // to be user interaction with the document, rather than the byproduct of
+ // interaction with the browser (i.e. a keypress to scroll the view port,
+ // keyboard shortcuts, etc). This is used to decide whether we should
+ // permit autoplay audible media. This also gesture activates all other
+ // content documents in this tab.
+ void NotifyUserGestureActivation(
+ UserActivation::Modifiers aModifiers = UserActivation::Modifiers::None());
+
+ // This function is used for mochitest only.
+ void ClearUserGestureActivation();
+
+ // Return true if NotifyUserGestureActivation() has been called on any
+ // document in the document tree.
+ bool HasBeenUserGestureActivated();
+
+ // Reture timestamp of last user gesture in milliseconds relative to
+ // navigation start timestamp.
+ DOMHighResTimeStamp LastUserGestureTimeStamp();
+
+ // Return true if there is transient user gesture activation and it hasn't yet
+ // timed out or hasn't been consumed.
+ bool HasValidTransientUserGestureActivation() const;
+
+ // Return true if HasValidTransientUserGestureActivation() would return true,
+ // and consume the activation.
+ bool ConsumeTransientUserGestureActivation();
+
+ bool GetTransientUserGestureActivationModifiers(
+ UserActivation::Modifiers* aModifiers);
+
+ BrowsingContext* GetBrowsingContext() const;
+
+ // This document is a WebExtension page, it might be a background page, a
+ // popup, a visible tab, a visible iframe ...e.t.c.
+ bool IsExtensionPage() const;
+
+ bool HasScriptsBlockedBySandbox() const;
+
+ void ReportHasScrollLinkedEffect(const TimeStamp& aTimeStamp);
+ bool HasScrollLinkedEffect() const;
+
+#ifdef DEBUG
+ void AssertDocGroupMatchesKey() const;
+#endif
+
+ DocGroup* GetDocGroup() const {
+#ifdef DEBUG
+ AssertDocGroupMatchesKey();
+#endif
+ return mDocGroup;
+ }
+
+ DocGroup* GetDocGroupOrCreate();
+
+ /**
+ * If we're a sub-document, the parent document's layout can affect our style
+ * and layout (due to the viewport size, viewport units, media queries...).
+ *
+ * This function returns true if our parent document and our child document
+ * can observe each other. If they cannot, then we don't need to synchronously
+ * update the parent document layout every time the child document may need
+ * up-to-date layout information.
+ */
+ bool StyleOrLayoutObservablyDependsOnParentDocumentLayout() const {
+ return GetInProcessParentDocument() &&
+ GetDocGroup() == GetInProcessParentDocument()->GetDocGroup();
+ }
+
+ void AddIntersectionObserver(DOMIntersectionObserver* aObserver) {
+ MOZ_ASSERT(!mIntersectionObservers.Contains(aObserver),
+ "Intersection observer already in the list");
+ mIntersectionObservers.Insert(aObserver);
+ }
+
+ void RemoveIntersectionObserver(DOMIntersectionObserver* aObserver) {
+ mIntersectionObservers.Remove(aObserver);
+ }
+
+ bool HasIntersectionObservers() const {
+ return !mIntersectionObservers.IsEmpty();
+ }
+
+ void UpdateIntersectionObservations(TimeStamp aNowTime);
+ void ScheduleIntersectionObserverNotification();
+ MOZ_CAN_RUN_SCRIPT void NotifyIntersectionObservers();
+
+ DOMIntersectionObserver* GetLazyLoadObserver() { return mLazyLoadObserver; }
+ DOMIntersectionObserver& EnsureLazyLoadObserver();
+
+ ResizeObserver* GetLastRememberedSizeObserver() {
+ return mLastRememberedSizeObserver;
+ }
+ ResizeObserver& EnsureLastRememberedSizeObserver();
+ void ObserveForLastRememberedSize(Element&);
+ void UnobserveForLastRememberedSize(Element&);
+
+ // Dispatch a runnable related to the document.
+ nsresult Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) const;
+
+ // The URLs passed to this function should match what
+ // JS::DescribeScriptedCaller() returns, since this API is used to
+ // determine whether some code is being called from a tracking script.
+ void NoteScriptTrackingStatus(const nsACString& aURL, bool isTracking);
+ // The JSContext passed to this method represents the context that we want to
+ // determine if it belongs to a tracker.
+ bool IsScriptTracking(JSContext* aCx) const;
+
+ // ResizeObserver usage.
+ void AddResizeObserver(ResizeObserver&);
+ void RemoveResizeObserver(ResizeObserver&);
+ void ScheduleResizeObserversNotification() const;
+ bool HasResizeObservers() const { return !mResizeObservers.IsEmpty(); }
+ /**
+ * Calls GatherActiveObservations(aDepth) for all ResizeObservers.
+ * All observations in each ResizeObserver with element's depth more than
+ * aDepth will be gathered.
+ */
+ void GatherAllActiveResizeObservations(uint32_t aDepth);
+ /**
+ * Calls BroadcastActiveObservations() for all ResizeObservers.
+ * It also returns the shallowest depth of observed target elements with
+ * active observations from all ResizeObservers or
+ * numeric_limits<uint32_t>::max() if there aren't any active observations
+ * at all.
+ */
+ MOZ_CAN_RUN_SCRIPT uint32_t BroadcastAllActiveResizeObservations();
+ /**
+ * Returns whether there is any ResizeObserver that has active
+ * observations.
+ */
+ bool HasAnyActiveResizeObservations() const;
+ /**
+ * Returns whether there is any ResizeObserver that has skipped observations.
+ */
+ bool HasAnySkippedResizeObservations() const;
+ /**
+ * Determine proximity to viewport for content-visibility: auto elements and
+ * notify resize observers.
+ */
+ MOZ_CAN_RUN_SCRIPT void
+ DetermineProximityToViewportAndNotifyResizeObservers();
+
+ // Getter for PermissionDelegateHandler. Performs lazy initialization.
+ PermissionDelegateHandler* GetPermissionDelegateHandler();
+
+ // Notify the document that a fetch or a XHR request has completed
+ // succesfully in this document. This is used by the password manager to infer
+ // whether a form is submitted.
+ void NotifyFetchOrXHRSuccess();
+
+ // Set whether NotifyFetchOrXHRSuccess should dispatch an event.
+ void SetNotifyFetchSuccess(bool aShouldNotify);
+
+ // When this is set, removing a form or a password field from DOM
+ // sends a Chrome-only event. This is now only used by the password manager
+ // and formautofill.
+ void SetNotifyFormOrPasswordRemoved(bool aShouldNotify);
+
+ // This function is used by HTMLFormElement and HTMLInputElement to determin
+ // whether to send an event when it is removed from DOM.
+ bool ShouldNotifyFormOrPasswordRemoved() const {
+ return mShouldNotifyFormOrPasswordRemoved;
+ }
+
+ HTMLEditor* GetHTMLEditor() const;
+
+ /**
+ * Localization
+ *
+ * For more information on DocumentL10n see
+ * intl/l10n/docs/fluent/tutorial.rst
+ */
+
+ public:
+ /**
+ * This is a public method exposed on Document WebIDL
+ * to chrome only documents.
+ */
+ DocumentL10n* GetL10n() const { return mDocumentL10n.get(); }
+
+ /**
+ * Whether there's any async l10n mutation work pending.
+ *
+ * When this turns false, we fire the L10nMutationsFinished event.
+ */
+ bool HasPendingL10nMutations() const;
+
+ /**
+ * This method should be called when the container
+ * of l10n resources parsing is completed.
+ *
+ * It triggers initial async fetch of the resources
+ * as early as possible.
+ *
+ * In HTML case this is </head>.
+ * In XUL case this is </linkset>.
+ */
+ void OnL10nResourceContainerParsed();
+
+ /**
+ * This method should be called when a link element
+ * with rel="localization" is being added to the
+ * l10n resource container element.
+ */
+ void LocalizationLinkAdded(Element* aLinkElement);
+
+ /**
+ * This method should be called when a link element
+ * with rel="localization" is being removed.
+ */
+ void LocalizationLinkRemoved(Element* aLinkElement);
+
+ /**
+ * This method should be called as soon as the
+ * parsing of the document is completed.
+ *
+ * In HTML/XHTML this happens when we finish parsing
+ * the document element.
+ * In XUL it happens at `DoneWalking`, during
+ * `MozBeforeInitialXULLayout`.
+ */
+ void OnParsingCompleted();
+
+ /**
+ * This method is called when the initial translation
+ * of the document is completed.
+ *
+ * It unblocks the load event if translation was blocking it.
+ *
+ * If the `aL10nCached` is set to `true`, and the document has
+ * a prototype, it will set the `isL10nCached` flag on it.
+ */
+ void InitialTranslationCompleted(bool aL10nCached);
+
+ /**
+ * Returns whether the document allows localization.
+ */
+ bool AllowsL10n() const;
+
+ void SetAllowDeclarativeShadowRoots(bool aAllowDeclarativeShadowRoots);
+ bool AllowsDeclarativeShadowRoots() const;
+
+ protected:
+ RefPtr<DocumentL10n> mDocumentL10n;
+
+ /**
+ * Return true when you want a document without explicitly specified viewport
+ * dimensions/scale to be treated as if "width=device-width" had in fact been
+ * specified.
+ */
+ virtual bool UseWidthDeviceWidthFallbackViewport() const;
+
+ private:
+ bool IsErrorPage() const;
+
+ // Takes the bits from mStyleUseCounters if appropriate, and sets them in
+ // mUseCounters.
+ void SetCssUseCounterBits();
+
+ void ParseWidthAndHeightInMetaViewport(const nsAString& aWidthString,
+ const nsAString& aHeightString,
+ bool aIsAutoScale);
+
+ // Parse scale values in viewport meta tag for a given |aHeaderField| which
+ // represents the scale property and returns the scale value if it's valid.
+ Maybe<LayoutDeviceToScreenScale> ParseScaleInHeader(nsAtom* aHeaderField);
+
+ // Parse scale values in |aViewportMetaData| and set the values in
+ // mScaleMinFloat, mScaleMaxFloat and mScaleFloat respectively.
+ void ParseScalesInViewportMetaData(const ViewportMetaData& aViewportMetaData);
+
+ // Get parent FeaturePolicy from container. The parent FeaturePolicy is
+ // stored in parent iframe or container's browsingContext (cross process)
+ already_AddRefed<mozilla::dom::FeaturePolicy> GetParentFeaturePolicy();
+
+ public:
+ const OriginTrials& Trials() const { return mTrials; }
+
+ private:
+ void DoCacheAllKnownLangPrefs();
+ void RecomputeLanguageFromCharset();
+ bool GetSHEntryHasUserInteraction();
+
+ void AppendAutoFocusCandidateToTopDocument(Element* aAutoFocusCandidate);
+
+ public:
+ void SetMayNeedFontPrefsUpdate() { mMayNeedFontPrefsUpdate = true; }
+
+ bool MayNeedFontPrefsUpdate() { return mMayNeedFontPrefsUpdate; }
+
+ void SetSHEntryHasUserInteraction(bool aHasInteraction);
+
+ nsAtom* GetContentLanguageAsAtomForStyle() const;
+ nsAtom* GetLanguageForStyle() const;
+
+ /**
+ * Fetch the user's font preferences for the given aLanguage's
+ * language group.
+ */
+ const LangGroupFontPrefs* GetFontPrefsForLang(
+ nsAtom* aLanguage, bool* aNeedsToCache = nullptr) const;
+
+ void ForceCacheLang(nsAtom* aLanguage) {
+ if (!mLanguagesUsed.EnsureInserted(aLanguage)) {
+ return;
+ }
+ GetFontPrefsForLang(aLanguage);
+ }
+
+ void CacheAllKnownLangPrefs() {
+ if (!mMayNeedFontPrefsUpdate) {
+ return;
+ }
+ DoCacheAllKnownLangPrefs();
+ }
+
+ nsINode* GetServoRestyleRoot() const { return mServoRestyleRoot; }
+
+ uint32_t GetServoRestyleRootDirtyBits() const {
+ MOZ_ASSERT(mServoRestyleRoot);
+ MOZ_ASSERT(mServoRestyleRootDirtyBits);
+ return mServoRestyleRootDirtyBits;
+ }
+
+ void ClearServoRestyleRoot() {
+ mServoRestyleRoot = nullptr;
+ mServoRestyleRootDirtyBits = 0;
+ }
+
+ inline void SetServoRestyleRoot(nsINode* aRoot, uint32_t aDirtyBits);
+ inline void SetServoRestyleRootDirtyBits(uint32_t aDirtyBits);
+
+ bool ShouldThrowOnDynamicMarkupInsertion() {
+ return mThrowOnDynamicMarkupInsertionCounter;
+ }
+
+ void IncrementThrowOnDynamicMarkupInsertionCounter() {
+ ++mThrowOnDynamicMarkupInsertionCounter;
+ }
+
+ void DecrementThrowOnDynamicMarkupInsertionCounter() {
+ MOZ_ASSERT(mThrowOnDynamicMarkupInsertionCounter);
+ --mThrowOnDynamicMarkupInsertionCounter;
+ }
+
+ bool ShouldIgnoreOpens() const { return mIgnoreOpensDuringUnloadCounter; }
+
+ void IncrementIgnoreOpensDuringUnloadCounter() {
+ ++mIgnoreOpensDuringUnloadCounter;
+ }
+
+ void DecrementIgnoreOpensDuringUnloadCounter() {
+ MOZ_ASSERT(mIgnoreOpensDuringUnloadCounter);
+ --mIgnoreOpensDuringUnloadCounter;
+ }
+
+ mozilla::dom::FeaturePolicy* FeaturePolicy() const;
+
+ /**
+ * Find the (non-anonymous) content in this document for aFrame. It will
+ * be aFrame's content node if that content is in this document and not
+ * anonymous. Otherwise, when aFrame is in a subdocument, we use the frame
+ * element containing the subdocument containing aFrame, and/or find the
+ * nearest non-anonymous ancestor in this document.
+ * Returns null if there is no such element.
+ */
+ nsIContent* GetContentInThisDocument(nsIFrame* aFrame) const;
+
+ void ReportShadowDOMUsage();
+
+ // Sets flags for media telemetry.
+ void SetDocTreeHadMedia();
+
+ dom::XPathEvaluator* XPathEvaluator();
+
+ void MaybeInitializeFinalizeFrameLoaders();
+
+ void SetDelayFrameLoaderInitialization(bool aDelayFrameLoaderInitialization) {
+ mDelayFrameLoaderInitialization = aDelayFrameLoaderInitialization;
+ }
+
+ void SetPrototypeDocument(nsXULPrototypeDocument* aPrototype);
+
+ nsIPermissionDelegateHandler* PermDelegateHandler();
+
+ // Returns whether this is a top-level about:blank page without an opener (and
+ // thus likely not accessible by content). Likely because it shouldn't be used
+ // for security checks for example, see bug 1860098.
+ bool IsLikelyContentInaccessibleTopLevelAboutBlank() const;
+
+ // CSS prefers-color-scheme media feature for this document.
+ enum class IgnoreRFP { No, Yes };
+ ColorScheme PreferredColorScheme(IgnoreRFP = IgnoreRFP::No) const;
+ // Returns the initial color-scheme used for this document based on the
+ // color-scheme meta tag.
+ ColorScheme DefaultColorScheme() const;
+
+ static bool HasRecentlyStartedForegroundLoads();
+
+ static bool AutomaticStorageAccessPermissionCanBeGranted(
+ nsIPrincipal* aPrincipal);
+
+ already_AddRefed<Promise> AddCertException(bool aIsTemporary,
+ ErrorResult& aError);
+
+ void ReloadWithHttpsOnlyException();
+
+ // Subframes need to be static cloned after the main document has been
+ // embedded within a script global. A `PendingFrameStaticClone` is a static
+ // clone which has not yet been performed.
+ //
+ // The getter returns a direct reference to an internal array which is
+ // manipulated from within printing code.
+ struct PendingFrameStaticClone {
+ PendingFrameStaticClone() = default;
+ PendingFrameStaticClone(PendingFrameStaticClone&&) = default;
+ PendingFrameStaticClone& operator=(PendingFrameStaticClone&&) = default;
+ ~PendingFrameStaticClone();
+
+ RefPtr<nsFrameLoaderOwner> mElement;
+ RefPtr<nsFrameLoader> mStaticCloneOf;
+ };
+ void AddPendingFrameStaticClone(nsFrameLoaderOwner* aElement,
+ nsFrameLoader* aStaticCloneOf);
+
+ bool ShouldAvoidNativeTheme() const;
+
+ static bool IsValidDomain(nsIURI* aOrigHost, nsIURI* aNewURI);
+
+ // Inform a parent document that a BrowserBridgeChild has been created for
+ // an OOP sub-document.
+ // (This is the OOP counterpart to nsDocLoader::ChildEnteringOnload)
+ void OOPChildLoadStarted(BrowserBridgeChild* aChild);
+
+ // Inform a parent document that the BrowserBridgeChild for one of its
+ // OOP sub-documents is done calling its onload handler.
+ // (This is the OOP counterpart to nsDocLoader::ChildDoneWithOnload)
+ void OOPChildLoadDone(BrowserBridgeChild* aChild);
+
+ void ClearOOPChildrenLoading();
+
+ bool HasOOPChildrenLoading() { return !mOOPChildrenLoading.IsEmpty(); }
+
+ void SetDidHitCompleteSheetCache() { mDidHitCompleteSheetCache = true; }
+
+ bool DidHitCompleteSheetCache() const { return mDidHitCompleteSheetCache; }
+
+ /**
+ * Get the `HighlightRegistry` which contains all highlights associated
+ * with this document.
+ */
+ class HighlightRegistry& HighlightRegistry();
+
+ bool ShouldResistFingerprinting(RFPTarget aTarget) const;
+ bool IsInPrivateBrowsing() const;
+
+ const Maybe<RFPTarget>& GetOverriddenFingerprintingSettings() const {
+ return mOverriddenFingerprintingSettings;
+ }
+
+ // Recompute the current resist fingerprinting state. Returns true when
+ // the state was changed.
+ bool RecomputeResistFingerprinting();
+
+ void RecordCanvasUsage(CanvasUsage& aUsage);
+ void RecordFontFingerprinting();
+
+ bool MayHaveDOMActivateListeners() const;
+
+ void DropStyleSet();
+
+ protected:
+ // Returns the WindowContext for the document that we will contribute
+ // page use counters to.
+ WindowContext* GetWindowContextForPageUseCounters() const;
+
+ void DoUpdateSVGUseElementShadowTrees();
+
+ already_AddRefed<nsIPrincipal> MaybeDowngradePrincipal(
+ nsIPrincipal* aPrincipal);
+
+ void EnsureOnloadBlocker();
+
+ void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages);
+
+ // Returns true if the scheme for the url for this document is "about".
+ bool IsAboutPage() const;
+
+ bool ContainsEMEContent();
+ bool ContainsMSEContent();
+
+ /**
+ * Returns the title element of the document as defined by the HTML
+ * specification, or null if there isn't one. For documents whose root
+ * element is an <svg:svg>, this is the first <svg:title> element that's a
+ * child of the root. For other documents, it's the first HTML title element
+ * in the document.
+ */
+ Element* GetTitleElement();
+
+ void RecordNavigationTiming(ReadyState aReadyState);
+
+ // Recomputes the visibility state but doesn't set the new value.
+ dom::VisibilityState ComputeVisibilityState() const;
+
+ // Since we wouldn't automatically play media from non-visited page, we need
+ // to notify window when the page was first visited.
+ void MaybeActiveMediaComponents();
+
+ // Apply the fullscreen state to the document, and trigger related
+ // events. It returns false if the fullscreen element ready check
+ // fails and nothing gets changed.
+ bool ApplyFullscreen(UniquePtr<FullscreenRequest>);
+
+ void RemoveDocStyleSheetsFromStyleSets();
+ void ResetStylesheetsToURI(nsIURI* aURI);
+ void FillStyleSet();
+ void FillStyleSetUserAndUASheets();
+ void FillStyleSetDocumentSheets();
+ void CompatibilityModeChanged();
+ bool NeedsQuirksSheet() const {
+ // SVG documents never load quirk.css.
+ // FIXME(emilio): Can SVG documents be in quirks mode anyway?
+ return mCompatMode == eCompatibility_NavQuirks && !IsSVGDocument();
+ }
+ void AddContentEditableStyleSheetsToStyleSet(bool aDesignMode);
+ void RemoveContentEditableStyleSheets();
+ void AddStyleSheetToStyleSets(StyleSheet&);
+ void RemoveStyleSheetFromStyleSets(StyleSheet&);
+ void NotifyStyleSheetApplicableStateChanged();
+ // Just like EnableStyleSheetsForSet, but doesn't check whether
+ // aSheetSet is null and allows the caller to control whether to set
+ // aSheetSet as the preferred set in the CSSLoader.
+ void EnableStyleSheetsForSetInternal(const nsAString& aSheetSet,
+ bool aUpdateCSSLoader);
+
+ already_AddRefed<nsIURI> GetDomainURI();
+ already_AddRefed<nsIURI> CreateInheritingURIForHost(
+ const nsACString& aHostString);
+ already_AddRefed<nsIURI> RegistrableDomainSuffixOfInternal(
+ const nsAString& aHostSuffixString, nsIURI* aOrigHost);
+
+ void WriteCommon(const nsAString& aText, bool aNewlineTerminate,
+ mozilla::ErrorResult& aRv);
+ // A version of WriteCommon used by WebIDL bindings
+ void WriteCommon(const mozilla::dom::Sequence<nsString>& aText,
+ bool aNewlineTerminate, mozilla::ErrorResult& rv);
+
+ void* GenerateParserKey(void);
+
+ private:
+ // ExecCommandParam indicates how HTMLDocument.execCommand() treats given the
+ // parameter.
+ enum class ExecCommandParam : uint8_t {
+ // Always ignore it.
+ Ignore,
+ // Treat the given parameter as-is. If the command requires it, use it.
+ // Otherwise, ignore it.
+ String,
+ // Always treat it as boolean parameter.
+ Boolean,
+ // Always treat it as boolean, but inverted.
+ InvertedBoolean,
+ };
+
+ using GetEditorCommandFunc = mozilla::EditorCommand*();
+
+ struct InternalCommandData {
+ const char* mXULCommandName;
+ mozilla::Command mCommand; // uint8_t
+ // How ConvertToInternalCommand() to treats aValue.
+ // Its callers don't need to check this.
+ ExecCommandParam mExecCommandParam; // uint8_t
+ GetEditorCommandFunc* mGetEditorCommandFunc;
+ enum class CommandOnTextEditor : uint8_t {
+ Disabled,
+ Enabled,
+ FallThrough, // Not disabled, but handled by HTMLEditor if there is one
+ };
+ CommandOnTextEditor mCommandOnTextEditor;
+
+ InternalCommandData()
+ : mXULCommandName(nullptr),
+ mCommand(mozilla::Command::DoNothing),
+ mExecCommandParam(ExecCommandParam::Ignore),
+ mGetEditorCommandFunc(nullptr),
+ mCommandOnTextEditor(CommandOnTextEditor::Disabled) {}
+ InternalCommandData(const char* aXULCommandName, mozilla::Command aCommand,
+ ExecCommandParam aExecCommandParam,
+ GetEditorCommandFunc aGetEditorCommandFunc,
+ CommandOnTextEditor aCommandOnTextEditor)
+ : mXULCommandName(aXULCommandName),
+ mCommand(aCommand),
+ mExecCommandParam(aExecCommandParam),
+ mGetEditorCommandFunc(aGetEditorCommandFunc),
+ mCommandOnTextEditor(aCommandOnTextEditor) {}
+
+ bool IsAvailableOnlyWhenEditable() const {
+ return mCommand != mozilla::Command::Cut &&
+ mCommand != mozilla::Command::Copy &&
+ mCommand != mozilla::Command::Paste &&
+ mCommand != mozilla::Command::SetDocumentReadOnly &&
+ mCommand != mozilla::Command::SelectAll;
+ }
+ bool IsCutOrCopyCommand() const {
+ return mCommand == mozilla::Command::Cut ||
+ mCommand == mozilla::Command::Copy;
+ }
+ bool IsPasteCommand() const { return mCommand == mozilla::Command::Paste; }
+ };
+
+ /**
+ * AutoEditorCommandTarget considers which editor or global command manager
+ * handles given command.
+ */
+ class MOZ_RAII AutoEditorCommandTarget {
+ public:
+ MOZ_CAN_RUN_SCRIPT AutoEditorCommandTarget(
+ Document& aDocument, const InternalCommandData& aCommandData);
+ AutoEditorCommandTarget() = delete;
+ explicit AutoEditorCommandTarget(const AutoEditorCommandTarget& aOther) =
+ delete;
+
+ bool DoNothing() const { return mDoNothing; }
+ MOZ_CAN_RUN_SCRIPT bool IsEditable(Document* aDocument) const;
+ bool IsEditor() const {
+ MOZ_ASSERT_IF(mEditorCommand, mActiveEditor || mHTMLEditor);
+ return !!mEditorCommand;
+ }
+
+ MOZ_CAN_RUN_SCRIPT bool IsCommandEnabled() const;
+ MOZ_CAN_RUN_SCRIPT nsresult DoCommand(nsIPrincipal* aPrincipal) const;
+ template <typename ParamType>
+ MOZ_CAN_RUN_SCRIPT nsresult DoCommandParam(const ParamType& aParam,
+ nsIPrincipal* aPrincipal) const;
+ MOZ_CAN_RUN_SCRIPT nsresult
+ GetCommandStateParams(nsCommandParams& aParams) const;
+
+ private:
+ // The returned editor's life is guaranteed while this instance is alive.
+ EditorBase* GetTargetEditor() const;
+
+ RefPtr<EditorBase> mActiveEditor;
+ RefPtr<HTMLEditor> mHTMLEditor;
+ RefPtr<EditorCommand> mEditorCommand;
+ const InternalCommandData& mCommandData;
+ bool mDoNothing = false;
+ };
+
+ /**
+ * Helper method to initialize sInternalCommandDataHashtable.
+ */
+ static void EnsureInitializeInternalCommandDataHashtable();
+
+ /**
+ * ConvertToInternalCommand() returns a copy of InternalCommandData instance.
+ * Note that if aAdjustedValue is non-nullptr, this method checks whether
+ * aValue is proper value or not unless InternalCommandData::mExecCommandParam
+ * is ExecCommandParam::Ignore. For example, if aHTMLCommandName is
+ * "defaultParagraphSeparator", the value has to be one of "div", "p" or
+ * "br". If aValue is invalid value for InternalCommandData::mCommand, this
+ * returns a copy of instance created with default constructor. I.e., its
+ * mCommand is set to Command::DoNothing. So, this treats aHTMLCommandName
+ * is unsupported in such case.
+ *
+ * @param aHTMLCommandName Command name in HTML, e.g., used by
+ * execCommand().
+ * @param aValue The value which is set to the 3rd parameter
+ * of execCommand().
+ * @param aAdjustedValue [out] Must be empty string if set non-nullptr.
+ * Will be set to adjusted value for executing
+ * the internal command.
+ * @return Returns a copy of instance created with the
+ * default constructor if there is no
+ * corresponding internal command for
+ * aHTMLCommandName or aValue is invalid for
+ * found internal command when aAdjustedValue
+ * is not nullptr. Otherwise, returns a copy of
+ * instance registered in
+ * sInternalCommandDataHashtable.
+ */
+ static InternalCommandData ConvertToInternalCommand(
+ const nsAString& aHTMLCommandName, const nsAString& aValue = u""_ns,
+ nsAString* aAdjustedValue = nullptr);
+
+ /**
+ * AutoRunningExecCommandMarker is AutoRestorer for mIsRunningExecCommand.
+ * Since it's a bit field, not a bool member, therefore, we cannot use
+ * AutoRestorer for it.
+ */
+ class MOZ_STACK_CLASS AutoRunningExecCommandMarker final {
+ public:
+ AutoRunningExecCommandMarker() = delete;
+ explicit AutoRunningExecCommandMarker(const AutoRunningExecCommandMarker&) =
+ delete;
+ // Guaranteeing the document's lifetime with `MOZ_CAN_RUN_SCRIPT`.
+ MOZ_CAN_RUN_SCRIPT AutoRunningExecCommandMarker(Document& aDocument,
+ nsIPrincipal* aPrincipal);
+ ~AutoRunningExecCommandMarker() {
+ if (mTreatAsUserInput) {
+ mDocument.mIsRunningExecCommandByChromeOrAddon =
+ mHasBeenRunningByChromeOrAddon;
+ } else {
+ mDocument.mIsRunningExecCommandByContent = mHasBeenRunningByContent;
+ }
+ }
+
+ [[nodiscard]] bool IsSafeToRun() const {
+ // We don't allow nested calls of execCommand even if the caller is chrome
+ // script.
+ if (mTreatAsUserInput) {
+ return !mHasBeenRunningByChromeOrAddon && !mHasBeenRunningByContent;
+ }
+ // If current call is by content, we should ignore whether nested with a
+ // call by addon (or chrome script) because the caller wants to emulate
+ // user input for making it undoable. So, we should treat the first
+ // call as user input.
+ return !mHasBeenRunningByContent;
+ }
+
+ private:
+ Document& mDocument;
+ bool mTreatAsUserInput;
+ bool mHasBeenRunningByContent;
+ bool mHasBeenRunningByChromeOrAddon;
+ };
+
+ // Mapping table from HTML command name to internal command.
+ using InternalCommandDataHashtable =
+ nsTHashMap<nsStringCaseInsensitiveHashKey, InternalCommandData>;
+ static InternalCommandDataHashtable* sInternalCommandDataHashtable;
+
+ mutable std::bitset<static_cast<size_t>(
+ DeprecatedOperations::eDeprecatedOperationCount)>
+ mDeprecationWarnedAbout;
+ mutable std::bitset<eDocumentWarningCount> mDocWarningWarnedAbout;
+
+ // Lazy-initialization to have mDocGroup initialized in prior to the
+ UniquePtr<ServoStyleSet> mStyleSet;
+
+ protected:
+ // Never ever call this. Only call GetWindow!
+ nsPIDOMWindowOuter* GetWindowInternal() const;
+
+ // Never ever call this. Only call GetScriptHandlingObject!
+ nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const;
+
+ // Never ever call this. Only call AllowXULXBL!
+ bool InternalAllowXULXBL();
+
+ /**
+ * These methods should be called before and after dispatching
+ * a mutation event.
+ * To make this easy and painless, use the mozAutoSubtreeModified helper
+ * class.
+ */
+ void WillDispatchMutationEvent(nsINode* aTarget);
+ void MutationEventDispatched(nsINode* aTarget);
+ friend class mozAutoSubtreeModified;
+
+ virtual Element* GetNameSpaceElement() override { return GetRootElement(); }
+
+ nsCString GetContentTypeInternal() const { return mContentType; }
+
+ // Update our frame request callback scheduling state, if needed. This will
+ // schedule or unschedule them, if necessary, and update
+ // mFrameRequestCallbacksScheduled. aOldShell should only be passed when
+ // mPresShell is becoming null; in that case it will be used to get hold of
+ // the relevant refresh driver.
+ void UpdateFrameRequestCallbackSchedulingState(
+ PresShell* aOldPresShell = nullptr);
+
+ // Helper for GetScrollingElement/IsScrollingElement.
+ bool IsPotentiallyScrollable(HTMLBodyElement* aBody);
+
+ void MaybeAllowStorageForOpenerAfterUserInteraction();
+
+ void MaybeStoreUserInteractionAsPermission();
+
+ // Helpers for GetElementsByName.
+ static bool MatchNameAttribute(Element* aElement, int32_t aNamespaceID,
+ nsAtom* aAtom, void* aData);
+ static void* UseExistingNameString(nsINode* aRootNode, const nsString* aName);
+
+ void MaybeResolveReadyForIdle();
+
+ using AutomaticStorageAccessPermissionGrantPromise =
+ MozPromise<bool, bool, true>;
+ [[nodiscard]] RefPtr<AutomaticStorageAccessPermissionGrantPromise>
+ AutomaticStorageAccessPermissionCanBeGranted(bool hasUserActivation);
+
+ static void AddToplevelLoadingDocument(Document* aDoc);
+ static void RemoveToplevelLoadingDocument(Document* aDoc);
+ static AutoTArray<Document*, 8>* sLoadingForegroundTopLevelContentDocument;
+ friend class cycleCollection;
+
+ nsCOMPtr<nsIReferrerInfo> mPreloadReferrerInfo;
+ nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
+
+ nsString mLastModified;
+
+ nsCOMPtr<nsIURI> mDocumentURI;
+ nsCOMPtr<nsIURI> mOriginalURI;
+ nsCOMPtr<nsIURI> mChromeXHRDocURI;
+ nsCOMPtr<nsIURI> mDocumentBaseURI;
+ nsCOMPtr<nsIURI> mChromeXHRDocBaseURI;
+
+ // The base domain of the document for third-party checks.
+ nsCString mBaseDomain;
+
+ // A lazily-constructed URL data for style system to resolve URL values.
+ RefPtr<URLExtraData> mCachedURLData;
+ nsCOMPtr<nsIReferrerInfo> mCachedReferrerInfoForInternalCSSAndSVGResources;
+
+ nsWeakPtr mDocumentLoadGroup;
+
+ WeakPtr<nsDocShell> mDocumentContainer;
+
+ NotNull<const Encoding*> mCharacterSet;
+ int32_t mCharacterSetSource;
+
+ OriginTrials mTrials;
+
+ // This is just a weak pointer; the parent document owns its children.
+ Document* mParentDocument;
+
+ // A reference to the element last returned from GetRootElement().
+ Element* mCachedRootElement;
+
+ // This is maintained by AutoSetRestoreSVGContextPaint.
+ const SVGContextPaint* mCurrentContextPaint = nullptr;
+
+ // This is a weak reference, but we hold a strong reference to mNodeInfo,
+ // which in turn holds a strong reference to this mNodeInfoManager.
+ nsNodeInfoManager* mNodeInfoManager;
+ RefPtr<css::Loader> mCSSLoader;
+ RefPtr<css::ImageLoader> mStyleImageLoader;
+
+ // The object that contains link color declarations (from the <body> mapped
+ // attributes), mapped attribute caches, and inline style attribute caches.
+ RefPtr<AttributeStyles> mAttributeStyles;
+
+ // Tracking for images in the document.
+ RefPtr<dom::ImageTracker> mImageTracker;
+
+ // A hashtable of ShadowRoots belonging to the composed doc.
+ //
+ // See ShadowRoot::Bind and ShadowRoot::Unbind.
+ ShadowRootSet mComposedShadowRoots;
+
+ using SVGUseElementSet = nsTHashSet<SVGUseElement*>;
+
+ // The set of <svg:use> elements that need a shadow tree reclone because the
+ // tree they map to has changed.
+ SVGUseElementSet mSVGUseElementsNeedingShadowTreeUpdate;
+
+ // The set of all object, embed, video/audio elements or
+ // nsIObjectLoadingContent or DocumentActivity for which this is
+ // the owner document. (They might not be in the document.)
+ //
+ // These are non-owning pointers, the elements are responsible for removing
+ // themselves when they go away.
+ UniquePtr<nsTHashSet<nsISupports*>> mActivityObservers;
+
+ // A hashtable of styled links keyed by address pointer.
+ nsTHashSet<Link*> mStyledLinks;
+#ifdef DEBUG
+ // Indicates whether mStyledLinks was cleared or not. This is used to track
+ // state so we can provide useful assertions to consumers of ForgetLink and
+ // AddStyleRelevantLink.
+ bool mStyledLinksCleared;
+#endif
+
+ // The array of all links that need their status resolved. Links must add
+ // themselves to this set by calling RegisterPendingLinkUpdate when added to a
+ // document.
+ static const size_t kSegmentSize = 128;
+
+ using LinksToUpdateList =
+ SegmentedVector<nsCOMPtr<Link>, kSegmentSize, InfallibleAllocPolicy>;
+
+ LinksToUpdateList mLinksToUpdate;
+
+ // SMIL Animation Controller, lazily-initialized in GetAnimationController
+ RefPtr<SMILAnimationController> mAnimationController;
+
+ // Table of element properties for this document.
+ nsPropertyTable mPropertyTable;
+
+ // Our cached .children collection
+ nsCOMPtr<nsIHTMLCollection> mChildrenCollection;
+
+ // Various DOM lists
+ RefPtr<nsContentList> mImages;
+ RefPtr<nsContentList> mEmbeds;
+ RefPtr<nsContentList> mLinks;
+ RefPtr<nsContentList> mForms;
+ RefPtr<nsContentList> mScripts;
+ nsCOMPtr<nsIHTMLCollection> mApplets;
+ RefPtr<nsContentList> mAnchors;
+
+ // container for per-context fonts (downloadable, SVG, etc.)
+ RefPtr<FontFaceSet> mFontFaceSet;
+
+ // Last time this document or a one of its sub-documents was focused. If
+ // focus has never occurred then mLastFocusTime.IsNull() will be true.
+ TimeStamp mLastFocusTime;
+
+ // Last time we found any scroll linked effect in this document.
+ TimeStamp mLastScrollLinkedEffectDetectionTime;
+
+ DocumentState mState{DocumentState::LTR_LOCALE};
+
+ RefPtr<Promise> mReadyForIdle;
+
+ RefPtr<mozilla::dom::FeaturePolicy> mFeaturePolicy;
+
+ // Permission Delegate Handler, lazily-initialized in
+ // GetPermissionDelegateHandler
+ RefPtr<PermissionDelegateHandler> mPermissionDelegateHandler;
+
+ bool mCachedStateObjectValid : 1;
+ bool mBlockAllMixedContent : 1;
+ bool mBlockAllMixedContentPreloads : 1;
+ bool mUpgradeInsecureRequests : 1;
+ bool mUpgradeInsecurePreloads : 1;
+ bool mDevToolsWatchingDOMMutations : 1;
+
+ // True if BIDI is enabled.
+ bool mBidiEnabled : 1;
+ // True if we may need to recompute the language prefs for this document.
+ bool mMayNeedFontPrefsUpdate : 1;
+ // True if a MathML element has ever been owned by this document.
+ bool mMathMLEnabled : 1;
+
+ // True if this document is the initial document for a window. This should
+ // basically be true only for documents that exist in newly-opened windows or
+ // documents created to satisfy a GetDocument() on a window when there's no
+ // document in it.
+ bool mIsInitialDocumentInWindow : 1;
+
+ // True if this document has ever been the initial document for a window. This
+ // is useful to determine if a document that was the initial document at one
+ // point, and became non-initial later.
+ bool mIsEverInitialDocumentInWindow : 1;
+
+ bool mIgnoreDocGroupMismatches : 1;
+
+ // True if we're loaded as data and therefor has any dangerous stuff, such
+ // as scripts and plugins, disabled.
+ bool mLoadedAsData : 1;
+
+ // True if the document is considered for memory reporting as a
+ // data document
+ bool mAddedToMemoryReportingAsDataDocument : 1;
+
+ // If true, whoever is creating the document has gotten it to the
+ // point where it's safe to start layout on it.
+ bool mMayStartLayout : 1;
+
+ // True iff we've ever fired a DOMTitleChanged event for this document
+ bool mHaveFiredTitleChange : 1;
+
+ // State for IsShowing(). mIsShowing starts off false. It becomes true when
+ // OnPageShow happens and becomes false when OnPageHide happens. So it's false
+ // before the initial load completes and when we're in bfcache or unloaded,
+ // true otherwise.
+ bool mIsShowing : 1;
+
+ // State for IsVisible(). mVisible starts off true. It becomes false when
+ // OnPageHide happens, and becomes true again when OnPageShow happens. So
+ // it's false only when we're in bfcache or unloaded.
+ bool mVisible : 1;
+
+ // True if our content viewer has been removed from the docshell
+ // (it may still be displayed, but in zombie state). Form control data
+ // has been saved.
+ bool mRemovedFromDocShell : 1;
+
+ // True iff DNS prefetch is allowed for this document. Note that if the
+ // document has no window, DNS prefetch won't be performed no matter what.
+ bool mAllowDNSPrefetch : 1;
+
+ // True when this document is a static clone of a normal document
+ bool mIsStaticDocument : 1;
+
+ // True while this document is being cloned to a static document.
+ bool mCreatingStaticClone : 1;
+
+ // True if this static document has any <canvas> element with a
+ // mozPrintCallback property at the time of the clone.
+ bool mHasPrintCallbacks : 1;
+
+ // True iff the document is being unlinked or deleted.
+ bool mInUnlinkOrDeletion : 1;
+
+ // True if document has ever had script handling object.
+ bool mHasHadScriptHandlingObject : 1;
+
+ // True if we're an SVG document being used as an image.
+ bool mIsBeingUsedAsImage : 1;
+
+ // True if our current document URI's scheme enables privileged CSS rules.
+ bool mChromeRulesEnabled : 1;
+
+ // True if we're loaded in a chrome docshell.
+ bool mInChromeDocShell : 1;
+
+ // True is this document is synthetic : stand alone image, video, audio
+ // file, etc.
+ bool mIsSyntheticDocument : 1;
+
+ // True is there is a pending runnable which will call
+ // FlushPendingLinkUpdates().
+ bool mHasLinksToUpdateRunnable : 1;
+
+ // True if we're flushing pending link updates.
+ bool mFlushingPendingLinkUpdates : 1;
+
+ // True if a DOMMutationObserver is perhaps attached to a node in the
+ // document.
+ bool mMayHaveDOMMutationObservers : 1;
+
+ // True if an nsIAnimationObserver is perhaps attached to a node in the
+ // document.
+ bool mMayHaveAnimationObservers : 1;
+
+ // True if the document has a CSP delivered throuh a header
+ bool mHasCSPDeliveredThroughHeader : 1;
+
+ // True if DisallowBFCaching has been called on this document.
+ bool mBFCacheDisallowed : 1;
+
+ bool mHasHadDefaultView : 1;
+
+ // Whether style sheet change events will be dispatched for this document
+ bool mStyleSheetChangeEventsEnabled : 1;
+
+ // Whether shadowrootattached/anonymousnodecreated/anonymousnoderemoved events
+ // will be dispatched for this document.
+ bool mDevToolsAnonymousAndShadowEventsEnabled : 1;
+
+ // Whether the document was created by a srcdoc iframe.
+ bool mIsSrcdocDocument : 1;
+
+ // Whether this document has a display document and thus is considered to
+ // be a resource document. Normally this is the same as !!mDisplayDocument,
+ // but mDisplayDocument is cleared during Unlink. mHasDisplayDocument is
+ // valid in the document's destructor.
+ bool mHasDisplayDocument : 1;
+
+ // Is the current mFontFaceSet valid?
+ bool mFontFaceSetDirty : 1;
+
+ // True if we have fired the DOMContentLoaded event, or don't plan to fire one
+ // (e.g. we're not being parsed at all).
+ bool mDidFireDOMContentLoaded : 1;
+
+ // True if we have frame request callbacks scheduled with the refresh driver.
+ // This should generally be updated only via
+ // UpdateFrameRequestCallbackSchedulingState.
+ bool mFrameRequestCallbacksScheduled : 1;
+
+ bool mIsTopLevelContentDocument : 1;
+
+ bool mIsContentDocument : 1;
+
+ // True if we have called BeginLoad and are expecting a paired EndLoad call.
+ bool mDidCallBeginLoad : 1;
+
+ // True if the encoding menu should be disabled.
+ bool mEncodingMenuDisabled : 1;
+
+ // False if we've disabled link handling for elements inside this document,
+ // true otherwise.
+ bool mLinksEnabled : 1;
+
+ // True if this document is for an SVG-in-OpenType font.
+ bool mIsSVGGlyphsDocument : 1;
+
+ // True if the document is being destroyed.
+ bool mInDestructor : 1;
+
+ // True if the document has been detached from its content viewer.
+ bool mIsGoingAway : 1;
+
+ // Whether we have filled our style set with all the stylesheets.
+ bool mStyleSetFilled : 1;
+
+ // Whether we have a quirks mode stylesheet in the style set.
+ bool mQuirkSheetAdded : 1;
+
+ // Whether we have a contenteditable.css stylesheet in the style set.
+ bool mContentEditableSheetAdded : 1;
+
+ // Whether we have a designmode.css stylesheet in the style set.
+ bool mDesignModeSheetAdded : 1;
+
+ // True if this document has ever had an HTML or SVG <title> element
+ // bound to it
+ bool mMayHaveTitleElement : 1;
+
+ bool mDOMLoadingSet : 1;
+ bool mDOMInteractiveSet : 1;
+ bool mDOMCompleteSet : 1;
+ bool mAutoFocusFired : 1;
+
+ bool mScrolledToRefAlready : 1;
+ bool mChangeScrollPosWhenScrollingToRef : 1;
+
+ bool mDelayFrameLoaderInitialization : 1;
+
+ bool mSynchronousDOMContentLoaded : 1;
+
+ // Set to true when the document is possibly controlled by the ServiceWorker.
+ // Used to prevent multiple requests to ServiceWorkerManager.
+ bool mMaybeServiceWorkerControlled : 1;
+
+ // These member variables cache information about the viewport so we don't
+ // have to recalculate it each time.
+ bool mAllowZoom : 1;
+ bool mValidScaleFloat : 1;
+ bool mValidMinScale : 1;
+ bool mValidMaxScale : 1;
+ bool mWidthStrEmpty : 1;
+
+ // Parser aborted. True if the parser of this document was forcibly
+ // terminated instead of letting it finish at its own pace.
+ bool mParserAborted : 1;
+
+ // Whether we have reported document use counters for this document with
+ // Telemetry yet. Normally this is only done at document destruction time,
+ // but for image documents (SVG documents) that are not guaranteed to be
+ // destroyed, we report use counters when the image cache no longer has any
+ // imgRequestProxys pointing to them. We track whether we ever reported use
+ // counters so that we only report them once for the document.
+ bool mReportedDocumentUseCounters : 1;
+
+ bool mHasReportedShadowDOMUsage : 1;
+
+ // Whether an event triggered by the refresh driver was delayed because this
+ // document has suppressed events.
+ bool mHasDelayedRefreshEvent : 1;
+
+ // The HTML spec has a "iframe load in progress" flag, but that doesn't seem
+ // to have the right semantics. See
+ // <https://github.com/whatwg/html/issues/4292>. What we have instead is a
+ // flag that is set while the window's 'load' event is firing if this document
+ // is the window's document.
+ bool mLoadEventFiring : 1;
+
+ // The HTML spec has a "mute iframe load" flag, but that doesn't seem to have
+ // the right semantics. See <https://github.com/whatwg/html/issues/4292>.
+ // What we have instead is a flag that is set if completion of our document
+ // via document.close() should skip firing the load event. Note that this
+ // flag is only relevant for HTML documents, but lives here for reasons that
+ // are documented above on SkipLoadEventAfterClose().
+ bool mSkipLoadEventAfterClose : 1;
+
+ // When false, the .cookies property is completely disabled
+ bool mDisableCookieAccess : 1;
+
+ // When false, the document.write() API is disabled.
+ bool mDisableDocWrite : 1;
+
+ // Has document.write() been called with a recursion depth higher than
+ // allowed?
+ bool mTooDeepWriteRecursion : 1;
+
+ /**
+ * Temporary flag that is set in EndUpdate() to ignore
+ * MaybeEditingStateChanged() script runners from a nested scope.
+ */
+ bool mPendingMaybeEditingStateChanged : 1;
+
+ // mHasBeenEditable is set to true when mEditingState is firstly set to
+ // eDesignMode or eContentEditable.
+ bool mHasBeenEditable : 1;
+
+ // Whether we've warned about the CSS zoom property.
+ //
+ // We don't use the general deprecated operation mechanism for this because we
+ // also record this as a `CountedUnknownProperty`.
+ bool mHasWarnedAboutZoom : 1;
+
+ // While we're handling an execCommand call by web app, set
+ // to true.
+ bool mIsRunningExecCommandByContent : 1;
+ // While we're handling an execCommand call by an addon (or chrome script),
+ // set to true.
+ bool mIsRunningExecCommandByChromeOrAddon : 1;
+
+ // True if we should change the readystate to complete after we fire
+ // DOMContentLoaded. This happens when we abort a load and
+ // nsDocumentViewer::EndLoad runs while we still have things blocking
+ // DOMContentLoaded. We wait for those to complete, and then update the
+ // readystate when they finish.
+ bool mSetCompleteAfterDOMContentLoaded : 1;
+
+ // Set the true if a completed cached stylesheet was created for the document.
+ bool mDidHitCompleteSheetCache : 1;
+
+ // Whether we have initialized mShouldReportUseCounters and
+ // mShouldSendPageUseCounters, and sent any needed message to the parent
+ // process to indicate that use counter data will be sent at some later point.
+ bool mUseCountersInitialized : 1;
+
+ // Whether this document should report use counters.
+ bool mShouldReportUseCounters : 1;
+
+ // Whether this document should send page use counters. Set to true after
+ // we've called SendExpectPageUseCounters on the top-level WindowGlobal.
+ bool mShouldSendPageUseCounters : 1;
+
+ // Whether the user has interacted with the document or not:
+ bool mUserHasInteracted : 1;
+
+ // We constantly update the user-interaction anti-tracking permission at any
+ // user-interaction using a timer. This boolean value is set to true when this
+ // timer is scheduled.
+ bool mHasUserInteractionTimerScheduled : 1;
+
+ // Whether we should resist fingerprinting.
+ bool mShouldResistFingerprinting : 1;
+
+ // Whether we are in private browsing mode.
+ bool mIsInPrivateBrowsing : 1;
+
+ // Whether we're cloning the contents of an SVG use element.
+ bool mCloningForSVGUse : 1;
+
+ bool mAllowDeclarativeShadowRoots : 1;
+
+ // The fingerprinting protections overrides for this document. The value will
+ // override the default enabled fingerprinting protections for this document.
+ // This will only get populated if these is one that comes from the local
+ // fingerprinting protection override pref or WebCompat. Otherwise, a value of
+ // Nothing() indicates no overrides are present for this document.
+ Maybe<RFPTarget> mOverriddenFingerprintingSettings;
+
+ uint8_t mXMLDeclarationBits;
+
+ // NOTE(emilio): Technically, this should be a StyleColorSchemeFlags, but we
+ // use uint8_t to avoid having to include a bunch of style system headers
+ // everywhere.
+ uint8_t mColorSchemeBits = 0;
+
+ // Currently active onload blockers.
+ uint32_t mOnloadBlockCount;
+
+ // Tracks if we are currently processing any document.write calls (either
+ // implicit or explicit). Note that if a write call writes out something which
+ // would block the parser, then mWriteLevel will be incorrect until the parser
+ // finishes processing that script.
+ uint32_t mWriteLevel;
+
+ uint32_t mContentEditableCount;
+ EditingState mEditingState;
+
+ // Compatibility mode
+ nsCompatibility mCompatMode;
+
+ // Our readyState
+ ReadyState mReadyState;
+
+ // Ancestor's loading state
+ bool mAncestorIsLoading;
+
+ // Our visibility state
+ dom::VisibilityState mVisibilityState;
+
+ enum Type {
+ eUnknown, // should never be used
+ eHTML,
+ eXHTML,
+ eGenericXML,
+ eSVG
+ };
+
+ Type mType;
+
+ uint8_t mDefaultElementType;
+
+ enum Tri { eTriUnset = 0, eTriFalse, eTriTrue };
+
+ Tri mAllowXULXBL;
+
+ bool mSkipDTDSecurityChecks;
+
+ // The document's script global object, the object from which the
+ // document can get its script context and scope. This is the
+ // *inner* window object.
+ nsCOMPtr<nsIScriptGlobalObject> mScriptGlobalObject;
+
+ // If mIsStaticDocument is true, mOriginalDocument points to the original
+ // document.
+ RefPtr<Document> mOriginalDocument;
+
+ // The bidi options for this document. What this bitfield means is
+ // defined in nsBidiUtils.h
+ uint32_t mBidiOptions;
+
+ // The sandbox flags on the document. These reflect the value of the sandbox
+ // attribute of the associated IFRAME or CSP-protectable content, if existent.
+ // These are set at load time and are immutable - see nsSandboxFlags.h for the
+ // possible flags.
+ uint32_t mSandboxFlags;
+
+ // The embedder policy obtained from parsing the HTTP response header or from
+ // our opener if this is the initial about:blank document.
+ Maybe<nsILoadInfo::CrossOriginEmbedderPolicy> mEmbedderPolicy;
+
+ RefPtr<nsAtom> mContentLanguage;
+
+ // The channel that got passed to Document::StartDocumentLoad(), if any.
+ nsCOMPtr<nsIChannel> mChannel;
+
+ // The CSP for every load lives in the Client within the LoadInfo. For all
+ // document-initiated subresource loads we can use that cached version of the
+ // CSP so we do not have to deserialize the CSP from the Client all the time.
+ nsCOMPtr<nsIContentSecurityPolicy> mCSP;
+ nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
+
+ private:
+ nsCString mContentType;
+
+ protected:
+ // The document's security info
+ nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo;
+
+ // The channel that failed to load and resulted in an error page.
+ // This only applies to error pages. Might be null.
+ nsCOMPtr<nsIChannel> mFailedChannel;
+
+ // if this document is part of a multipart document,
+ // the ID can be used to distinguish it from the other parts.
+ uint32_t mPartID;
+
+ // Cycle collector generation in which we're certain that this document
+ // won't be collected
+ uint32_t mMarkedCCGeneration;
+
+ PresShell* mPresShell;
+
+ nsCOMArray<nsINode> mSubtreeModifiedTargets;
+ uint32_t mSubtreeModifiedDepth;
+
+ // All images in process of being preloaded. This is a hashtable so
+ // we can remove them as the real image loads start; that way we
+ // make sure to not keep the image load going when no one cares
+ // about it anymore.
+ nsRefPtrHashtable<nsURIHashKey, imgIRequest> mPreloadingImages;
+
+ // A list of preconnects initiated by the preloader. This prevents
+ // the same uri from being used more than once, and allows the dom
+ // builder to not repeat the work of the preloader.
+ nsTHashMap<nsURIHashKey, bool> mPreloadedPreconnects;
+
+ // Current depth of picture elements from parser
+ uint32_t mPreloadPictureDepth;
+
+ // Set if we've found a URL for the current picture
+ nsString mPreloadPictureFoundSource;
+
+ // If we're an external resource document, this will be non-null and will
+ // point to our "display document": the one that all resource lookups should
+ // go to.
+ RefPtr<Document> mDisplayDocument;
+
+ uint32_t mEventsSuppressed;
+
+ // Any XHR ChannelEventQueues that were suspended on this document while
+ // events were suppressed.
+ nsTArray<RefPtr<net::ChannelEventQueue>> mSuspendedQueues;
+
+ // Any postMessage events that were suspended on this document while events
+ // were suppressed.
+ nsTArray<RefPtr<PostMessageEvent>> mSuspendedPostMessageEvents;
+
+ RefPtr<EventListener> mSuppressedEventListener;
+
+ /**
+ * https://html.spec.whatwg.org/#ignore-destructive-writes-counter
+ */
+ uint32_t mIgnoreDestructiveWritesCounter;
+
+ // Count of live static clones of this document.
+ uint32_t mStaticCloneCount;
+
+ // If the document is currently printing (or in print preview) this will point
+ // to the current static clone of this document. This is weak since the clone
+ // also has a reference to this document.
+ WeakPtr<Document> mLatestStaticClone;
+
+ // Array of nodes that have been blocked to prevent user tracking.
+ // They most likely have had their nsIChannel canceled by the URL
+ // classifier. (Safebrowsing)
+ //
+ // Weak nsINode pointers are used to allow nodes to disappear.
+ nsTArray<nsWeakPtr> mBlockedNodesByClassifier;
+
+ // Weak reference to mScriptGlobalObject QI:d to nsPIDOMWindow,
+ // updated on every set of mScriptGlobalObject.
+ nsPIDOMWindowInner* mWindow;
+
+ nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
+
+ FrameRequestManager mFrameRequestManager;
+
+ // This object allows us to evict ourself from the back/forward cache. The
+ // pointer is non-null iff we're currently in the bfcache.
+ nsIBFCacheEntry* mBFCacheEntry;
+
+ // Our base target.
+ nsString mBaseTarget;
+
+ nsCOMPtr<nsIStructuredCloneContainer> mStateObjectContainer;
+ JS::Heap<JS::Value> mCachedStateObject;
+
+ uint32_t mInSyncOperationCount;
+
+ UniquePtr<dom::XPathEvaluator> mXPathEvaluator;
+
+ nsTArray<RefPtr<AnonymousContent>> mAnonymousContents;
+
+ uint32_t mBlockDOMContentLoaded;
+
+ // Our live MediaQueryLists
+ LinkedList<MediaQueryList> mDOMMediaQueryLists;
+
+ // A hashset to keep track of which {element, imgRequestProxy}
+ // combination has been processed to avoid considering the same
+ // element twice for LargestContentfulPaint.
+ nsTHashtable<LCPEntryHashEntry> mContentIdentifiersForLCP;
+
+ // Array of observers
+ nsTObserverArray<nsIDocumentObserver*> mObservers;
+
+ // Flags for use counters used directly by this document.
+ UseCounters mUseCounters;
+ // Flags for use counters from resource documents, static clones,
+ // and SVG images referenced by this document. Those documents propagate
+ // their use counters up to here, which then count towards the top-level
+ // document's page use counters.
+ UseCounters mChildDocumentUseCounters;
+
+ // The CSS property use counters.
+ UniquePtr<StyleUseCounters> mStyleUseCounters;
+
+ TimeStamp mPageUnloadingEventTimeStamp;
+
+ RefPtr<DocGroup> mDocGroup;
+
+ RefPtr<nsCommandManager> mMidasCommandManager;
+
+ // The set of all the tracking script URLs. URLs are added to this set by
+ // calling NoteScriptTrackingStatus(). Currently we assume that a URL not
+ // existing in the set means the corresponding script isn't a tracking script.
+ nsTHashSet<nsCString> mTrackingScripts;
+
+ // Pointer to our parser if we're currently in the process of being
+ // parsed into.
+ nsCOMPtr<nsIParser> mParser;
+
+ // If the document was created from the the prototype cache there will be a
+ // reference to the prototype document to allow tracing.
+ RefPtr<nsXULPrototypeDocument> mPrototypeDocument;
+
+ // Weak reference to our sink for in case we no longer have a parser. This
+ // will allow us to flush out any pending stuff from the sink even if
+ // EndLoad() has already happened.
+ nsWeakPtr mWeakSink;
+
+ // Our update nesting level
+ uint32_t mUpdateNestLevel;
+
+ // HTTPS-Only Mode Status
+ // Constants are defined at nsILoadInfo::HTTPS_ONLY_*
+ uint32_t mHttpsOnlyStatus;
+
+ enum ViewportType : uint8_t {
+ DisplayWidthHeight,
+ Specified,
+ Unknown,
+ };
+
+ ViewportType mViewportType;
+
+ // viewport-fit described by
+ // https://drafts.csswg.org/css-round-display/#viewport-fit-descriptor
+ ViewportFitType mViewportFit;
+
+ PLDHashTable* mSubDocuments;
+
+ class HeaderData;
+ UniquePtr<HeaderData> mHeaderData;
+
+ nsTArray<net::EarlyHintConnectArgs> mEarlyHints;
+
+ class TitleChangeEvent;
+ nsRevocableEventPtr<TitleChangeEvent> mPendingTitleChangeEvent;
+
+ RefPtr<nsDOMNavigationTiming> mTiming;
+
+ // Recorded time of change to 'loading' state
+ // or time of the page gets restored from BFCache.
+ TimeStamp mLoadingOrRestoredFromBFCacheTimeStamp;
+
+ // Decided to use nsTObserverArray because it allows us to
+ // remove candidates while iterating them and this is what
+ // the spec defines. We could implement the spec without
+ // using nsTObserverArray, however using nsTObserverArray is more clear.
+ nsTObserverArray<nsWeakPtr> mAutoFocusCandidates;
+
+ nsCString mScrollToRef;
+
+ // Weak reference to the scope object (aka the script global object)
+ // that, unlike mScriptGlobalObject, is never unset once set. This
+ // is a weak reference to avoid leaks due to circular references.
+ nsWeakPtr mScopeObject;
+
+ // Array of intersection observers
+ nsTHashSet<DOMIntersectionObserver*> mIntersectionObservers;
+
+ // Array of resize observers
+ nsTArray<ResizeObserver*> mResizeObservers;
+
+ RefPtr<DOMIntersectionObserver> mLazyLoadObserver;
+
+ // ResizeObserver for storing and removing the last remembered size.
+ // @see {@link https://drafts.csswg.org/css-sizing-4/#last-remembered}
+ RefPtr<ResizeObserver> mLastRememberedSizeObserver;
+
+ // Stack of top layer elements.
+ nsTArray<nsWeakPtr> mTopLayer;
+
+ // The root of the doc tree in which this document is in. This is only
+ // non-null when this document is in fullscreen mode.
+ WeakPtr<Document> mFullscreenRoot;
+
+ RefPtr<DOMImplementation> mDOMImplementation;
+
+ RefPtr<nsContentList> mImageMaps;
+
+ // A set of responsive images keyed by address pointer.
+ nsTHashSet<HTMLImageElement*> mResponsiveContent;
+
+ RefPtr<DocumentTimeline> mDocumentTimeline;
+ LinkedList<DocumentTimeline> mTimelines;
+
+ RefPtr<dom::ScriptLoader> mScriptLoader;
+
+ // Tracker for scroll-driven animations that are waiting to start.
+ // nullptr until GetOrCreateScrollTimelineAnimationTracker is called.
+ RefPtr<ScrollTimelineAnimationTracker> mScrollTimelineAnimationTracker;
+
+ // A document "without a browsing context" that owns the content of
+ // HTMLTemplateElement.
+ RefPtr<Document> mTemplateContentsOwner;
+
+ dom::ExternalResourceMap mExternalResourceMap;
+
+ // ScreenOrientation "pending promise" as described by
+ // http://www.w3.org/TR/screen-orientation/
+ RefPtr<Promise> mOrientationPendingPromise;
+
+ nsTArray<RefPtr<nsFrameLoader>> mInitializableFrameLoaders;
+ nsTArray<nsCOMPtr<nsIRunnable>> mFrameLoaderFinalizers;
+ RefPtr<nsRunnableMethod<Document>> mFrameLoaderRunner;
+
+ nsTArray<PendingFrameStaticClone> mPendingFrameStaticClones;
+
+ // The layout history state that should be used by nodes in this
+ // document. We only actually store a pointer to it when:
+ // 1) We have no script global object.
+ // 2) We haven't had Destroy() called on us yet.
+ nsCOMPtr<nsILayoutHistoryState> mLayoutHistoryState;
+
+ // Mapping of wake lock types to sets of wake locks sentinels
+ // https://w3c.github.io/screen-wake-lock/#internal-slots
+ nsTHashMap<WakeLockType, nsTHashSet<RefPtr<WakeLockSentinel>>> mActiveLocks;
+
+ // The parsed viewport metadata of the last modified <meta name=viewport>
+ // element.
+ UniquePtr<ViewportMetaData> mLastModifiedViewportMetaData;
+
+ // A tree ordered list of all color-scheme meta tags in this document.
+ //
+ // TODO(emilio): There are other meta tags in the spec that have a similar
+ // processing model to color-scheme. We could store all in-document meta tags
+ // here to get sane and fast <meta> element processing.
+ TreeOrderedArray<HTMLMetaElement*> mColorSchemeMetaTags;
+
+ // These member variables cache information about the viewport so we don't
+ // have to recalculate it each time.
+ LayoutDeviceToScreenScale mScaleMinFloat;
+ LayoutDeviceToScreenScale mScaleMaxFloat;
+ LayoutDeviceToScreenScale mScaleFloat;
+ CSSToLayoutDeviceScale mPixelRatio;
+
+ CSSCoord mMinWidth;
+ CSSCoord mMaxWidth;
+ CSSCoord mMinHeight;
+ CSSCoord mMaxHeight;
+
+ RefPtr<EventListenerManager> mListenerManager;
+
+ nsCOMPtr<nsIRequest> mOnloadBlocker;
+
+ // Gecko-internal sheets used for extensions and such.
+ // Exposed to privileged script via nsIDOMWindowUtils.loadSheet.
+ nsTArray<RefPtr<StyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
+
+ // Member to store out last-selected stylesheet set.
+ nsString mLastStyleSheetSet;
+ nsString mPreferredStyleSheetSet;
+
+ RefPtr<DOMStyleSheetSetList> mStyleSheetSetList;
+
+ // We lazily calculate declaration blocks for elements with mapped
+ // attributes. This set contains all elements which need lazy resolution.
+ nsTHashSet<Element*> mLazyPresElements;
+
+ nsTHashSet<RefPtr<nsAtom>> mLanguagesUsed;
+
+ // TODO(emilio): Is this hot enough to warrant to be cached?
+ RefPtr<nsAtom> mLanguageFromCharset;
+
+ // Restyle root for servo's style system.
+ //
+ // We store this as an nsINode, rather than as an Element, so that we can
+ // store the Document node as the restyle root if the entire document (along
+ // with all document-level native-anonymous content) needs to be restyled.
+ //
+ // We also track which "descendant" bits (normal/animation-only/lazy-fc) the
+ // root corresponds to.
+ nsCOMPtr<nsINode> mServoRestyleRoot;
+ uint32_t mServoRestyleRootDirtyBits;
+
+ // Used in conjunction with the create-an-element-for-the-token algorithm to
+ // prevent custom element constructors from being able to use document.open(),
+ // document.close(), and document.write() when they are invoked by the parser.
+ uint32_t mThrowOnDynamicMarkupInsertionCounter;
+
+ // Count of unload/beforeunload/pagehide operations in progress.
+ uint32_t mIgnoreOpensDuringUnloadCounter;
+
+ nsCOMPtr<nsIDOMXULCommandDispatcher>
+ mCommandDispatcher; // [OWNER] of the focus tracker
+
+ RefPtr<XULBroadcastManager> mXULBroadcastManager;
+ RefPtr<XULPersist> mXULPersist;
+ RefPtr<ChromeObserver> mChromeObserver;
+
+ RefPtr<HTMLAllCollection> mAll;
+
+ nsTHashSet<RefPtr<WorkerDocumentListener>> mWorkerListeners;
+
+ // Pres shell resolution saved before entering fullscreen mode.
+ float mSavedResolution;
+
+ // Pres shell resolution saved before creating a MobileViewportManager.
+ float mSavedResolutionBeforeMVM;
+
+ nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
+
+ bool mHasStoragePermission;
+
+ // Document generation. Gets incremented everytime it changes.
+ int32_t mGeneration;
+
+ // Cached TabSizes values for the document.
+ int32_t mCachedTabSizeGeneration;
+ nsTabSizes mCachedTabSizes;
+
+ // This is equal to document's principal but with an isolation key. See
+ // StoragePrincipalHelper.h to know more.
+ nsCOMPtr<nsIPrincipal> mPartitionedPrincipal;
+
+ // The cached storage principal for this document.
+ // This is mutable so that we can keep EffectiveStoragePrincipal() const
+ // which is required due to its CloneDocHelper() call site. :-(
+ mutable nsCOMPtr<nsIPrincipal> mActiveStoragePrincipal;
+
+ // The cached cookie principal for this document.
+ // This is mutable so that we can keep EffectiveCookiePrincipal() const
+ // which is required due to its CloneDocHelper() call site. :-(
+ mutable nsCOMPtr<nsIPrincipal> mActiveCookiePrincipal;
+
+ // See GetNextFormNumber and GetNextControlNumber.
+ int32_t mNextFormNumber;
+ int32_t mNextControlNumber;
+
+ uint32_t mMediaElementWithMSECount = 0;
+
+ // Scope preloads per document. This is used by speculative loading as well.
+ PreloadService mPreloadService;
+
+ // See NotifyFetchOrXHRSuccess and SetNotifyFetchSuccess.
+ bool mShouldNotifyFetchSuccess;
+
+ // See SetNotifyFormOrPasswordRemoved and ShouldNotifyFormOrPasswordRemoved.
+ bool mShouldNotifyFormOrPasswordRemoved;
+
+ // Record page load telemetry
+ void RecordPageLoadEventTelemetry(
+ glean::perf::PageLoadExtra& aEventTelemetryData);
+
+ // Accumulate JS telemetry collected
+ void AccumulateJSTelemetry(
+ glean::perf::PageLoadExtra& aEventTelemetryDataOut);
+
+ // Accumulate page load metrics
+ void AccumulatePageLoadTelemetry(
+ glean::perf::PageLoadExtra& aEventTelemetryDataOut);
+
+ // The OOP counterpart to nsDocLoader::mChildrenInOnload.
+ // Not holding strong refs here since we don't actually use the BBCs.
+ nsTArray<const BrowserBridgeChild*> mOOPChildrenLoading;
+
+ // Registry of custom highlight definitions associated with this document.
+ RefPtr<class HighlightRegistry> mHighlightRegistry;
+
+ // Used for tracking a number of recent canvas extractions (e.g. toDataURL),
+ // this is used for a canvas fingerprinter detection heuristic.
+ nsTArray<CanvasUsage> mCanvasUsage;
+ uint64_t mLastCanvasUsage = 0;
+
+ UniquePtr<RadioGroupContainer> mRadioGroupContainer;
+
+ public:
+ // Needs to be public because the bindings code pokes at it.
+ JS::ExpandoAndGeneration mExpandoAndGeneration;
+
+ bool HasPendingInitialTranslation();
+
+ nsRefPtrHashtable<nsRefPtrHashKey<Element>, nsXULPrototypeElement>
+ mL10nProtoElements;
+
+ float GetSavedResolutionBeforeMVM() { return mSavedResolutionBeforeMVM; }
+ void SetSavedResolutionBeforeMVM(float aResolution) {
+ mSavedResolutionBeforeMVM = aResolution;
+ }
+
+ void LoadEventFired();
+
+ RadioGroupContainer& OwnedRadioGroupContainer();
+
+ static already_AddRefed<Document> ParseHTMLUnsafe(GlobalObject& aGlobal,
+ const nsAString& aHTML);
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(Document, NS_IDOCUMENT_IID)
+
+/**
+ * mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
+ * event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
+ * object is deleted.
+ */
+class MOZ_STACK_CLASS mozAutoSubtreeModified {
+ public:
+ /**
+ * @param aSubTreeOwner The document in which a subtree will be modified.
+ * @param aTarget The target of the possible DOMSubtreeModified event.
+ * Can be nullptr, in which case mozAutoSubtreeModified
+ * is just used to batch DOM mutations.
+ */
+ mozAutoSubtreeModified(Document* aSubtreeOwner, nsINode* aTarget) {
+ UpdateTarget(aSubtreeOwner, aTarget);
+ }
+
+ ~mozAutoSubtreeModified() { UpdateTarget(nullptr, nullptr); }
+
+ void UpdateTarget(Document* aSubtreeOwner, nsINode* aTarget) {
+ if (mSubtreeOwner) {
+ mSubtreeOwner->MutationEventDispatched(mTarget);
+ }
+
+ mTarget = aTarget;
+ mSubtreeOwner = aSubtreeOwner;
+ if (mSubtreeOwner) {
+ mSubtreeOwner->WillDispatchMutationEvent(mTarget);
+ }
+ }
+
+ private:
+ nsCOMPtr<nsINode> mTarget;
+ RefPtr<Document> mSubtreeOwner;
+};
+
+enum class SyncOperationBehavior { eSuspendInput, eAllowInput };
+
+class AutoWalkBrowsingContextGroup {
+ public:
+ virtual ~AutoWalkBrowsingContextGroup() = default;
+
+ protected:
+ void SuppressBrowsingContext(BrowsingContext* aContext);
+ void SuppressBrowsingContextGroup(BrowsingContextGroup* aGroup);
+ void UnsuppressDocuments() {
+ for (const auto& doc : mDocuments) {
+ UnsuppressDocument(doc);
+ }
+ }
+ virtual void SuppressDocument(Document* aDocument) = 0;
+ virtual void UnsuppressDocument(Document* aDocument) = 0;
+ AutoTArray<RefPtr<Document>, 16> mDocuments;
+};
+
+class MOZ_RAII nsAutoSyncOperation : private AutoWalkBrowsingContextGroup {
+ public:
+ explicit nsAutoSyncOperation(Document* aDocument,
+ SyncOperationBehavior aSyncBehavior);
+ ~nsAutoSyncOperation();
+
+ protected:
+ void SuppressDocument(Document* aDocument) override;
+ void UnsuppressDocument(Document* aDocument) override;
+
+ private:
+ uint32_t mMicroTaskLevel;
+ const SyncOperationBehavior mSyncBehavior;
+ RefPtr<BrowsingContext> mBrowsingContext;
+};
+
+class MOZ_RAII AutoSetThrowOnDynamicMarkupInsertionCounter final {
+ public:
+ explicit AutoSetThrowOnDynamicMarkupInsertionCounter(Document* aDocument)
+ : mDocument(aDocument) {
+ mDocument->IncrementThrowOnDynamicMarkupInsertionCounter();
+ }
+
+ ~AutoSetThrowOnDynamicMarkupInsertionCounter() {
+ mDocument->DecrementThrowOnDynamicMarkupInsertionCounter();
+ }
+
+ private:
+ Document* mDocument;
+};
+
+class MOZ_RAII IgnoreOpensDuringUnload final {
+ public:
+ explicit IgnoreOpensDuringUnload(Document* aDoc) : mDoc(aDoc) {
+ mDoc->IncrementIgnoreOpensDuringUnloadCounter();
+ }
+
+ ~IgnoreOpensDuringUnload() {
+ mDoc->DecrementIgnoreOpensDuringUnloadCounter();
+ }
+
+ private:
+ Document* mDoc;
+};
+
+bool IsInFocusedTab(Document* aDoc);
+
+// This covers all cases covered by IsInFocusedTab, but also ensures that
+// focused tab is "active" meaning not occluded.
+bool IsInActiveTab(Document* aDoc);
+
+} // namespace mozilla::dom
+
+NON_VIRTUAL_ADDREF_RELEASE(mozilla::dom::Document)
+
+// XXX These belong somewhere else
+nsresult NS_NewHTMLDocument(mozilla::dom::Document** aInstancePtrResult,
+ nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal,
+ bool aLoadedAsData = false);
+
+nsresult NS_NewXMLDocument(mozilla::dom::Document** aInstancePtrResult,
+ nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal,
+ bool aLoadedAsData = false,
+ bool aIsPlainDocument = false);
+
+nsresult NS_NewSVGDocument(mozilla::dom::Document** aInstancePtrResult,
+ nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal);
+
+nsresult NS_NewImageDocument(mozilla::dom::Document** aInstancePtrResult,
+ nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal);
+
+nsresult NS_NewVideoDocument(mozilla::dom::Document** aInstancePtrResult,
+ nsIPrincipal* aPrincipal,
+ nsIPrincipal* aPartitionedPrincipal);
+
+// Enum for requesting a particular type of document when creating a doc
+enum DocumentFlavor {
+ DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
+ DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
+ DocumentFlavorSVG, // SVGDocument
+ DocumentFlavorXML, // XMLDocument
+ DocumentFlavorPlain, // Just a Document
+};
+
+// Note: it's the caller's responsibility to create or get aPrincipal as needed
+// -- this method will not attempt to get a principal based on aDocumentURI.
+// Also, both aDocumentURI and aBaseURI must not be null.
+nsresult NS_NewDOMDocument(
+ mozilla::dom::Document** aInstancePtrResult, const nsAString& aNamespaceURI,
+ const nsAString& aQualifiedName, mozilla::dom::DocumentType* aDoctype,
+ nsIURI* aDocumentURI, nsIURI* aBaseURI, nsIPrincipal* aPrincipal,
+ bool aLoadedAsData, nsIGlobalObject* aEventObject, DocumentFlavor aFlavor);
+
+inline mozilla::dom::Document* nsINode::GetOwnerDocument() const {
+ mozilla::dom::Document* ownerDoc = OwnerDoc();
+
+ return ownerDoc != this ? ownerDoc : nullptr;
+}
+
+inline nsINode* nsINode::OwnerDocAsNode() const { return OwnerDoc(); }
+
+inline mozilla::dom::Document* nsINode::AsDocument() {
+ MOZ_ASSERT(IsDocument());
+ return static_cast<mozilla::dom::Document*>(this);
+}
+
+inline const mozilla::dom::Document* nsINode::AsDocument() const {
+ MOZ_ASSERT(IsDocument());
+ return static_cast<const mozilla::dom::Document*>(this);
+}
+
+inline nsISupports* ToSupports(mozilla::dom::Document* aDoc) {
+ return static_cast<nsINode*>(aDoc);
+}
+
+#endif /* mozilla_dom_Document_h___ */