Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
8 : * Base class for all our document implementations.
9 : */
10 :
11 : #ifndef nsDocument_h___
12 : #define nsDocument_h___
13 :
14 : #include "nsIDocument.h"
15 :
16 : #include "jsfriendapi.h"
17 : #include "nsCOMPtr.h"
18 : #include "nsAutoPtr.h"
19 : #include "nsCRT.h"
20 : #include "nsWeakReference.h"
21 : #include "nsWeakPtr.h"
22 : #include "nsTArray.h"
23 : #include "nsIdentifierMapEntry.h"
24 : #include "nsStubDocumentObserver.h"
25 : #include "nsIScriptGlobalObject.h"
26 : #include "nsIContent.h"
27 : #include "nsIPrincipal.h"
28 : #include "nsIParser.h"
29 : #include "nsBindingManager.h"
30 : #include "nsRefPtrHashtable.h"
31 : #include "nsJSThingHashtable.h"
32 : #include "nsIScriptObjectPrincipal.h"
33 : #include "nsIRadioGroupContainer.h"
34 : #include "nsILayoutHistoryState.h"
35 : #include "nsIRequest.h"
36 : #include "nsILoadGroup.h"
37 : #include "nsTObserverArray.h"
38 : #include "nsStubMutationObserver.h"
39 : #include "nsIChannel.h"
40 : #include "nsCycleCollectionParticipant.h"
41 : #include "nsContentList.h"
42 : #include "nsGkAtoms.h"
43 : #include "PLDHashTable.h"
44 : #include "nsDOMAttributeMap.h"
45 : #include "imgIRequest.h"
46 : #include "mozilla/EventStates.h"
47 : #include "mozilla/MemoryReporting.h"
48 : #include "mozilla/PendingAnimationTracker.h"
49 : #include "mozilla/dom/BoxObject.h"
50 : #include "mozilla/dom/DOMImplementation.h"
51 : #include "mozilla/dom/ScriptLoader.h"
52 : #include "mozilla/dom/StyleSheetList.h"
53 : #include "nsDataHashtable.h"
54 : #include "mozilla/TimeStamp.h"
55 : #include "mozilla/Attributes.h"
56 : #include "mozilla/LinkedList.h"
57 : #include "CustomElementRegistry.h"
58 : #include "mozilla/dom/Performance.h"
59 : #include "mozilla/Maybe.h"
60 : #include "nsIURIClassifier.h"
61 :
62 : #define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
63 : #define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
64 : #define XML_DECLARATION_BITS_STANDALONE_EXISTS (1 << 2)
65 : #define XML_DECLARATION_BITS_STANDALONE_YES (1 << 3)
66 :
67 :
68 : class nsDOMStyleSheetSetList;
69 : class nsDocument;
70 : class nsIRadioVisitor;
71 : class nsIFormControl;
72 : struct nsRadioGroupStruct;
73 : class nsOnloadBlocker;
74 : class nsDOMNavigationTiming;
75 : class nsWindowSizes;
76 : class nsHtml5TreeOpExecutor;
77 : class nsDocumentOnStack;
78 : class nsISecurityConsoleMessage;
79 :
80 : namespace mozilla {
81 : class EventChainPreVisitor;
82 : namespace dom {
83 : class ImageTracker;
84 : struct LifecycleCallbacks;
85 : class CallbackFunction;
86 : class DOMIntersectionObserver;
87 : class Performance;
88 :
89 : struct FullscreenRequest : public LinkedListElement<FullscreenRequest>
90 : {
91 : explicit FullscreenRequest(Element* aElement);
92 : FullscreenRequest(const FullscreenRequest&) = delete;
93 : ~FullscreenRequest();
94 :
95 0 : Element* GetElement() const { return mElement; }
96 0 : nsIDocument* GetDocument() const { return mDocument; }
97 :
98 : private:
99 : RefPtr<Element> mElement;
100 : RefPtr<nsIDocument> mDocument;
101 :
102 : public:
103 : // This value should be true if the fullscreen request is
104 : // originated from chrome code.
105 : bool mIsCallerChrome = false;
106 : // This value denotes whether we should trigger a NewOrigin event if
107 : // requesting fullscreen in its document causes the origin which is
108 : // fullscreen to change. We may want *not* to trigger that event if
109 : // we're calling RequestFullScreen() as part of a continuation of a
110 : // request in a subdocument in different process, whereupon the caller
111 : // need to send some notification itself with the real origin.
112 : bool mShouldNotifyNewOrigin = true;
113 : };
114 :
115 : } // namespace dom
116 : } // namespace mozilla
117 :
118 : class nsOnloadBlocker final : public nsIRequest
119 : {
120 : public:
121 0 : nsOnloadBlocker() {}
122 :
123 : NS_DECL_ISUPPORTS
124 : NS_DECL_NSIREQUEST
125 :
126 : private:
127 0 : ~nsOnloadBlocker() {}
128 : };
129 :
130 : // Base class for our document implementations.
131 : class nsDocument : public nsIDocument,
132 : public nsSupportsWeakReference,
133 : public nsIScriptObjectPrincipal,
134 : public nsIRadioGroupContainer,
135 : public nsIApplicationCacheContainer,
136 : public nsStubMutationObserver
137 : {
138 : friend class nsIDocument;
139 :
140 : public:
141 : typedef mozilla::dom::Element Element;
142 : typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
143 :
144 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
145 :
146 : NS_DECL_ADDSIZEOFEXCLUDINGTHIS
147 :
148 : // StartDocumentLoad is pure virtual so that subclasses must override it.
149 : // The nsDocument StartDocumentLoad does some setup, but does NOT set
150 : // *aDocListener; this is the job of subclasses.
151 : virtual nsresult StartDocumentLoad(const char* aCommand,
152 : nsIChannel* aChannel,
153 : nsILoadGroup* aLoadGroup,
154 : nsISupports* aContainer,
155 : nsIStreamListener **aDocListener,
156 : bool aReset = true,
157 : nsIContentSink* aContentSink = nullptr) override = 0;
158 :
159 : virtual void StopDocumentLoad() override;
160 :
161 : static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject);
162 : static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
163 : static bool IsWebAnimationsEnabled(mozilla::dom::CallerType aCallerType);
164 :
165 : virtual void EndUpdate() override;
166 : virtual void BeginLoad() override;
167 : virtual void EndLoad() override;
168 :
169 : // nsIRadioGroupContainer
170 : NS_IMETHOD WalkRadioGroup(const nsAString& aName,
171 : nsIRadioVisitor* aVisitor,
172 : bool aFlushContent) override;
173 : virtual void
174 : SetCurrentRadioButton(const nsAString& aName,
175 : mozilla::dom::HTMLInputElement* aRadio) override;
176 : virtual mozilla::dom::HTMLInputElement*
177 : GetCurrentRadioButton(const nsAString& aName) override;
178 : NS_IMETHOD
179 : GetNextRadioButton(const nsAString& aName,
180 : const bool aPrevious,
181 : mozilla::dom::HTMLInputElement* aFocusedRadio,
182 : mozilla::dom::HTMLInputElement** aRadioOut) override;
183 : virtual void AddToRadioGroup(const nsAString& aName,
184 : mozilla::dom::HTMLInputElement* aRadio) override;
185 : virtual void RemoveFromRadioGroup(const nsAString& aName,
186 : mozilla::dom::HTMLInputElement* aRadio) override;
187 : virtual uint32_t GetRequiredRadioCount(const nsAString& aName) const override;
188 : virtual void RadioRequiredWillChange(const nsAString& aName,
189 : bool aRequiredAdded) override;
190 : virtual bool GetValueMissingState(const nsAString& aName) const override;
191 : virtual void SetValueMissingState(const nsAString& aName, bool aValue) override;
192 :
193 : // for radio group
194 : nsRadioGroupStruct* GetRadioGroup(const nsAString& aName) const;
195 : nsRadioGroupStruct* GetOrCreateRadioGroup(const nsAString& aName);
196 :
197 : // Check whether shadow DOM is enabled for the global of aObject.
198 : static bool IsShadowDOMEnabled(JSContext* aCx, JSObject* aObject);
199 : // Check whether shadow DOM is enabled for the document this node belongs to.
200 : static bool IsShadowDOMEnabled(const nsINode* aNode);
201 :
202 : public:
203 : using mozilla::dom::DocumentOrShadowRoot::GetElementById;
204 : using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagName;
205 : using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagNameNS;
206 : using mozilla::dom::DocumentOrShadowRoot::GetElementsByClassName;
207 :
208 : // EventTarget
209 : void GetEventTargetParent(mozilla::EventChainPreVisitor& aVisitor) override;
210 : virtual mozilla::EventListenerManager*
211 : GetOrCreateListenerManager() override;
212 : virtual mozilla::EventListenerManager*
213 : GetExistingListenerManager() const override;
214 :
215 : // nsIScriptObjectPrincipal
216 : virtual nsIPrincipal* GetPrincipal() override;
217 :
218 : // nsIApplicationCacheContainer
219 : NS_DECL_NSIAPPLICATIONCACHECONTAINER
220 :
221 : virtual nsresult Init();
222 :
223 : virtual void Destroy() override;
224 : virtual void RemovedFromDocShell() override;
225 :
226 : virtual void BlockOnload() override;
227 : virtual void UnblockOnload(bool aFireSync) override;
228 :
229 39 : NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDocument,
230 : nsIDocument)
231 :
232 56 : void SetLoadedAsData(bool aLoadedAsData) { mLoadedAsData = aLoadedAsData; }
233 : void SetLoadedAsInteractiveData(bool aLoadedAsInteractiveData)
234 : {
235 0 : mLoadedAsInteractiveData = aLoadedAsInteractiveData;
236 : }
237 :
238 : nsresult CloneDocHelper(nsDocument* clone, bool aPreallocateChildren) const;
239 :
240 : // Only BlockOnload should call this!
241 : void AsyncBlockOnload();
242 :
243 : virtual void DocAddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const override;
244 : // DocAddSizeOfIncludingThis is inherited from nsIDocument.
245 :
246 : protected:
247 : friend class nsNodeUtils;
248 :
249 : void RetrieveRelevantHeaders(nsIChannel *aChannel);
250 :
251 : void TryChannelCharset(nsIChannel *aChannel,
252 : int32_t& aCharsetSource,
253 : NotNull<const Encoding*>& aEncoding,
254 : nsHtml5TreeOpExecutor* aExecutor);
255 :
256 : nsIContent* GetFirstBaseNodeWithHref();
257 : nsresult SetFirstBaseNodeWithHref(nsIContent *node);
258 :
259 : #define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) do { \
260 : NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
261 : func_, params_); \
262 : /* FIXME(emilio): Apparently we can keep observing from the BFCache? That \
263 : looks bogus. */ \
264 : if (nsIPresShell* shell = GetObservingShell()) { \
265 : shell->func_ params_; \
266 : } \
267 : } while(0)
268 :
269 : #ifdef DEBUG
270 : void VerifyRootContentState();
271 : #endif
272 :
273 : explicit nsDocument(const char* aContentType);
274 : virtual ~nsDocument();
275 :
276 : public:
277 : // FIXME(emilio): This needs to be here instead of in nsIDocument because Rust
278 : // can't represent alignas(8) values on 32-bit architectures, which would
279 : // cause nsIDocument's layout to be wrong in the Rust side.
280 : //
281 : // This can be fixed after updating to rust 1.25 and updating bindgen to
282 : // include https://github.com/rust-lang-nursery/rust-bindgen/pull/1271.
283 : js::ExpandoAndGeneration mExpandoAndGeneration;
284 :
285 : nsClassHashtable<nsStringHashKey, nsRadioGroupStruct> mRadioGroups;
286 :
287 : friend class nsCallRequestFullScreen;
288 :
289 : // The application cache that this document is associated with, if
290 : // any. This can change during the lifetime of the document.
291 : nsCOMPtr<nsIApplicationCache> mApplicationCache;
292 :
293 : nsCOMPtr<nsIContent> mFirstBaseNodeWithHref;
294 : private:
295 : friend class nsUnblockOnloadEvent;
296 :
297 : // These are not implemented and not supported.
298 : nsDocument(const nsDocument& aOther);
299 : nsDocument& operator=(const nsDocument& aOther);
300 : };
301 :
302 : class nsDocumentOnStack
303 : {
304 : public:
305 509 : explicit nsDocumentOnStack(nsIDocument* aDoc) : mDoc(aDoc)
306 : {
307 509 : mDoc->IncreaseStackRefCnt();
308 : }
309 509 : ~nsDocumentOnStack()
310 0 : {
311 0 : mDoc->DecreaseStackRefCnt();
312 0 : }
313 : private:
314 : nsIDocument* mDoc;
315 : };
316 :
317 : #endif /* nsDocument_h___ */
|