/* -*- 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 "jsfriendapi.h" #include "nsCOMPtr.h" #include "nsAutoPtr.h" #include "nsCRT.h" #include "nsWeakReference.h" #include "nsWeakPtr.h" #include "nsTArray.h" #include "nsIdentifierMapEntry.h" #include "nsIDOMDocument.h" #include "nsStubDocumentObserver.h" #include "nsIScriptGlobalObject.h" #include "nsIContent.h" #include "nsIPrincipal.h" #include "nsIParser.h" #include "nsBindingManager.h" #include "nsRefPtrHashtable.h" #include "nsJSThingHashtable.h" #include "nsIScriptObjectPrincipal.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 "PLDHashTable.h" #include "nsDOMAttributeMap.h" #include "imgIRequest.h" #include "mozilla/EventStates.h" #include "mozilla/MemoryReporting.h" #include "mozilla/PendingAnimationTracker.h" #include "mozilla/dom/BoxObject.h" #include "mozilla/dom/DOMImplementation.h" #include "mozilla/dom/ScriptLoader.h" #include "mozilla/dom/StyleSheetList.h" #include "nsDataHashtable.h" #include "mozilla/TimeStamp.h" #include "mozilla/Attributes.h" #include "mozilla/LinkedList.h" #include "CustomElementRegistry.h" #include "mozilla/dom/Performance.h" #include "mozilla/Maybe.h" #include "nsIURIClassifier.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 nsDOMNavigationTiming; class nsWindowSizes; class nsHtml5TreeOpExecutor; class nsDocumentOnStack; class nsISecurityConsoleMessage; namespace mozilla { class EventChainPreVisitor; namespace dom { class ImageTracker; struct LifecycleCallbacks; class CallbackFunction; class DOMIntersectionObserver; class Performance; struct FullscreenRequest : public LinkedListElement { explicit FullscreenRequest(Element* aElement); FullscreenRequest(const FullscreenRequest&) = delete; ~FullscreenRequest(); Element* GetElement() const { return mElement; } nsIDocument* GetDocument() const { return mDocument; } private: RefPtr mElement; RefPtr 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 class nsOnloadBlocker final : public nsIRequest { public: nsOnloadBlocker() {} NS_DECL_ISUPPORTS NS_DECL_NSIREQUEST private: ~nsOnloadBlocker() {} }; // Base class for our document implementations. class nsDocument : public nsIDocument, public nsIDOMDocument, public nsSupportsWeakReference, public nsIScriptObjectPrincipal, public nsIRadioGroupContainer, public nsIApplicationCacheContainer, public nsStubMutationObserver { friend class nsIDocument; public: typedef mozilla::dom::Element Element; typedef mozilla::net::ReferrerPolicy ReferrerPolicy; NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_ADDSIZEOFEXCLUDINGTHIS // 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; static bool CallerIsTrustedAboutPage(JSContext* aCx, JSObject* aObject); static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject); static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject); static bool IsWebAnimationsEnabled(mozilla::dom::CallerType aCallerType); virtual void EndUpdate(nsUpdateType aUpdateType) override; virtual void BeginLoad() override; virtual void EndLoad() override; // 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, mozilla::dom::HTMLInputElement* aRadio) override; virtual void RemoveFromRadioGroup(const nsAString& aName, mozilla::dom::HTMLInputElement* 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); // Check whether shadow DOM is enabled for the global of aObject. static bool IsShadowDOMEnabled(JSContext* aCx, JSObject* aObject); // Check whether shadow DOM is enabled for the document this node belongs to. static bool IsShadowDOMEnabled(const nsINode* aNode); public: // nsIDOMDocument NS_DECL_NSIDOMDOCUMENT using mozilla::dom::DocumentOrShadowRoot::GetElementById; using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagName; using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagNameNS; using mozilla::dom::DocumentOrShadowRoot::GetElementsByClassName; // nsIDOMEventTarget virtual nsresult GetEventTargetParent( mozilla::EventChainPreVisitor& aVisitor) override; virtual mozilla::EventListenerManager* GetOrCreateListenerManager() override; virtual mozilla::EventListenerManager* GetExistingListenerManager() const override; // nsIScriptObjectPrincipal virtual nsIPrincipal* GetPrincipal() override; // nsIApplicationCacheContainer NS_DECL_NSIAPPLICATIONCACHECONTAINER virtual nsresult Init(); virtual void Destroy() override; virtual void RemovedFromDocShell() override; virtual void BlockOnload() override; virtual void UnblockOnload(bool aFireSync) override; NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument, nsIDocument) void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; } void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData) { mLoadedAsInteractiveData = aLoadedAsInteractiveData; } nsresult CloneDocHelper(nsDocument* clone, bool aPreallocateChildren) const; // Only BlockOnload should call this! void AsyncBlockOnload(); virtual void DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const override; // DocAddSizeOfIncludingThis is inherited from nsIDocument. virtual nsIDOMNode* AsDOMNode() override { return this; } protected: friend class nsNodeUtils; void RetrieveRelevantHeaders(nsIChannel *aChannel); void TryChannelCharset(nsIChannel *aChannel, int32_t& aCharsetSource, NotNull& aEncoding, nsHtml5TreeOpExecutor* aExecutor); nsIContent* GetFirstBaseNodeWithHref(); nsresult SetFirstBaseNodeWithHref(nsIContent *node); #define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) do { \ NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \ func_, params_); \ /* FIXME(emilio): Apparently we can keep observing from the BFCache? That \ looks bogus. */ \ if (nsIPresShell* shell = GetObservingShell()) { \ shell->func_ params_; \ } \ } while(0) #ifdef DEBUG void VerifyRootContentState(); #endif explicit nsDocument(const char* aContentType); virtual ~nsDocument(); public: // FIXME(emilio): This needs to be here instead of in nsIDocument because Rust // can't represent alignas(8) values on 32-bit architectures, which would // cause nsIDocument's layout to be wrong in the Rust side. // // This can be fixed after updating to rust 1.25 and updating bindgen to // include https://github.com/rust-lang-nursery/rust-bindgen/pull/1271. js::ExpandoAndGeneration mExpandoAndGeneration; nsClassHashtable mRadioGroups; friend class nsCallRequestFullScreen; // The application cache that this document is associated with, if // any. This can change during the lifetime of the document. nsCOMPtr mApplicationCache; nsCOMPtr mFirstBaseNodeWithHref; private: friend class nsUnblockOnloadEvent; // These are not implemented and not supported. nsDocument(const nsDocument& aOther); nsDocument& operator=(const nsDocument& aOther); }; class nsDocumentOnStack { public: explicit nsDocumentOnStack(nsIDocument* aDoc) : mDoc(aDoc) { mDoc->IncreaseStackRefCnt(); } ~nsDocumentOnStack() { mDoc->DecreaseStackRefCnt(); } private: nsIDocument* mDoc; }; #endif /* nsDocument_h___ */