diff options
Diffstat (limited to 'dom/base/nsDocument.h')
-rw-r--r-- | dom/base/nsDocument.h | 1641 |
1 files changed, 1641 insertions, 0 deletions
diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h new file mode 100644 index 000000000..17d936055 --- /dev/null +++ b/dom/base/nsDocument.h @@ -0,0 +1,1641 @@ +/* -*- 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/. */ + +/* + * Base class for all our document implementations. + */ + +#ifndef nsDocument_h___ +#define nsDocument_h___ + +#include "nsIDocument.h" + +#include "nsCOMPtr.h" +#include "nsAutoPtr.h" +#include "nsCRT.h" +#include "nsWeakReference.h" +#include "nsWeakPtr.h" +#include "nsTArray.h" +#include "nsIDOMDocument.h" +#include "nsIDOMDocumentXBL.h" +#include "nsStubDocumentObserver.h" +#include "nsIScriptGlobalObject.h" +#include "nsIContent.h" +#include "nsIPrincipal.h" +#include "nsIParser.h" +#include "nsBindingManager.h" +#include "nsInterfaceHashtable.h" +#include "nsJSThingHashtable.h" +#include "nsIScriptObjectPrincipal.h" +#include "nsIURI.h" +#include "nsScriptLoader.h" +#include "nsIRadioGroupContainer.h" +#include "nsILayoutHistoryState.h" +#include "nsIRequest.h" +#include "nsILoadGroup.h" +#include "nsTObserverArray.h" +#include "nsStubMutationObserver.h" +#include "nsIChannel.h" +#include "nsCycleCollectionParticipant.h" +#include "nsContentList.h" +#include "nsGkAtoms.h" +#include "nsIApplicationCache.h" +#include "nsIApplicationCacheContainer.h" +#include "mozilla/StyleSetHandle.h" +#include "PLDHashTable.h" +#include "nsAttrAndChildArray.h" +#include "nsDOMAttributeMap.h" +#include "nsIContentViewer.h" +#include "nsIInterfaceRequestor.h" +#include "nsILoadContext.h" +#include "nsIProgressEventSink.h" +#include "nsISecurityEventSink.h" +#include "nsIChannelEventSink.h" +#include "imgIRequest.h" +#include "mozilla/EventListenerManager.h" +#include "mozilla/EventStates.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/PendingAnimationTracker.h" +#include "mozilla/dom/DOMImplementation.h" +#include "mozilla/dom/StyleSheetList.h" +#include "nsDataHashtable.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/Attributes.h" +#include "nsIDOMXPathEvaluator.h" +#include "jsfriendapi.h" +#include "ImportManager.h" +#include "mozilla/LinkedList.h" +#include "CustomElementRegistry.h" +#include "mozilla/dom/Performance.h" + +#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0) +#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1) +#define XML_DECLARATION_BITS_STANDALONE_EXISTS (1 << 2) +#define XML_DECLARATION_BITS_STANDALONE_YES (1 << 3) + + +class nsDOMStyleSheetSetList; +class nsDocument; +class nsIRadioVisitor; +class nsIFormControl; +struct nsRadioGroupStruct; +class nsOnloadBlocker; +class nsUnblockOnloadEvent; +class nsDOMNavigationTiming; +class nsWindowSizes; +class nsHtml5TreeOpExecutor; +class nsDocumentOnStack; +class nsISecurityConsoleMessage; +class nsPIBoxObject; + +namespace mozilla { +class EventChainPreVisitor; +namespace dom { +class BoxObject; +class ImageTracker; +struct LifecycleCallbacks; +class CallbackFunction; +class DOMIntersectionObserver; +class Performance; + +struct FullscreenRequest : public LinkedListElement<FullscreenRequest> +{ + explicit FullscreenRequest(Element* aElement); + FullscreenRequest(const FullscreenRequest&) = delete; + ~FullscreenRequest(); + + Element* GetElement() const { return mElement; } + nsDocument* GetDocument() const { return mDocument; } + +private: + RefPtr<Element> mElement; + RefPtr<nsDocument> mDocument; + +public: + // This value should be true if the fullscreen request is + // originated from chrome code. + bool mIsCallerChrome = false; + // This value denotes whether we should trigger a NewOrigin event if + // requesting fullscreen in its document causes the origin which is + // fullscreen to change. We may want *not* to trigger that event if + // we're calling RequestFullScreen() as part of a continuation of a + // request in a subdocument in different process, whereupon the caller + // need to send some notification itself with the real origin. + bool mShouldNotifyNewOrigin = true; +}; + +} // namespace dom +} // namespace mozilla + +/** + * Right now our identifier map entries contain information for 'name' + * and 'id' mappings of a given string. This is so that + * nsHTMLDocument::ResolveName only has to do one hash lookup instead + * of two. It's not clear whether this still matters for performance. + * + * We also store the document.all result list here. This is mainly so that + * when all elements with the given ID are removed and we remove + * the ID's nsIdentifierMapEntry, the document.all result is released too. + * Perhaps the document.all results should have their own hashtable + * in nsHTMLDocument. + */ +class nsIdentifierMapEntry : public nsStringHashKey +{ +public: + typedef mozilla::dom::Element Element; + typedef mozilla::net::ReferrerPolicy ReferrerPolicy; + + explicit nsIdentifierMapEntry(const nsAString& aKey) : + nsStringHashKey(&aKey), mNameContentList(nullptr) + { + } + explicit nsIdentifierMapEntry(const nsAString* aKey) : + nsStringHashKey(aKey), mNameContentList(nullptr) + { + } + nsIdentifierMapEntry(const nsIdentifierMapEntry& aOther) : + nsStringHashKey(&aOther.GetKey()) + { + NS_ERROR("Should never be called"); + } + ~nsIdentifierMapEntry(); + + void AddNameElement(nsINode* aDocument, Element* aElement); + void RemoveNameElement(Element* aElement); + bool IsEmpty(); + nsBaseContentList* GetNameContentList() { + return mNameContentList; + } + bool HasNameElement() const { + return mNameContentList && mNameContentList->Length() != 0; + } + + /** + * Returns the element if we know the element associated with this + * id. Otherwise returns null. + */ + Element* GetIdElement(); + /** + * Returns the list of all elements associated with this id. + */ + const nsTArray<Element*>& GetIdElements() const { + return mIdContentList; + } + /** + * If this entry has a non-null image element set (using SetImageElement), + * the image element will be returned, otherwise the same as GetIdElement(). + */ + Element* GetImageIdElement(); + /** + * Append all the elements with this id to aElements + */ + void AppendAllIdContent(nsCOMArray<nsIContent>* aElements); + /** + * This can fire ID change callbacks. + * @return true if the content could be added, false if we failed due + * to OOM. + */ + bool AddIdElement(Element* aElement); + /** + * This can fire ID change callbacks. + */ + void RemoveIdElement(Element* aElement); + /** + * Set the image element override for this ID. This will be returned by + * GetIdElement(true) if non-null. + */ + void SetImageElement(Element* aElement); + bool HasIdElementExposedAsHTMLDocumentProperty(); + + bool HasContentChangeCallback() { return mChangeCallbacks != nullptr; } + void AddContentChangeCallback(nsIDocument::IDTargetObserver aCallback, + void* aData, bool aForImage); + void RemoveContentChangeCallback(nsIDocument::IDTargetObserver aCallback, + void* aData, bool aForImage); + + void Traverse(nsCycleCollectionTraversalCallback* aCallback); + + struct ChangeCallback { + nsIDocument::IDTargetObserver mCallback; + void* mData; + bool mForImage; + }; + + struct ChangeCallbackEntry : public PLDHashEntryHdr { + typedef const ChangeCallback KeyType; + typedef const ChangeCallback* KeyTypePointer; + + explicit ChangeCallbackEntry(const ChangeCallback* aKey) : + mKey(*aKey) { } + ChangeCallbackEntry(const ChangeCallbackEntry& toCopy) : + mKey(toCopy.mKey) { } + + KeyType GetKey() const { return mKey; } + bool KeyEquals(KeyTypePointer aKey) const { + return aKey->mCallback == mKey.mCallback && + aKey->mData == mKey.mData && + aKey->mForImage == mKey.mForImage; + } + + static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; } + static PLDHashNumber HashKey(KeyTypePointer aKey) + { + return mozilla::HashGeneric(aKey->mCallback, aKey->mData); + } + enum { ALLOW_MEMMOVE = true }; + + ChangeCallback mKey; + }; + + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; + +private: + void FireChangeCallbacks(Element* aOldElement, Element* aNewElement, + bool aImageOnly = false); + + // empty if there are no elements with this ID. + // The elements are stored as weak pointers. + nsTArray<Element*> mIdContentList; + RefPtr<nsBaseContentList> mNameContentList; + nsAutoPtr<nsTHashtable<ChangeCallbackEntry> > mChangeCallbacks; + RefPtr<Element> mImageElement; +}; + +namespace mozilla { +namespace dom { + +} // namespace dom +} // namespace mozilla + +class nsDocHeaderData +{ +public: + nsDocHeaderData(nsIAtom* aField, const nsAString& aData) + : mField(aField), mData(aData), mNext(nullptr) + { + } + + ~nsDocHeaderData(void) + { + delete mNext; + } + + nsCOMPtr<nsIAtom> mField; + nsString mData; + nsDocHeaderData* mNext; +}; + +class nsDOMStyleSheetList : public mozilla::dom::StyleSheetList, + public nsStubDocumentObserver +{ +public: + explicit nsDOMStyleSheetList(nsIDocument* aDocument); + + NS_DECL_ISUPPORTS_INHERITED + + // nsIDocumentObserver + NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED + NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED + + // nsIMutationObserver + NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED + + virtual nsINode* GetParentObject() const override + { + return mDocument; + } + + uint32_t Length() override; + mozilla::StyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) override; + +protected: + virtual ~nsDOMStyleSheetList(); + + int32_t mLength; + nsIDocument* mDocument; +}; + +class nsOnloadBlocker final : public nsIRequest +{ +public: + nsOnloadBlocker() {} + + NS_DECL_ISUPPORTS + NS_DECL_NSIREQUEST + +private: + ~nsOnloadBlocker() {} +}; + +class nsExternalResourceMap +{ +public: + typedef nsIDocument::ExternalResourceLoad ExternalResourceLoad; + nsExternalResourceMap(); + + /** + * Request an external resource document. This does exactly what + * nsIDocument::RequestExternalResource is documented to do. + */ + nsIDocument* RequestResource(nsIURI* aURI, + nsINode* aRequestingNode, + nsDocument* aDisplayDocument, + ExternalResourceLoad** aPendingLoad); + + /** + * Enumerate the resource documents. See + * nsIDocument::EnumerateExternalResources. + */ + void EnumerateResources(nsIDocument::nsSubDocEnumFunc aCallback, void* aData); + + /** + * 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(); + nsCOMPtr<nsIDocument> mDocument; + nsCOMPtr<nsIContentViewer> mViewer; + nsCOMPtr<nsILoadGroup> mLoadGroup; + }; + + // Hide all our viewers + void HideViewers(); + + // Show all our viewers + void ShowViewers(); + +protected: + class PendingLoad : public ExternalResourceLoad, + public nsIStreamListener + { + ~PendingLoad() {} + + public: + explicit PendingLoad(nsDocument* 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, nsINode* aRequestingNode); + + /** + * Set up an nsIContentViewer based on aRequest. This is guaranteed to + * put null in *aViewer and *aLoadGroup on all failures. + */ + nsresult SetupViewer(nsIRequest* aRequest, nsIContentViewer** aViewer, + nsILoadGroup** aLoadGroup); + + private: + RefPtr<nsDocument> mDisplayDocument; + nsCOMPtr<nsIStreamListener> mTargetListener; + nsCOMPtr<nsIURI> mURI; + }; + friend class PendingLoad; + + class LoadgroupCallbacks final : public nsIInterfaceRequestor + { + ~LoadgroupCallbacks() {} + 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) + DECL_SHIM(nsISecurityEventSink, NSISECURITYEVENTSINK) + DECL_SHIM(nsIApplicationCacheContainer, NSIAPPLICATIONCACHECONTAINER) +#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, nsIContentViewer* aViewer, + nsILoadGroup* aLoadGroup, + nsIDocument* aDisplayDocument); + + nsClassHashtable<nsURIHashKey, ExternalResource> mMap; + nsRefPtrHashtable<nsURIHashKey, PendingLoad> mPendingLoads; + bool mHaveShutDown; +}; + +// Base class for our document implementations. +class nsDocument : public nsIDocument, + public nsIDOMDocument, + public nsIDOMDocumentXBL, + public nsSupportsWeakReference, + public nsIScriptObjectPrincipal, + public nsIRadioGroupContainer, + public nsIApplicationCacheContainer, + public nsStubMutationObserver, + public nsIObserver, + public nsIDOMXPathEvaluator +{ + friend class nsIDocument; + +public: + typedef mozilla::dom::Element Element; + using nsIDocument::GetElementsByTagName; + typedef mozilla::net::ReferrerPolicy ReferrerPolicy; + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + + NS_DECL_SIZEOF_EXCLUDING_THIS + + virtual void Reset(nsIChannel *aChannel, nsILoadGroup *aLoadGroup) override; + virtual void ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup, + nsIPrincipal* aPrincipal) override; + + // StartDocumentLoad is pure virtual so that subclasses must override it. + // The nsDocument StartDocumentLoad 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 = true, + nsIContentSink* aContentSink = nullptr) override = 0; + + virtual void StopDocumentLoad() override; + + virtual void NotifyPossibleTitleChange(bool aBoundTitleElement) override; + + virtual void SetDocumentURI(nsIURI* aURI) override; + + virtual void SetChromeXHRDocURI(nsIURI* aURI) override; + + virtual void SetChromeXHRDocBaseURI(nsIURI* aURI) override; + + virtual void ApplySettingsFromCSP(bool aSpeculative) override; + + /** + * Set the principal responsible for this document. + */ + virtual void SetPrincipal(nsIPrincipal *aPrincipal) override; + + /** + * Get the Content-Type of this document. + */ + // NS_IMETHOD GetContentType(nsAString& aContentType); + // Already declared in nsIDOMDocument + + /** + * Set the Content-Type of this document. + */ + virtual void SetContentType(const nsAString& aContentType) override; + + virtual void SetBaseURI(nsIURI* aURI) override; + + /** + * Get/Set the base target of a link in a document. + */ + virtual void GetBaseTarget(nsAString &aBaseTarget) override; + + /** + * Return a standard name for the document's character set. This will + * trigger a startDocumentLoad if necessary to answer the question. + */ + virtual void SetDocumentCharacterSet(const nsACString& aCharSetID) override; + + /** + * Add an observer that gets notified whenever the charset changes. + */ + virtual nsresult AddCharSetObserver(nsIObserver* aObserver) override; + + /** + * Remove a charset observer. + */ + virtual void RemoveCharSetObserver(nsIObserver* aObserver) override; + + virtual Element* AddIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver, + void* aData, bool aForImage) override; + virtual void RemoveIDTargetObserver(nsIAtom* aID, IDTargetObserver aObserver, + void* aData, bool aForImage) override; + + /** + * Access HTTP header data (this may also get set from other sources, like + * HTML META tags). + */ + virtual void GetHeaderData(nsIAtom* aHeaderField, nsAString& aData) const override; + virtual void SetHeaderData(nsIAtom* aheaderField, + const nsAString& aData) override; + + /** + * 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). + */ + virtual already_AddRefed<nsIPresShell> CreateShell( + nsPresContext* aContext, + nsViewManager* aViewManager, + mozilla::StyleSetHandle aStyleSet) override; + virtual void DeleteShell() override; + + virtual nsresult GetAllowPlugins(bool* aAllowPlugins) override; + + static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject); + static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject); + virtual mozilla::dom::DocumentTimeline* Timeline() override; + virtual void GetAnimations( + nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) override; + mozilla::LinkedList<mozilla::dom::DocumentTimeline>& Timelines() override + { + return mTimelines; + } + + virtual nsresult SetSubDocumentFor(Element* aContent, + nsIDocument* aSubDoc) override; + virtual nsIDocument* GetSubDocumentFor(nsIContent* aContent) const override; + virtual Element* FindContentForSubDocument(nsIDocument *aDocument) const override; + virtual Element* GetRootElementInternal() const override; + + virtual void EnsureOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet) override; + + /** + * Get the (document) style sheets owned by this document. + * These are ordered, highest priority last + */ + virtual int32_t GetNumberOfStyleSheets() const override; + virtual mozilla::StyleSheet* GetStyleSheetAt(int32_t aIndex) const override; + virtual int32_t GetIndexOfStyleSheet( + const mozilla::StyleSheet* aSheet) const override; + virtual void AddStyleSheet(mozilla::StyleSheet* aSheet) override; + virtual void RemoveStyleSheet(mozilla::StyleSheet* aSheet) override; + + virtual void UpdateStyleSheets( + nsTArray<RefPtr<mozilla::StyleSheet>>& aOldSheets, + nsTArray<RefPtr<mozilla::StyleSheet>>& aNewSheets) override; + virtual void AddStyleSheetToStyleSets(mozilla::StyleSheet* aSheet); + virtual void RemoveStyleSheetFromStyleSets(mozilla::StyleSheet* aSheet); + + virtual void InsertStyleSheetAt(mozilla::StyleSheet* aSheet, + int32_t aIndex) override; + virtual void SetStyleSheetApplicableState(mozilla::StyleSheet* aSheet, + bool aApplicable) override; + + virtual nsresult LoadAdditionalStyleSheet(additionalSheetType aType, + nsIURI* aSheetURI) override; + virtual nsresult AddAdditionalStyleSheet(additionalSheetType aType, + mozilla::StyleSheet* aSheet) override; + virtual void RemoveAdditionalStyleSheet(additionalSheetType aType, + nsIURI* sheetURI) override; + virtual mozilla::StyleSheet* GetFirstAdditionalAuthorSheet() override; + + virtual nsIChannel* GetChannel() const override { + return mChannel; + } + + virtual nsIChannel* GetFailedChannel() const override { + return mFailedChannel; + } + virtual void SetFailedChannel(nsIChannel* aChannel) override { + mFailedChannel = aChannel; + } + + virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject) override; + + virtual void SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject) override; + + virtual nsIGlobalObject* GetScopeObject() const override; + void SetScopeObject(nsIGlobalObject* aGlobal) override; + /** + * Get the script loader for this document + */ + virtual nsScriptLoader* ScriptLoader() override; + + /** + * Add/Remove an element to the document's id and name hashes + */ + virtual void AddToIdTable(Element* aElement, nsIAtom* aId) override; + virtual void RemoveFromIdTable(Element* aElement, nsIAtom* aId) override; + virtual void AddToNameTable(Element* aElement, nsIAtom* aName) override; + virtual void RemoveFromNameTable(Element* aElement, nsIAtom* aName) override; + + /** + * Add a new observer of document change notifications. Whenever + * content is changed, appended, inserted or removed the observers are + * informed. + */ + virtual void AddObserver(nsIDocumentObserver* aObserver) override; + + /** + * Remove an observer of document change notifications. This will + * return false if the observer cannot be found. + */ + virtual bool RemoveObserver(nsIDocumentObserver* aObserver) override; + + // Observation hooks used to propagate notifications to document + // observers. + virtual void BeginUpdate(nsUpdateType aUpdateType) override; + virtual void EndUpdate(nsUpdateType aUpdateType) override; + virtual void BeginLoad() override; + virtual void EndLoad() override; + + virtual void SetReadyStateInternal(ReadyState rs) override; + + virtual void ContentStateChanged(nsIContent* aContent, + mozilla::EventStates aStateMask) + override; + virtual void DocumentStatesChanged( + mozilla::EventStates aStateMask) override; + + virtual void StyleRuleChanged(mozilla::StyleSheet* aStyleSheet, + mozilla::css::Rule* aStyleRule) override; + virtual void StyleRuleAdded(mozilla::StyleSheet* aStyleSheet, + mozilla::css::Rule* aStyleRule) override; + virtual void StyleRuleRemoved(mozilla::StyleSheet* aStyleSheet, + mozilla::css::Rule* aStyleRule) override; + + virtual void FlushPendingNotifications(mozFlushType aType) override; + virtual void FlushExternalResources(mozFlushType aType) override; + virtual void SetXMLDeclaration(const char16_t *aVersion, + const char16_t *aEncoding, + const int32_t aStandalone) override; + virtual void GetXMLDeclaration(nsAString& aVersion, + nsAString& aEncoding, + nsAString& Standalone) override; + virtual bool IsScriptEnabled() override; + + virtual void OnPageShow(bool aPersisted, mozilla::dom::EventTarget* aDispatchStartTarget) override; + virtual void OnPageHide(bool aPersisted, mozilla::dom::EventTarget* aDispatchStartTarget) override; + + virtual void WillDispatchMutationEvent(nsINode* aTarget) override; + virtual void MutationEventDispatched(nsINode* aTarget) override; + + // nsINode + virtual bool IsNodeOfType(uint32_t aFlags) const override; + virtual nsIContent *GetChildAt(uint32_t aIndex) const override; + virtual nsIContent * const * GetChildArray(uint32_t* aChildCount) const override; + virtual int32_t IndexOf(const nsINode* aPossibleChild) const override; + virtual uint32_t GetChildCount() const override; + virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex, + bool aNotify) override; + virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override; + virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override + { + return NS_ERROR_NOT_IMPLEMENTED; + } + + // nsIRadioGroupContainer + NS_IMETHOD WalkRadioGroup(const nsAString& aName, + nsIRadioVisitor* aVisitor, + bool aFlushContent) override; + virtual void + SetCurrentRadioButton(const nsAString& aName, + mozilla::dom::HTMLInputElement* aRadio) override; + virtual mozilla::dom::HTMLInputElement* + GetCurrentRadioButton(const nsAString& aName) override; + NS_IMETHOD + GetNextRadioButton(const nsAString& aName, + const bool aPrevious, + mozilla::dom::HTMLInputElement* aFocusedRadio, + mozilla::dom::HTMLInputElement** aRadioOut) override; + virtual void AddToRadioGroup(const nsAString& aName, + nsIFormControl* aRadio) override; + virtual void RemoveFromRadioGroup(const nsAString& aName, + nsIFormControl* aRadio) override; + virtual uint32_t GetRequiredRadioCount(const nsAString& aName) const override; + virtual void RadioRequiredWillChange(const nsAString& aName, + bool aRequiredAdded) override; + virtual bool GetValueMissingState(const nsAString& aName) const override; + virtual void SetValueMissingState(const nsAString& aName, bool aValue) override; + + // for radio group + nsRadioGroupStruct* GetRadioGroup(const nsAString& aName) const; + nsRadioGroupStruct* GetOrCreateRadioGroup(const nsAString& aName); + + virtual nsViewportInfo GetViewportInfo(const mozilla::ScreenIntSize& aDisplaySize) override; + + void ReportUseCounters(); + + virtual void AddIntersectionObserver( + mozilla::dom::DOMIntersectionObserver* aObserver) override; + virtual void RemoveIntersectionObserver( + mozilla::dom::DOMIntersectionObserver* aObserver) override; + virtual void UpdateIntersectionObservations() override; + virtual void ScheduleIntersectionObserverNotification() override; + virtual void NotifyIntersectionObservers() override; + + virtual void NotifyLayerManagerRecreated() override; + + +private: + void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet); + nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const; + void SendToConsole(nsCOMArray<nsISecurityConsoleMessage>& aMessages); + +public: + // nsIDOMNode + NS_FORWARD_NSIDOMNODE_TO_NSINODE_OVERRIDABLE + + // nsIDOMDocument + NS_DECL_NSIDOMDOCUMENT + + // nsIDOMDocumentXBL + NS_DECL_NSIDOMDOCUMENTXBL + + // nsIDOMEventTarget + virtual nsresult PreHandleEvent( + mozilla::EventChainPreVisitor& aVisitor) override; + virtual mozilla::EventListenerManager* + GetOrCreateListenerManager() override; + virtual mozilla::EventListenerManager* + GetExistingListenerManager() const override; + + // nsIScriptObjectPrincipal + virtual nsIPrincipal* GetPrincipal() override; + + // nsIApplicationCacheContainer + NS_DECL_NSIAPPLICATIONCACHECONTAINER + + // nsIObserver + NS_DECL_NSIOBSERVER + + NS_DECL_NSIDOMXPATHEVALUATOR + + virtual nsresult Init(); + + virtual already_AddRefed<Element> CreateElem(const nsAString& aName, + nsIAtom* aPrefix, + int32_t aNamespaceID, + const nsAString* aIs = nullptr) override; + + virtual void Sanitize() override; + + virtual void EnumerateSubDocuments(nsSubDocEnumFunc aCallback, + void *aData) override; + + virtual bool CanSavePresentation(nsIRequest *aNewRequest) override; + virtual void Destroy() override; + virtual void RemovedFromDocShell() override; + virtual already_AddRefed<nsILayoutHistoryState> GetLayoutHistoryState() const override; + + virtual void BlockOnload() override; + virtual void UnblockOnload(bool aFireSync) override; + + virtual void AddStyleRelevantLink(mozilla::dom::Link* aLink) override; + virtual void ForgetLink(mozilla::dom::Link* aLink) override; + + virtual void ClearBoxObjectFor(nsIContent* aContent) override; + + virtual already_AddRefed<mozilla::dom::BoxObject> + GetBoxObjectFor(mozilla::dom::Element* aElement, + mozilla::ErrorResult& aRv) override; + + virtual Element* + GetAnonymousElementByAttribute(nsIContent* aElement, + nsIAtom* aAttrName, + const nsAString& aAttrValue) const override; + + virtual Element* ElementFromPointHelper(float aX, float aY, + bool aIgnoreRootScrollFrame, + bool aFlushLayout) override; + + virtual void ElementsFromPointHelper(float aX, float aY, + uint32_t aFlags, + nsTArray<RefPtr<mozilla::dom::Element>>& aElements) override; + + virtual nsresult NodesFromRectHelper(float aX, float aY, + float aTopSize, float aRightSize, + float aBottomSize, float aLeftSize, + bool aIgnoreRootScrollFrame, + bool aFlushLayout, + nsIDOMNodeList** aReturn) override; + + virtual void FlushSkinBindings() override; + + virtual nsresult InitializeFrameLoader(nsFrameLoader* aLoader) override; + virtual nsresult FinalizeFrameLoader(nsFrameLoader* aLoader, nsIRunnable* aFinalizer) override; + virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) override; + virtual nsIDocument* + RequestExternalResource(nsIURI* aURI, + nsINode* aRequestingNode, + ExternalResourceLoad** aPendingLoad) override; + virtual void + EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData) override; + + // Returns our (lazily-initialized) animation controller. + // If HasAnimationController is true, this is guaranteed to return non-null. + nsSMILAnimationController* GetAnimationController() override; + + virtual mozilla::PendingAnimationTracker* + GetPendingAnimationTracker() final override + { + return mPendingAnimationTracker; + } + + virtual mozilla::PendingAnimationTracker* + GetOrCreatePendingAnimationTracker() override; + + virtual void SuppressEventHandling(SuppressionType aWhat, + uint32_t aIncrease) override; + + virtual void UnsuppressEventHandlingAndFireEvents(SuppressionType aWhat, + bool aFireEvents) override; + + void DecreaseEventSuppression() { + MOZ_ASSERT(mEventsSuppressed); + --mEventsSuppressed; + UpdateFrameRequestCallbackSchedulingState(); + } + + void ResumeAnimations() { + MOZ_ASSERT(mAnimationsPaused); + --mAnimationsPaused; + UpdateFrameRequestCallbackSchedulingState(); + } + + virtual nsIDocument* GetTemplateContentsOwner() override; + + NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument, + nsIDocument) + + void DoNotifyPossibleTitleChange(); + + nsExternalResourceMap& ExternalResourceMap() + { + return mExternalResourceMap; + } + + void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; } + void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData) + { + mLoadedAsInteractiveData = aLoadedAsInteractiveData; + } + + nsresult CloneDocHelper(nsDocument* clone) const; + + void MaybeInitializeFinalizeFrameLoaders(); + + void MaybeEndOutermostXBLUpdate(); + + virtual void PreloadPictureOpened() override; + virtual void PreloadPictureClosed() override; + + virtual void + PreloadPictureImageSource(const nsAString& aSrcsetAttr, + const nsAString& aSizesAttr, + const nsAString& aTypeAttr, + const nsAString& aMediaAttr) override; + + virtual already_AddRefed<nsIURI> + ResolvePreloadImage(nsIURI *aBaseURI, + const nsAString& aSrcAttr, + const nsAString& aSrcsetAttr, + const nsAString& aSizesAttr) override; + + virtual void MaybePreLoadImage(nsIURI* uri, + const nsAString &aCrossOriginAttr, + ReferrerPolicy aReferrerPolicy) override; + virtual void ForgetImagePreload(nsIURI* aURI) override; + + virtual void MaybePreconnect(nsIURI* uri, + mozilla::CORSMode aCORSMode) override; + + virtual void PreloadStyle(nsIURI* uri, const nsAString& charset, + const nsAString& aCrossOriginAttr, + ReferrerPolicy aReferrerPolicy, + const nsAString& aIntegrity) override; + + virtual nsresult LoadChromeSheetSync(nsIURI* uri, bool isAgentSheet, + RefPtr<mozilla::StyleSheet>* aSheet) override; + + virtual nsISupports* GetCurrentContentSink() override; + + virtual mozilla::EventStates GetDocumentState() override; + + // Only BlockOnload should call this! + void AsyncBlockOnload(); + + virtual void SetScrollToRef(nsIURI *aDocumentURI) override; + virtual void ScrollToRef() override; + virtual void ResetScrolledToRefAlready() override; + virtual void SetChangeScrollPosWhenScrollingToRef(bool aValue) override; + + virtual Element *GetElementById(const nsAString& aElementId) override; + virtual const nsTArray<Element*>* GetAllElementsForId(const nsAString& aElementId) const override; + + virtual Element *LookupImageElement(const nsAString& aElementId) override; + virtual void MozSetImageElement(const nsAString& aImageElementId, + Element* aElement) override; + + // AddPlugin adds a plugin-related element to mPlugins when the element is + // added to the tree. + virtual nsresult AddPlugin(nsIObjectLoadingContent* aPlugin) override; + // RemovePlugin removes a plugin-related element to mPlugins when the + // element is removed from the tree. + virtual void RemovePlugin(nsIObjectLoadingContent* aPlugin) override; + // GetPlugins returns the plugin-related elements from + // the frame and any subframes. + virtual void GetPlugins(nsTArray<nsIObjectLoadingContent*>& aPlugins) override; + + // Adds an element to mResponsiveContent when the element is + // added to the tree. + virtual nsresult AddResponsiveContent(nsIContent* aContent) override; + // Removes an element from mResponsiveContent when the element is + // removed from the tree. + virtual void RemoveResponsiveContent(nsIContent* aContent) override; + // Notifies any responsive content added by AddResponsiveContent upon media + // features values changing. + virtual void NotifyMediaFeatureValuesChanged() override; + + virtual nsresult GetStateObject(nsIVariant** aResult) override; + + virtual nsDOMNavigationTiming* GetNavigationTiming() const override; + virtual nsresult SetNavigationTiming(nsDOMNavigationTiming* aTiming) override; + + virtual Element* FindImageMap(const nsAString& aNormalizedMapName) override; + + virtual nsTArray<Element*> GetFullscreenStack() const override; + virtual void AsyncRequestFullScreen( + mozilla::UniquePtr<FullscreenRequest>&& aRequest) override; + virtual void RestorePreviousFullScreenState() override; + virtual bool IsFullscreenLeaf() override; + virtual nsresult + RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) override; + + virtual nsresult RemoteFrameFullscreenReverted() override; + virtual nsIDocument* GetFullscreenRoot() override; + virtual void SetFullscreenRoot(nsIDocument* aRoot) override; + + // Returns the size of the mBlockedTrackingNodes array. (nsIDocument.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). + // + // A script can subsequently use GetBlockedTrackingNodes() + // 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 + // mBlockedTrackingNodesArray but they are not removed when those nodes + // are removed from the tree or even garbage collected. + long BlockedTrackingNodeCount() const; + + // + // Returns strong references to mBlockedTrackingNodes. (nsIDocument.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> BlockedTrackingNodes() const; + + static bool IsUnprefixedFullscreenEnabled(JSContext* aCx, JSObject* aObject); + + // Do the "fullscreen element ready check" from the fullscreen spec. + // It returns true if the given element is allowed to go into fullscreen. + bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome); + + // This is called asynchronously by nsIDocument::AsyncRequestFullScreen() + // to move this document into full-screen mode if allowed. + void RequestFullScreen(mozilla::UniquePtr<FullscreenRequest>&& aRequest); + + // Removes all elements from the full-screen stack, removing full-scren + // styles from the top element in the stack. + void CleanupFullscreenState(); + + // Pushes aElement onto the full-screen stack, and removes full-screen styles + // from the former full-screen stack top, and its ancestors, and applies the + // styles to aElement. aElement becomes the new "full-screen element". + bool FullScreenStackPush(Element* aElement); + + // Remove the top element from the full-screen stack. Removes the full-screen + // styles from the former top element, and applies them to the new top + // element, if there is one. + void FullScreenStackPop(); + + // Returns the top element from the full-screen stack. + Element* FullScreenStackTop(); + + // DOM-exposed fullscreen API + bool FullscreenEnabled() override; + Element* GetFullscreenElement() override; + + void RequestPointerLock(Element* aElement) override; + bool SetPointerLock(Element* aElement, int aCursorStyle); + static void UnlockPointer(nsIDocument* aDoc = nullptr); + + void SetCurrentOrientation(mozilla::dom::OrientationType aType, + uint16_t aAngle) override; + uint16_t CurrentOrientationAngle() const override; + mozilla::dom::OrientationType CurrentOrientationType() const override; + void SetOrientationPendingPromise(mozilla::dom::Promise* aPromise) override; + mozilla::dom::Promise* GetOrientationPendingPromise() const override; + + // This method may fire a DOM event; if it does so it will happen + // synchronously. + void UpdateVisibilityState(); + // Posts an event to call UpdateVisibilityState + virtual void PostVisibilityUpdateEvent() override; + + // Since we wouldn't automatically play media from non-visited page, we need + // to notify window when the page was first visited. + void MaybeActiveMediaComponents(); + + virtual void DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const override; + // DocAddSizeOfIncludingThis is inherited from nsIDocument. + + virtual nsIDOMNode* AsDOMNode() override { return this; } + + // WebIDL bits + virtual mozilla::dom::DOMImplementation* + GetImplementation(mozilla::ErrorResult& rv) override; + virtual void + RegisterElement(JSContext* aCx, const nsAString& aName, + const mozilla::dom::ElementRegistrationOptions& aOptions, + JS::MutableHandle<JSObject*> aRetval, + mozilla::ErrorResult& rv) override; + virtual mozilla::dom::StyleSheetList* StyleSheets() override; + virtual void SetSelectedStyleSheetSet(const nsAString& aSheetSet) override; + virtual void GetLastStyleSheetSet(nsString& aSheetSet) override; + virtual mozilla::dom::DOMStringList* StyleSheetSets() override; + virtual void EnableStyleSheetsForSet(const nsAString& aSheetSet) override; + virtual already_AddRefed<Element> CreateElement(const nsAString& aTagName, + const mozilla::dom::ElementCreationOptionsOrString& aOptions, + ErrorResult& rv) override; + virtual already_AddRefed<Element> CreateElementNS(const nsAString& aNamespaceURI, + const nsAString& aQualifiedName, + const mozilla::dom::ElementCreationOptionsOrString& aOptions, + mozilla::ErrorResult& rv) override; + + virtual nsIDocument* MasterDocument() override + { + return mMasterDocument ? mMasterDocument.get() + : this; + } + + virtual void SetMasterDocument(nsIDocument* master) override + { + MOZ_ASSERT(master); + mMasterDocument = master; + } + + virtual bool IsMasterDocument() override + { + return !mMasterDocument; + } + + virtual mozilla::dom::ImportManager* ImportManager() override + { + if (mImportManager) { + MOZ_ASSERT(!mMasterDocument, "Only the master document has ImportManager set"); + return mImportManager.get(); + } + + if (mMasterDocument) { + return mMasterDocument->ImportManager(); + } + + // ImportManager is created lazily. + // If the manager is not yet set it has to be the + // master document and this is the first import in it. + // Let's create a new manager. + mImportManager = new mozilla::dom::ImportManager(); + return mImportManager.get(); + } + + virtual bool HasSubImportLink(nsINode* aLink) override + { + return mSubImportLinks.Contains(aLink); + } + + virtual uint32_t IndexOfSubImportLink(nsINode* aLink) override + { + return mSubImportLinks.IndexOf(aLink); + } + + virtual void AddSubImportLink(nsINode* aLink) override + { + mSubImportLinks.AppendElement(aLink); + } + + virtual nsINode* GetSubImportLink(uint32_t aIdx) override + { + return aIdx < mSubImportLinks.Length() ? mSubImportLinks[aIdx].get() + : nullptr; + } + + virtual void UnblockDOMContentLoaded() override; + +protected: + friend class nsNodeUtils; + friend class nsDocumentOnStack; + + void IncreaseStackRefCnt() + { + ++mStackRefCnt; + } + + void DecreaseStackRefCnt() + { + if (--mStackRefCnt == 0 && mNeedsReleaseAfterStackRefCntRelease) { + mNeedsReleaseAfterStackRefCntRelease = false; + NS_RELEASE_THIS(); + } + } + + /** + * Check that aId is not empty and log a message to the console + * service if it is. + * @returns true if aId looks correct, false otherwise. + */ + inline bool CheckGetElementByIdArg(const nsAString& aId) + { + if (aId.IsEmpty()) { + ReportEmptyGetElementByIdArg(); + return false; + } + return true; + } + + void ReportEmptyGetElementByIdArg(); + + void DispatchContentLoadedEvents(); + + void RetrieveRelevantHeaders(nsIChannel *aChannel); + + void TryChannelCharset(nsIChannel *aChannel, + int32_t& aCharsetSource, + nsACString& aCharset, + nsHtml5TreeOpExecutor* aExecutor); + + // 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(); + + // Refreshes the hrefs of all the links in the document. + void RefreshLinkHrefs(); + + nsIContent* GetFirstBaseNodeWithHref(); + nsresult SetFirstBaseNodeWithHref(nsIContent *node); + + /** + * 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(); + +public: + // Get our title + virtual void GetTitle(nsString& aTitle) override; + // Set our title + virtual void SetTitle(const nsAString& aTitle, mozilla::ErrorResult& rv) override; + + bool mIsTopLevelContentDocument: 1; + bool mIsContentDocument: 1; + + bool IsTopLevelContentDocument(); + void SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument); + + bool IsContentDocument() const; + void SetIsContentDocument(bool aIsContentDocument); + + js::ExpandoAndGeneration mExpandoAndGeneration; + + bool ContainsEMEContent(); + + bool ContainsMSEContent(); + +protected: + already_AddRefed<nsIPresShell> doCreateShell(nsPresContext* aContext, + nsViewManager* aViewManager, + mozilla::StyleSetHandle aStyleSet); + + void RemoveDocStyleSheetsFromStyleSets(); + void RemoveStyleSheetsFromStyleSets( + const nsTArray<RefPtr<mozilla::StyleSheet>>& aSheets, + mozilla::SheetType aType); + void ResetStylesheetsToURI(nsIURI* aURI); + void FillStyleSet(mozilla::StyleSetHandle aStyleSet); + + // Return whether all the presshells for this document are safe to flush + bool IsSafeToFlush() const; + + void DispatchPageTransition(mozilla::dom::EventTarget* aDispatchTarget, + const nsAString& aType, + bool aPersisted); + + virtual nsPIDOMWindowOuter* GetWindowInternal() const override; + virtual nsIScriptGlobalObject* GetScriptHandlingObjectInternal() const override; + virtual bool InternalAllowXULXBL() override; + + void UpdateScreenOrientation(); + +#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \ + NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \ + func_, params_); + +#ifdef DEBUG + void VerifyRootContentState(); +#endif + + explicit nsDocument(const char* aContentType); + virtual ~nsDocument(); + + void EnsureOnloadBlocker(); + + void NotifyStyleSheetApplicableStateChanged(); + + // 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(const FullscreenRequest& aRequest); + + nsTArray<nsIObserver*> mCharSetObservers; + + PLDHashTable *mSubDocuments; + + // Array of owning references to all children + nsAttrAndChildArray mChildren; + + // Pointer to our parser if we're currently in the process of being + // parsed into. + nsCOMPtr<nsIParser> mParser; + + // 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; + + nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheets; + nsTArray<RefPtr<mozilla::StyleSheet>> mOnDemandBuiltInUASheets; + nsTArray<RefPtr<mozilla::StyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount]; + + // Array of observers + nsTObserverArray<nsIDocumentObserver*> mObservers; + + // Array of intersection observers + nsTArray<RefPtr<mozilla::dom::DOMIntersectionObserver>> mIntersectionObservers; + + // Tracker for animations that are waiting to start. + // nullptr until GetOrCreatePendingAnimationTracker is called. + RefPtr<mozilla::PendingAnimationTracker> mPendingAnimationTracker; + + // 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; + + // Stack of full-screen elements. When we request full-screen we push the + // full-screen element onto this stack, and when we cancel full-screen we + // pop one off this stack, restoring the previous full-screen state + nsTArray<nsWeakPtr> mFullScreenStack; + + // The root of the doc tree in which this document is in. This is only + // non-null when this document is in fullscreen mode. + nsWeakPtr mFullscreenRoot; + +private: + static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp); + + /** + * Check if the passed custom element name, aOptions.mIs, is a registered + * custom element type or not, then return the custom element name for future + * usage. + * + * If there is no existing custom element definition for this name, throw a + * NotFoundError. + */ + const nsString* CheckCustomElementName( + const mozilla::dom::ElementCreationOptions& aOptions, + const nsAString& aLocalName, + uint32_t aNamespaceID, + ErrorResult& rv); + +public: + virtual already_AddRefed<mozilla::dom::CustomElementRegistry> + GetCustomElementRegistry() override; + + // Check whether web components are enabled for the global of aObject. + static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject); + // Check whether web components are enabled for the global of the document + // this nodeinfo comes from. + static bool IsWebComponentsEnabled(mozilla::dom::NodeInfo* aNodeInfo); + // Check whether web components are enabled for the given window. + static bool IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow); + + RefPtr<mozilla::EventListenerManager> mListenerManager; + RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets; + RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList; + RefPtr<nsScriptLoader> mScriptLoader; + nsDocHeaderData* mHeaderData; + /* mIdentifierMap works as follows for IDs: + * 1) Attribute changes affect the table immediately (removing and adding + * entries as needed). + * 2) Removals from the DOM affect the table immediately + * 3) Additions to the DOM always update existing entries for names, and add + * new ones for IDs. + */ + nsTHashtable<nsIdentifierMapEntry> mIdentifierMap; + + nsClassHashtable<nsStringHashKey, nsRadioGroupStruct> mRadioGroups; + + // Recorded time of change to 'loading' state. + mozilla::TimeStamp mLoadingTimeStamp; + + // True if the document has been detached from its content viewer. + bool mIsGoingAway:1; + // True if the document is being destroyed. + bool mInDestructor:1; + + // True if this document has ever had an HTML or SVG <title> element + // bound to it + bool mMayHaveTitleElement:1; + + bool mHasWarnedAboutBoxObjects:1; + + bool mDelayFrameLoaderInitialization:1; + + bool mSynchronousDOMContentLoaded:1; + + bool mInXBLUpdate:1; + + // Whether we're currently under a FlushPendingNotifications call to + // our presshell. This is used to handle flush reentry correctly. + bool mInFlush: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; + + friend class nsCallRequestFullScreen; + + // ScreenOrientation "pending promise" as described by + // http://www.w3.org/TR/screen-orientation/ + RefPtr<mozilla::dom::Promise> mOrientationPendingPromise; + + uint16_t mCurrentOrientationAngle; + mozilla::dom::OrientationType mCurrentOrientationType; + + // Keeps track of whether we have a pending + // 'style-sheet-applicable-state-changed' notification. + bool mSSApplicableStateNotificationPending:1; + + // Whether we have reported 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 mReportedUseCounters:1; + + // Whether we have filled our pres shell's style set with the document's + // additional sheets and sheets from the nsStyleSheetService. + bool mStyleSetFilled:1; + + uint8_t mPendingFullscreenRequests; + + uint8_t mXMLDeclarationBits; + + nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject> *mBoxObjectTable; + + // A document "without a browsing context" that owns the content of + // HTMLTemplateElement. + nsCOMPtr<nsIDocument> mTemplateContentsOwner; + + // Our update nesting level + uint32_t mUpdateNestLevel; + + // The application cache that this document is associated with, if + // any. This can change during the lifetime of the document. + nsCOMPtr<nsIApplicationCache> mApplicationCache; + + nsCOMPtr<nsIContent> mFirstBaseNodeWithHref; + + mozilla::EventStates mDocumentState; + mozilla::EventStates mGotDocumentState; + + RefPtr<nsDOMNavigationTiming> mTiming; +private: + friend class nsUnblockOnloadEvent; + // Recomputes the visibility state but doesn't set the new value. + mozilla::dom::VisibilityState GetVisibilityState() const; + void NotifyStyleSheetAdded(mozilla::StyleSheet* aSheet, bool aDocumentSheet); + void NotifyStyleSheetRemoved(mozilla::StyleSheet* aSheet, bool aDocumentSheet); + + void PostUnblockOnloadEvent(); + void DoUnblockOnload(); + + nsresult CheckFrameOptions(); + nsresult InitCSP(nsIChannel* aChannel); + + /** + * 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; + + // 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); + + void ClearAllBoxObjects(); + + // Returns true if the scheme for the url for this document is "about" + bool IsAboutPage(); + + // These are not implemented and not supported. + nsDocument(const nsDocument& aOther); + nsDocument& operator=(const nsDocument& aOther); + + // 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; + + // Currently active onload blockers + uint32_t mOnloadBlockCount; + // Onload blockers which haven't been activated yet + uint32_t mAsyncOnloadBlockCount; + nsCOMPtr<nsIRequest> mOnloadBlocker; + + // A hashtable of styled links keyed by address pointer. + nsTHashtable<nsPtrHashKey<mozilla::dom::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 + + // A set of responsive images keyed by address pointer. + nsTHashtable< nsPtrHashKey<nsIContent> > mResponsiveContent; + + // Member to store out last-selected stylesheet set. + nsString mLastStyleSheetSet; + + nsTArray<RefPtr<nsFrameLoader> > mInitializableFrameLoaders; + nsTArray<nsCOMPtr<nsIRunnable> > mFrameLoaderFinalizers; + RefPtr<nsRunnableMethod<nsDocument> > mFrameLoaderRunner; + + nsCOMPtr<nsIRunnable> mMaybeEndOutermostXBLUpdateRunner; + + nsRevocableEventPtr<nsRunnableMethod<nsDocument, void, false> > + mPendingTitleChangeEvent; + + nsExternalResourceMap mExternalResourceMap; + + // 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. + nsDataHashtable< nsURIHashKey, bool> mPreloadedPreconnects; + + // Current depth of picture elements from parser + int32_t mPreloadPictureDepth; + + // Set if we've found a URL for the current picture + nsString mPreloadPictureFoundSource; + + RefPtr<mozilla::dom::DOMImplementation> mDOMImplementation; + + RefPtr<nsContentList> mImageMaps; + + nsCString mScrollToRef; + uint8_t mScrolledToRefAlready : 1; + uint8_t mChangeScrollPosWhenScrollingToRef : 1; + + // Tracking for plugins in the document. + nsTHashtable< nsPtrHashKey<nsIObjectLoadingContent> > mPlugins; + + RefPtr<mozilla::dom::DocumentTimeline> mDocumentTimeline; + mozilla::LinkedList<mozilla::dom::DocumentTimeline> mTimelines; + + enum ViewportType { + DisplayWidthHeight, + Specified, + Unknown + }; + + ViewportType mViewportType; + + // These member variables cache information about the viewport so we don't have to + // recalculate it each time. + bool mValidWidth, mValidHeight; + mozilla::LayoutDeviceToScreenScale mScaleMinFloat; + mozilla::LayoutDeviceToScreenScale mScaleMaxFloat; + mozilla::LayoutDeviceToScreenScale mScaleFloat; + mozilla::CSSToLayoutDeviceScale mPixelRatio; + bool mAutoSize, mAllowZoom, mAllowDoubleTapZoom, mValidScaleFloat, mValidMaxScale, mScaleStrEmpty, mWidthStrEmpty; + mozilla::CSSSize mViewportSize; + + nsrefcnt mStackRefCnt; + bool mNeedsReleaseAfterStackRefCntRelease; + + nsCOMPtr<nsIDocument> mMasterDocument; + RefPtr<mozilla::dom::ImportManager> mImportManager; + nsTArray<nsCOMPtr<nsINode> > mSubImportLinks; + + // Set to true when the document is possibly controlled by the ServiceWorker. + // Used to prevent multiple requests to ServiceWorkerManager. + bool mMaybeServiceWorkerControlled; + +#ifdef DEBUG +public: + bool mWillReparent; +#endif +}; + +class nsDocumentOnStack +{ +public: + explicit nsDocumentOnStack(nsDocument* aDoc) : mDoc(aDoc) + { + mDoc->IncreaseStackRefCnt(); + } + ~nsDocumentOnStack() + { + mDoc->DecreaseStackRefCnt(); + } +private: + nsDocument* mDoc; +}; + +#endif /* nsDocument_h___ */ |