/* -*- 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 "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 "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 nsViewportInfo;
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 FragmentDirective;
class FrameRequestCallback;
class HighlightRegistry;
class HTMLAllCollection;
class HTMLBodyElement;
class HTMLInputElement;
class HTMLMetaElement;
class HTMLDialogElement;
class HTMLSharedElement;
class HTMLVideoElement;
class HTMLImageElement;
class ImageTracker;
enum class InteractiveWidget : uint8_t;
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;
class TrustedHTMLOrString;
class OwningTrustedHTMLOrString;
enum class ViewportFitType : uint8_t;
class ViewTransition;
class ViewTransitionUpdateCallback;
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 glean::perf {
struct PageLoadExtra;
}
}
// 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,
const BatchRemovalState* = nullptr) 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; }
bool CookieAccessDisabled()
const {
return mDisableCookieAccess; }
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 document is on the 3PCB exception list.
bool IsOn3PCBExceptionList()
const;
// 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(
const Variant<Nothing, FeaturePolicyInfo, Element*>&
aContainerFeaturePolicy);
nsresult InitFeaturePolicy(nsIChannel* aChannel);
void EnsureNotEnteringAndExitFullscreen();
protected:
friend class nsUnblockOnloadEvent;
nsresult InitCSP(nsIChannel* aChannel);
nsresult InitCOEP(nsIChannel* aChannel);
nsresult InitDocPolicy(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 and is
// not aContentToIgnore, or nullptr if that doesn't exist.
Element* GetHtmlChildElement(
nsAtom* aTag,
const nsIContent* aContentToIgnore = nullptr)
const;
// 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(
const nsIContent* aContentToIgnore = nullptr)
const;
// 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()
const {
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()
const;
// 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()
const;
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();
/**
* Process any active CloseWatchers in the document, such
* as fullscreen elements, popovers, dialogs.
*/
MOZ_CAN_RUN_SCRIPT
void ProcessCloseRequest();
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;
/**
--> --------------------
--> maximum size reached
--> --------------------