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 #ifndef nsPIDOMWindow_h__
8 #define nsPIDOMWindow_h__
9 
10 #include "nsIDOMWindow.h"
11 #include "mozIDOMWindow.h"
12 
13 #include "nsCOMPtr.h"
14 #include "nsTArray.h"
15 #include "Units.h"
16 #include "mozilla/dom/EventTarget.h"
17 #include "mozilla/EventForwards.h"
18 #include "mozilla/Maybe.h"
19 #include "mozilla/TaskCategory.h"
20 #include "js/TypeDecls.h"
21 #include "nsRefPtrHashtable.h"
22 #include "nsILoadInfo.h"
23 
24 // Only fired for inner windows.
25 #define DOM_WINDOW_DESTROYED_TOPIC "dom-window-destroyed"
26 #define DOM_WINDOW_FROZEN_TOPIC "dom-window-frozen"
27 #define DOM_WINDOW_THAWED_TOPIC "dom-window-thawed"
28 
29 class nsDOMOfflineResourceList;
30 class nsGlobalWindowInner;
31 class nsGlobalWindowOuter;
32 class nsIArray;
33 class nsIBaseWindow;
34 class nsIChannel;
35 class nsIContent;
36 class nsIContentSecurityPolicy;
37 class nsICSSDeclaration;
38 class nsIDocShell;
39 class nsIDocShellTreeOwner;
40 class nsDocShellLoadState;
41 class nsIPrincipal;
42 class nsIRunnable;
43 class nsIScriptTimeoutHandler;
44 class nsISerialEventTarget;
45 class nsIURI;
46 class nsIWebBrowserChrome;
47 class nsPIDOMWindowInner;
48 class nsPIDOMWindowOuter;
49 class nsPIWindowRoot;
50 
51 using SuspendTypes = uint32_t;
52 
53 namespace mozilla {
54 namespace dom {
55 class AudioContext;
56 class BrowsingContext;
57 class BrowsingContextGroup;
58 class ClientInfo;
59 class ClientState;
60 class ContentFrameMessageManager;
61 class DocGroup;
62 class Document;
63 class Element;
64 class Location;
65 class MediaDevices;
66 class MediaKeys;
67 class Navigator;
68 class Performance;
69 class Selection;
70 class ServiceWorker;
71 class ServiceWorkerDescriptor;
72 class Timeout;
73 class TimeoutManager;
74 class WindowContext;
75 class WindowGlobalChild;
76 class CustomElementRegistry;
77 enum class CallerType : uint32_t;
78 }  // namespace dom
79 }  // namespace mozilla
80 
81 enum UIStateChangeType {
82   UIStateChangeType_NoChange,
83   UIStateChangeType_Set,
84   UIStateChangeType_Clear,
85   UIStateChangeType_Invalid  // used for serialization only
86 };
87 
88 enum class FullscreenReason {
89   // Toggling the fullscreen mode requires trusted context.
90   ForFullscreenMode,
91   // Fullscreen API is the API provided to untrusted content.
92   ForFullscreenAPI,
93   // This reason can only be used with exiting fullscreen.
94   // It is otherwise identical to eForFullscreenAPI except it would
95   // suppress the fullscreen transition.
96   ForForceExitFullscreen
97 };
98 
99 // Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs
100 #define NS_PIDOMWINDOWINNER_IID                      \
101   {                                                  \
102     0x775dabc9, 0x8f43, 0x4277, {                    \
103       0x9a, 0xdb, 0xf1, 0x99, 0x0d, 0x77, 0xcf, 0xfb \
104     }                                                \
105   }
106 
107 // Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs
108 #define NS_PIDOMWINDOWOUTER_IID                      \
109   {                                                  \
110     0x769693d4, 0xb009, 0x4fe2, {                    \
111       0xaf, 0x18, 0x7d, 0xc8, 0xdf, 0x74, 0x96, 0xdf \
112     }                                                \
113   }
114 
115 class nsPIDOMWindowInner : public mozIDOMWindow {
116  protected:
117   using Document = mozilla::dom::Document;
118   friend nsGlobalWindowInner;
119   friend nsGlobalWindowOuter;
120 
121   nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow,
122                      mozilla::dom::WindowGlobalChild* aActor);
123 
124   ~nsPIDOMWindowInner();
125 
126  public:
127   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOWINNER_IID)
128 
129   nsIGlobalObject* AsGlobal();
130   const nsIGlobalObject* AsGlobal() const;
131 
GetOuterWindow()132   nsPIDOMWindowOuter* GetOuterWindow() const { return mOuterWindow; }
133 
From(mozIDOMWindow * aFrom)134   static nsPIDOMWindowInner* From(mozIDOMWindow* aFrom) {
135     return static_cast<nsPIDOMWindowInner*>(aFrom);
136   }
137 
138   NS_IMPL_FROMEVENTTARGET_HELPER_WITH_GETTER(nsPIDOMWindowInner,
139                                              GetAsWindowInner())
140 
141   // Returns true if this object is the currently-active inner window for its
142   // BrowsingContext.
143   bool IsCurrentInnerWindow() const;
144 
145   // Returns true if the document of this window is the active document.  This
146   // is identical to IsCurrentInnerWindow() now that document.open() no longer
147   // creates new inner windows for the document it is called on.
148   inline bool HasActiveDocument();
149 
150   // Return true if this object is the currently-active inner window for its
151   // BrowsingContext and any container document is also fully active.
152   // For https://html.spec.whatwg.org/multipage/browsers.html#fully-active
153   bool IsFullyActive() const;
154 
155   // Returns true if this window is the same as mTopInnerWindow
156   inline bool IsTopInnerWindow() const;
157 
158   // Returns true if this was the current window for its BrowsingContext when it
159   // was discarded.
160   virtual bool WasCurrentInnerWindow() const = 0;
161 
162   // Check whether a document is currently loading (really checks if the
163   // load event has completed).  May not be reset to false on errors.
164   inline bool IsLoading() const;
165   inline bool IsHandlingResizeEvent() const;
166 
167   // Note: not related to IsLoading.  Set to false if there's an error, etc.
168   virtual void SetActiveLoadingState(bool aIsActiveLoading) = 0;
169 
170   bool AddAudioContext(mozilla::dom::AudioContext* aAudioContext);
171   void RemoveAudioContext(mozilla::dom::AudioContext* aAudioContext);
172   void MuteAudioContexts();
173   void UnmuteAudioContexts();
174 
175   void SetAudioCapture(bool aCapture);
176 
177   /**
178    * Associate this inner window with a MediaKeys instance.
179    */
180   void AddMediaKeysInstance(mozilla::dom::MediaKeys* aMediaKeysInstance);
181 
182   /**
183    * Remove an association between this inner window and a MediaKeys instance.
184    */
185   void RemoveMediaKeysInstance(mozilla::dom::MediaKeys* aMediaKeysInstance);
186 
187   /**
188    * Return if any MediaKeys instances are associated with this window.
189    */
190   bool HasActiveMediaKeysInstance();
191 
192   mozilla::dom::Performance* GetPerformance();
193 
194   void QueuePerformanceNavigationTiming();
195 
HasMutationListeners(uint32_t aMutationEventType)196   bool HasMutationListeners(uint32_t aMutationEventType) const {
197     if (!mOuterWindow) {
198       NS_ERROR("HasMutationListeners() called on orphan inner window!");
199 
200       return false;
201     }
202 
203     return (mMutationBits & aMutationEventType) != 0;
204   }
205 
SetMutationListeners(uint32_t aType)206   void SetMutationListeners(uint32_t aType) {
207     if (!mOuterWindow) {
208       NS_ERROR("HasMutationListeners() called on orphan inner window!");
209 
210       return;
211     }
212 
213     mMutationBits |= aType;
214   }
215 
216   /**
217    * Call this to check whether some node (this window, its document,
218    * or content in that document) has a mouseenter/leave event listener.
219    */
HasMouseEnterLeaveEventListeners()220   bool HasMouseEnterLeaveEventListeners() const {
221     return mMayHaveMouseEnterLeaveEventListener;
222   }
223 
224   /**
225    * Call this to indicate that some node (this window, its document,
226    * or content in that document) has a mouseenter/leave event listener.
227    */
SetHasMouseEnterLeaveEventListeners()228   void SetHasMouseEnterLeaveEventListeners() {
229     mMayHaveMouseEnterLeaveEventListener = true;
230   }
231 
232   /**
233    * Call this to check whether some node (this window, its document,
234    * or content in that document) has a Pointerenter/leave event listener.
235    */
HasPointerEnterLeaveEventListeners()236   bool HasPointerEnterLeaveEventListeners() const {
237     return mMayHavePointerEnterLeaveEventListener;
238   }
239 
240   /**
241    * Call this to indicate that some node (this window, its document,
242    * or content in that document) has a Pointerenter/leave event listener.
243    */
SetHasPointerEnterLeaveEventListeners()244   void SetHasPointerEnterLeaveEventListeners() {
245     mMayHavePointerEnterLeaveEventListener = true;
246   }
247 
248   /**
249    * Call this to check whether some node (this window, its document,
250    * or content in that document) has a beforeinput event listener.
251    * Returing false may be wrong if some nodes have come from another document
252    * with `Document.adoptNode`.
253    */
HasBeforeInputEventListenersForTelemetry()254   bool HasBeforeInputEventListenersForTelemetry() const {
255     return mMayHaveBeforeInputEventListenerForTelemetry;
256   }
257 
258   /**
259    * Call this to indicate that some node (this window, its document,
260    * or content in that document) has a beforeinput event listener.
261    */
SetHasBeforeInputEventListenersForTelemetry()262   void SetHasBeforeInputEventListenersForTelemetry() {
263     mMayHaveBeforeInputEventListenerForTelemetry = true;
264   }
265 
266   /**
267    * Call this to check whether some node (The document, or content in the
268    * document) has been observed by web apps with a mutation observer.
269    * (i.e., `MutationObserver.observe()` called by chrome script and addon's
270    * script does not make this returns true).
271    * Returing false may be wrong if some nodes have come from another document
272    * with `Document.adoptNode`.
273    */
MutationObserverHasObservedNodeForTelemetry()274   bool MutationObserverHasObservedNodeForTelemetry() const {
275     return mMutationObserverHasObservedNodeForTelemetry;
276   }
277 
278   /**
279    * Call this to indicate that some node (The document, or content in the
280    * document) is observed by web apps with a mutation observer.
281    */
SetMutationObserverHasObservedNodeForTelemetry()282   void SetMutationObserverHasObservedNodeForTelemetry() {
283     mMutationObserverHasObservedNodeForTelemetry = true;
284   }
285 
286   // Sets the event for window.event. Does NOT take ownership, so
287   // the caller is responsible for clearing the event before the
288   // event gets deallocated. Pass nullptr to set window.event to
289   // undefined. Returns the previous value.
SetEvent(mozilla::dom::Event * aEvent)290   mozilla::dom::Event* SetEvent(mozilla::dom::Event* aEvent) {
291     mozilla::dom::Event* old = mEvent;
292     mEvent = aEvent;
293     return old;
294   }
295 
296   /**
297    * Check whether this window is a secure context.
298    */
299   bool IsSecureContext() const;
300   bool IsSecureContextIfOpenerIgnored() const;
301 
302   // Calling suspend should prevent any asynchronous tasks from
303   // executing javascript for this window.  This means setTimeout,
304   // requestAnimationFrame, and events should not be fired. Suspending
305   // a window maybe also suspends its children.  Workers may
306   // continue to perform computations in the background.  A window
307   // can have Suspend() called multiple times and will only resume after
308   // a matching number of Resume() calls.
309   void Suspend(bool aIncludeSubWindows = true);
310   void Resume(bool aIncludeSubWindows = true);
311 
312   // Whether or not this window was suspended by the BrowserContextGroup
GetWasSuspendedByGroup()313   bool GetWasSuspendedByGroup() const { return mWasSuspendedByGroup; }
SetWasSuspendedByGroup(bool aSuspended)314   void SetWasSuspendedByGroup(bool aSuspended) {
315     mWasSuspendedByGroup = aSuspended;
316   }
317 
318   // Apply the parent window's suspend, freeze, and modal state to the current
319   // window.
320   void SyncStateFromParentWindow();
321 
322   /**
323    * Increment active peer connection count.
324    */
325   void AddPeerConnection();
326 
327   /**
328    * Decrement active peer connection count.
329    */
330   void RemovePeerConnection();
331 
332   /**
333    * Check whether the active peer connection count is non-zero.
334    */
335   bool HasActivePeerConnections();
336 
337   bool IsPlayingAudio();
338 
339   bool IsDocumentLoaded() const;
340 
341   mozilla::dom::TimeoutManager& TimeoutManager();
342 
343   bool IsRunningTimeout();
344 
345   // To cache top inner-window if available after constructed for tab-wised
346   // indexedDB counters.
347   void TryToCacheTopInnerWindow();
348 
349   // Increase/Decrease the number of active IndexedDB databases for the
350   // decision making of timeout-throttling.
351   void UpdateActiveIndexedDBDatabaseCount(int32_t aDelta);
352 
353   // Return true if there is any active IndexedDB databases which could block
354   // timeout-throttling.
355   bool HasActiveIndexedDBDatabases();
356 
357   // Increase/Decrease the number of open WebSockets.
358   void UpdateWebSocketCount(int32_t aDelta);
359 
360   // Return true if there are any open WebSockets that could block
361   // timeout-throttling.
362   bool HasOpenWebSockets() const;
363 
364   mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
365   mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
366   mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
367 
368   void SetCsp(nsIContentSecurityPolicy* aCsp);
369   void SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp);
370   nsIContentSecurityPolicy* GetCsp();
371 
372   void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
373 
374   void NoteDOMContentLoaded();
375 
376   virtual mozilla::dom::CustomElementRegistry* CustomElements() = 0;
377 
378   // XXX: This is called on inner windows
379   virtual nsPIDOMWindowOuter* GetInProcessScriptableTop() = 0;
380   virtual nsPIDOMWindowOuter* GetInProcessScriptableParent() = 0;
381   virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() = 0;
382 
GetChromeEventHandler()383   mozilla::dom::EventTarget* GetChromeEventHandler() const {
384     return mChromeEventHandler;
385   }
386 
GetParentTarget()387   mozilla::dom::EventTarget* GetParentTarget() {
388     if (!mParentTarget) {
389       UpdateParentTarget();
390     }
391     return mParentTarget;
392   }
393 
MaybeUpdateTouchState()394   virtual void MaybeUpdateTouchState() {}
395 
GetExtantDoc()396   Document* GetExtantDoc() const { return mDoc; }
397   nsIURI* GetDocumentURI() const;
398   nsIURI* GetDocBaseURI() const;
399 
GetDoc()400   Document* GetDoc() {
401     if (!mDoc) {
402       MaybeCreateDoc();
403     }
404     return mDoc;
405   }
406 
407   mozilla::dom::WindowContext* GetWindowContext() const;
GetWindowGlobalChild()408   mozilla::dom::WindowGlobalChild* GetWindowGlobalChild() const {
409     return mWindowGlobalChild;
410   }
411 
412   // Removes this inner window from the BFCache, if it is cached, and returns
413   // true if it was.
414   bool RemoveFromBFCacheSync();
415 
416   // Determine if the window is suspended or frozen.  Outer windows
417   // will forward this call to the inner window for convenience.  If
418   // there is no inner window then the outer window is considered
419   // suspended and frozen by default.
420   virtual bool IsSuspended() const = 0;
421   virtual bool IsFrozen() const = 0;
422 
423   // Fire any DOM notification events related to things that happened while
424   // the window was frozen.
425   virtual nsresult FireDelayedDOMEvents(bool aIncludeSubWindows) = 0;
426 
427   /**
428    * Get the docshell in this window.
429    */
430   inline nsIDocShell* GetDocShell() const;
431 
432   /**
433    * Get the browsing context in this window.
434    */
435   inline mozilla::dom::BrowsingContext* GetBrowsingContext() const;
436 
437   /**
438    * Get the browsing context group this window belongs to.
439    */
440   mozilla::dom::BrowsingContextGroup* GetBrowsingContextGroup() const;
441 
442   /**
443    * Call this to indicate that some node (this window, its document,
444    * or content in that document) has a paint event listener.
445    */
SetHasPaintEventListeners()446   void SetHasPaintEventListeners() { mMayHavePaintEventListener = true; }
447 
448   /**
449    * Call this to check whether some node (this window, its document,
450    * or content in that document) has a paint event listener.
451    */
HasPaintEventListeners()452   bool HasPaintEventListeners() { return mMayHavePaintEventListener; }
453 
454   /**
455    * Call this to indicate that some node (this window, its document,
456    * or content in that document) has a touch event listener.
457    */
SetHasTouchEventListeners()458   void SetHasTouchEventListeners() {
459     if (!mMayHaveTouchEventListener) {
460       mMayHaveTouchEventListener = true;
461       MaybeUpdateTouchState();
462     }
463   }
464 
465   /**
466    * Call this to indicate that some node (this window, its document,
467    * or content in that document) has a selectionchange event listener.
468    */
SetHasSelectionChangeEventListeners()469   void SetHasSelectionChangeEventListeners() {
470     mMayHaveSelectionChangeEventListener = true;
471   }
472 
473   /**
474    * Call this to check whether some node (this window, its document,
475    * or content in that document) has a selectionchange event listener.
476    */
HasSelectionChangeEventListeners()477   bool HasSelectionChangeEventListeners() const {
478     return mMayHaveSelectionChangeEventListener;
479   }
480 
481   /**
482    * Call this to indicate that some node (this window, its document,
483    * or content in that document) has a select event listener of form controls.
484    */
SetHasFormSelectEventListeners()485   void SetHasFormSelectEventListeners() {
486     mMayHaveFormSelectEventListener = true;
487   }
488 
489   /**
490    * Call this to check whether some node (this window, its document,
491    * or content in that document) has a select event listener of form controls.
492    */
HasFormSelectEventListeners()493   bool HasFormSelectEventListeners() const {
494     return mMayHaveFormSelectEventListener;
495   }
496 
497   /*
498    * Get and set the currently focused element within the document. If
499    * aNeedsFocus is true, then set mNeedsFocus to true to indicate that a
500    * document focus event is needed.
501    *
502    * DO NOT CALL EITHER OF THESE METHODS DIRECTLY. USE THE FOCUS MANAGER
503    * INSTEAD.
504    */
GetFocusedElement()505   mozilla::dom::Element* GetFocusedElement() const {
506     return mFocusedElement.get();
507   }
508 
509   virtual void SetFocusedElement(mozilla::dom::Element* aElement,
510                                  uint32_t aFocusMethod = 0,
511                                  bool aNeedsFocus = false) = 0;
512 
UnknownFocusMethodShouldShowOutline()513   bool UnknownFocusMethodShouldShowOutline() const {
514     return mUnknownFocusMethodShouldShowOutline;
515   }
516 
517   /**
518    * Retrieves the method that was used to focus the current node.
519    */
520   virtual uint32_t GetFocusMethod() = 0;
521 
522   /*
523    * Tells the window that it now has focus or has lost focus, based on the
524    * state of aFocus. If this method returns true, then the document loaded
525    * in the window has never received a focus event and expects to receive
526    * one. If false is returned, the document has received a focus event before
527    * and should only receive one if the window is being focused.
528    *
529    * aFocusMethod may be set to one of the focus method constants in
530    * nsIFocusManager to indicate how focus was set.
531    */
532   virtual bool TakeFocus(bool aFocus, uint32_t aFocusMethod) = 0;
533 
534   /**
535    * Indicates that the window may now accept a document focus event. This
536    * should be called once a document has been loaded into the window.
537    */
538   virtual void SetReadyForFocus() = 0;
539 
540   /**
541    * Whether the focused content within the window should show a focus ring.
542    */
543   virtual bool ShouldShowFocusRing() = 0;
544 
545   /**
546    * Indicates that the page in the window has been hidden. This is used to
547    * reset the focus state.
548    */
549   virtual void PageHidden() = 0;
550 
551   /**
552    * Instructs this window to asynchronously dispatch a hashchange event.  This
553    * method must be called on an inner window.
554    */
555   virtual nsresult DispatchAsyncHashchange(nsIURI* aOldURI,
556                                            nsIURI* aNewURI) = 0;
557 
558   /**
559    * Instructs this window to synchronously dispatch a popState event.
560    */
561   virtual nsresult DispatchSyncPopState() = 0;
562 
563   /**
564    * Tell this window that it should listen for sensor changes of the given
565    * type.
566    */
567   virtual void EnableDeviceSensor(uint32_t aType) = 0;
568 
569   /**
570    * Tell this window that it should remove itself from sensor change
571    * notifications.
572    */
573   virtual void DisableDeviceSensor(uint32_t aType) = 0;
574 
575 #if defined(MOZ_WIDGET_ANDROID)
576   virtual void EnableOrientationChangeListener() = 0;
577   virtual void DisableOrientationChangeListener() = 0;
578 #endif
579 
580   /**
581    * Tell this window that there is an observer for gamepad input
582    *
583    * Inner windows only.
584    */
585   virtual void SetHasGamepadEventListener(bool aHasGamepad = true) = 0;
586 
587   /**
588    * Return the window id of this window
589    */
WindowID()590   uint64_t WindowID() const { return mWindowID; }
591 
592   // WebIDL-ish APIs
MarkUncollectableForCCGeneration(uint32_t aGeneration)593   void MarkUncollectableForCCGeneration(uint32_t aGeneration) {
594     mMarkedCCGeneration = aGeneration;
595   }
596 
GetMarkedCCGeneration()597   uint32_t GetMarkedCCGeneration() { return mMarkedCCGeneration; }
598 
599   mozilla::dom::Navigator* Navigator();
600   mozilla::dom::MediaDevices* GetExtantMediaDevices() const;
601   virtual mozilla::dom::Location* Location() = 0;
602 
603   virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
604 
605   virtual nsresult GetInnerWidth(double* aWidth) = 0;
606   virtual nsresult GetInnerHeight(double* aHeight) = 0;
607 
608   virtual already_AddRefed<nsICSSDeclaration> GetComputedStyle(
609       mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
610       mozilla::ErrorResult& aError) = 0;
611 
612   virtual nsDOMOfflineResourceList* GetApplicationCache() = 0;
613 
614   virtual bool GetFullScreen() = 0;
615 
616   virtual nsresult Focus(mozilla::dom::CallerType aCallerType) = 0;
617   virtual nsresult Close() = 0;
618 
619   mozilla::dom::DocGroup* GetDocGroup() const;
620   virtual nsISerialEventTarget* EventTargetFor(
621       mozilla::TaskCategory aCategory) const = 0;
622 
623   void SaveStorageAccessPermissionGranted();
624 
625   bool HasStorageAccessPermissionGranted();
626 
UpdateLockCount(bool aIncrement)627   uint32_t UpdateLockCount(bool aIncrement) {
628     MOZ_ASSERT_IF(!aIncrement, mLockCount > 0);
629     mLockCount += aIncrement ? 1 : -1;
630     return mLockCount;
631   };
HasActiveLocks()632   bool HasActiveLocks() { return mLockCount > 0; }
633 
634  protected:
635   void CreatePerformanceObjectIfNeeded();
636 
637   // Lazily instantiate an about:blank document if necessary, and if
638   // we have what it takes to do so.
639   void MaybeCreateDoc();
640 
SetChromeEventHandlerInternal(mozilla::dom::EventTarget * aChromeEventHandler)641   void SetChromeEventHandlerInternal(
642       mozilla::dom::EventTarget* aChromeEventHandler) {
643     mChromeEventHandler = aChromeEventHandler;
644     // mParentTarget will be set when the next event is dispatched.
645     mParentTarget = nullptr;
646   }
647 
648   virtual void UpdateParentTarget() = 0;
649 
650   // These two variables are special in that they're set to the same
651   // value on both the outer window and the current inner window. Make
652   // sure you keep them in sync!
653   nsCOMPtr<mozilla::dom::EventTarget> mChromeEventHandler;  // strong
654   RefPtr<Document> mDoc;
655   // Cache the URI when mDoc is cleared.
656   nsCOMPtr<nsIURI> mDocumentURI;  // strong
657   nsCOMPtr<nsIURI> mDocBaseURI;   // strong
658 
659   nsCOMPtr<mozilla::dom::EventTarget> mParentTarget;  // strong
660 
661   RefPtr<mozilla::dom::Performance> mPerformance;
662   mozilla::UniquePtr<mozilla::dom::TimeoutManager> mTimeoutManager;
663 
664   RefPtr<mozilla::dom::Navigator> mNavigator;
665 
666   // These variables are only used on inner windows.
667   uint32_t mMutationBits;
668 
669   uint32_t mActivePeerConnections = 0;
670 
671   bool mIsDocumentLoaded;
672   bool mIsHandlingResizeEvent;
673   bool mMayHavePaintEventListener;
674   bool mMayHaveTouchEventListener;
675   bool mMayHaveSelectionChangeEventListener;
676   bool mMayHaveFormSelectEventListener;
677   bool mMayHaveMouseEnterLeaveEventListener;
678   bool mMayHavePointerEnterLeaveEventListener;
679   // Only used for telemetry probes.  This may be wrong if some nodes have
680   // come from another document with `Document.adoptNode`.
681   bool mMayHaveBeforeInputEventListenerForTelemetry;
682   bool mMutationObserverHasObservedNodeForTelemetry;
683 
684   // Our inner window's outer window.
685   nsCOMPtr<nsPIDOMWindowOuter> mOuterWindow;
686 
687   // The element within the document that is currently focused when this
688   // window is active.
689   RefPtr<mozilla::dom::Element> mFocusedElement;
690 
691   // The AudioContexts created for the current document, if any.
692   nsTArray<mozilla::dom::AudioContext*> mAudioContexts;  // Weak
693 
694   // Instances of MediaKeys created in this inner window. Storing these allows
695   // us to shutdown MediaKeys when an inner windows is destroyed. We can also
696   // use the presence of MediaKeys to assess if a window has EME activity.
697   nsTArray<mozilla::dom::MediaKeys*> mMediaKeysInstances;  // Weak
698 
699   RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
700 
701   // A unique (as long as our 64-bit counter doesn't roll over) id for
702   // this window.
703   uint64_t mWindowID;
704 
705   // Set to true once we've sent the (chrome|content)-document-global-created
706   // notification.
707   bool mHasNotifiedGlobalCreated;
708 
709   // Whether when focused via an "unknown" focus method, we should show outlines
710   // by default or not. The initial value of this is true (so as to show
711   // outlines for stuff like html autofocus, or initial programmatic focus
712   // without any other user interaction).
713   bool mUnknownFocusMethodShouldShowOutline = true;
714 
715   uint32_t mMarkedCCGeneration;
716 
717   // mTopInnerWindow is used for tab-wise check by timeout throttling. It could
718   // be null.
719   nsCOMPtr<nsPIDOMWindowInner> mTopInnerWindow;
720 
721   // The evidence that we have tried to cache mTopInnerWindow only once from
722   // SetNewDocument(). Note: We need this extra flag because mTopInnerWindow
723   // could be null and we don't want it to be set multiple times.
724   bool mHasTriedToCacheTopInnerWindow;
725 
726   // The number of active IndexedDB databases.
727   uint32_t mNumOfIndexedDBDatabases;
728 
729   // The number of open WebSockets.
730   uint32_t mNumOfOpenWebSockets;
731 
732   // The event dispatch code sets and unsets this while keeping
733   // the event object alive.
734   mozilla::dom::Event* mEvent;
735 
736   // A boolean flag indicating whether storage access is granted for the
737   // current window. These are also set as permissions, but it could happen
738   // that we need to access them synchronously in this context, and for
739   // this, we need a copy here.
740   bool mStorageAccessPermissionGranted;
741 
742   // The WindowGlobalChild actor for this window.
743   //
744   // This will be non-null during the full lifetime of the window, initialized
745   // during SetNewDocument, and cleared during FreeInnerObjects.
746   RefPtr<mozilla::dom::WindowGlobalChild> mWindowGlobalChild;
747 
748   bool mWasSuspendedByGroup;
749 
750   /**
751    * Count of the number of active LockRequest objects, including ones from
752    * workers.
753    */
754   uint32_t mLockCount = 0;
755 };
756 
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowInner,NS_PIDOMWINDOWINNER_IID)757 NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowInner, NS_PIDOMWINDOWINNER_IID)
758 
759 class nsPIDOMWindowOuter : public mozIDOMWindowProxy {
760  protected:
761   using Document = mozilla::dom::Document;
762 
763   explicit nsPIDOMWindowOuter(uint64_t aWindowID);
764 
765   ~nsPIDOMWindowOuter();
766 
767   void NotifyResumingDelayedMedia();
768 
769  public:
770   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOWOUTER_IID)
771 
772   NS_IMPL_FROMEVENTTARGET_HELPER_WITH_GETTER(nsPIDOMWindowOuter,
773                                              GetAsWindowOuter())
774 
775   static nsPIDOMWindowOuter* From(mozIDOMWindowProxy* aFrom) {
776     return static_cast<nsPIDOMWindowOuter*>(aFrom);
777   }
778 
779   // Given an inner window, return its outer if the inner is the current inner.
780   // Otherwise (argument null or not an inner or not current) return null.
781   static nsPIDOMWindowOuter* GetFromCurrentInner(nsPIDOMWindowInner* aInner);
782 
783   // Check whether a document is currently loading
784   inline bool IsLoading() const;
785   inline bool IsHandlingResizeEvent() const;
786 
787   nsPIDOMWindowInner* GetCurrentInnerWindow() const { return mInnerWindow; }
788 
789   nsPIDOMWindowInner* EnsureInnerWindow() {
790     // GetDoc forces inner window creation if there isn't one already
791     GetDoc();
792     return GetCurrentInnerWindow();
793   }
794 
795   bool IsRootOuterWindow() { return mIsRootOuterWindow; }
796 
797   /**
798    * Set initial keyboard indicator state for focus rings.
799    */
800   void SetInitialKeyboardIndicators(UIStateChangeType aShowFocusRings);
801 
802   // Internal getter/setter for the frame element, this version of the
803   // getter crosses chrome boundaries whereas the public scriptable
804   // one doesn't for security reasons.
805   mozilla::dom::Element* GetFrameElementInternal() const;
806   void SetFrameElementInternal(mozilla::dom::Element* aFrameElement);
807 
808   void SetDesktopModeViewport(bool aDesktopModeViewport) {
809     mDesktopModeViewport = aDesktopModeViewport;
810   }
811   bool IsDesktopModeViewport() const { return mDesktopModeViewport; }
812   bool IsBackground() { return mIsBackground; }
813 
814   // Audio API
815   bool GetAudioMuted() const;
816 
817   // No longer to delay media from starting for this window.
818   void ActivateMediaComponents();
819   bool ShouldDelayMediaFromStart() const;
820 
821   void RefreshMediaElementsVolume();
822 
823   virtual nsPIDOMWindowOuter* GetPrivateRoot() = 0;
824 
825   /**
826    * |top| gets the root of the window hierarchy.
827    *
828    * This function does not cross chrome-content boundaries, so if this
829    * window's parent is of a different type, |top| will return this window.
830    *
831    * When script reads the top property, we run GetInProcessScriptableTop,
832    * which will not cross an <iframe mozbrowser> boundary.
833    *
834    * In contrast, C++ calls to GetTop are forwarded to GetRealTop, which
835    * ignores <iframe mozbrowser> boundaries.
836    */
837 
838   virtual already_AddRefed<nsPIDOMWindowOuter>
839   GetInProcessTop() = 0;  // Outer only
840   virtual already_AddRefed<nsPIDOMWindowOuter> GetInProcessParent() = 0;
841   virtual nsPIDOMWindowOuter* GetInProcessScriptableTop() = 0;
842   virtual nsPIDOMWindowOuter* GetInProcessScriptableParent() = 0;
843   virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() = 0;
844 
845   /**
846    * Behaves identically to GetInProcessScriptableParent except that it
847    * returns null if GetInProcessScriptableParent would return this window.
848    */
849   virtual nsPIDOMWindowOuter* GetInProcessScriptableParentOrNull() = 0;
850 
851   virtual void SetIsBackground(bool aIsBackground) = 0;
852 
853   mozilla::dom::EventTarget* GetChromeEventHandler() const {
854     return mChromeEventHandler;
855   }
856 
857   virtual void SetChromeEventHandler(
858       mozilla::dom::EventTarget* aChromeEventHandler) = 0;
859 
860   mozilla::dom::EventTarget* GetParentTarget() {
861     if (!mParentTarget) {
862       UpdateParentTarget();
863     }
864     return mParentTarget;
865   }
866 
867   mozilla::dom::ContentFrameMessageManager* GetMessageManager() {
868     // We maintain our mMessageManager state alongside mParentTarget.
869     if (!mParentTarget) {
870       UpdateParentTarget();
871     }
872     return mMessageManager;
873   }
874 
875   Document* GetExtantDoc() const { return mDoc; }
876   nsIURI* GetDocumentURI() const;
877 
878   Document* GetDoc() {
879     if (!mDoc) {
880       MaybeCreateDoc();
881     }
882     return mDoc;
883   }
884 
885   // Set the window up with an about:blank document with the current subject
886   // principal and potentially a CSP and a COEP.
887   virtual void SetInitialPrincipalToSubject(
888       nsIContentSecurityPolicy* aCSP,
889       const mozilla::Maybe<nsILoadInfo::CrossOriginEmbedderPolicy>& aCoep) = 0;
890 
891   // Returns an object containing the window's state.  This also suspends
892   // all running timeouts in the window.
893   virtual already_AddRefed<nsISupports> SaveWindowState() = 0;
894 
895   // Restore the window state from aState.
896   virtual nsresult RestoreWindowState(nsISupports* aState) = 0;
897 
898   // Determine if the window is suspended or frozen.  Outer windows
899   // will forward this call to the inner window for convenience.  If
900   // there is no inner window then the outer window is considered
901   // suspended and frozen by default.
902   virtual bool IsSuspended() const = 0;
903   virtual bool IsFrozen() const = 0;
904 
905   // Fire any DOM notification events related to things that happened while
906   // the window was frozen.
907   virtual nsresult FireDelayedDOMEvents(bool aIncludeSubWindows) = 0;
908 
909   /**
910    * Get the docshell in this window.
911    */
912   inline nsIDocShell* GetDocShell() const;
913 
914   /**
915    * Get the browsing context in this window.
916    */
917   inline mozilla::dom::BrowsingContext* GetBrowsingContext() const;
918 
919   /**
920    * Get the browsing context group this window belongs to.
921    */
922   mozilla::dom::BrowsingContextGroup* GetBrowsingContextGroup() const;
923 
924   /**
925    * Set a new document in the window. Calling this method will in most cases
926    * create a new inner window. This may be called with a pointer to the current
927    * document, in that case the document remains unchanged, but a new inner
928    * window will be created.
929    *
930    * aDocument must not be null.
931    */
932   virtual nsresult SetNewDocument(
933       Document* aDocument, nsISupports* aState, bool aForceReuseInnerWindow,
934       mozilla::dom::WindowGlobalChild* aActor = nullptr) = 0;
935 
936   /**
937    * Ensure the size and position of this window are up-to-date by doing
938    * a layout flush in the parent (which will in turn, do a layout flush
939    * in its parent, etc.).
940    */
941   virtual void EnsureSizeAndPositionUpToDate() = 0;
942 
943   /**
944    * Suppresses/unsuppresses user initiated event handling in window's document
945    * and all in-process descendant documents.
946    */
947   virtual void SuppressEventHandling() = 0;
948   virtual void UnsuppressEventHandling() = 0;
949 
950   /**
951    * Callback for notifying a window about a modal dialog being
952    * opened/closed with the window as a parent.
953    *
954    * If any script can run between the enter and leave modal states, and the
955    * window isn't top, the LeaveModalState() should be called on the window
956    * returned by EnterModalState().
957    */
958   virtual nsPIDOMWindowOuter* EnterModalState() = 0;
959   virtual void LeaveModalState() = 0;
960 
961   virtual bool CanClose() = 0;
962   virtual void ForceClose() = 0;
963 
964   /**
965    * Moves the top-level window into fullscreen mode if aIsFullScreen is true,
966    * otherwise exits fullscreen.
967    */
968   virtual nsresult SetFullscreenInternal(FullscreenReason aReason,
969                                          bool aIsFullscreen) = 0;
970   virtual void FullscreenWillChange(bool aIsFullscreen) = 0;
971   /**
972    * This function should be called when the fullscreen state is flipped.
973    * If no widget is involved the fullscreen change, this method is called
974    * by SetFullscreenInternal, otherwise, it is called when the widget
975    * finishes its change to or from fullscreen.
976    *
977    * @param aIsFullscreen indicates whether the widget is in fullscreen.
978    */
979   virtual void FinishFullscreenChange(bool aIsFullscreen) = 0;
980 
981   virtual void ForceFullScreenInWidget() = 0;
982 
983   virtual void MacFullscreenMenubarOverlapChanged(
984       mozilla::DesktopCoord aOverlapAmount) = 0;
985 
986   // XXX: These focus methods all forward to the inner, could we change
987   // consumers to call these on the inner directly?
988 
989   /*
990    * Get and set the currently focused element within the document. If
991    * aNeedsFocus is true, then set mNeedsFocus to true to indicate that a
992    * document focus event is needed.
993    *
994    * DO NOT CALL EITHER OF THESE METHODS DIRECTLY. USE THE FOCUS MANAGER
995    * INSTEAD.
996    */
997   inline mozilla::dom::Element* GetFocusedElement() const;
998 
999   virtual void SetFocusedElement(mozilla::dom::Element* aElement,
1000                                  uint32_t aFocusMethod = 0,
1001                                  bool aNeedsFocus = false) = 0;
1002   /**
1003    * Get whether a focused element focused by unknown reasons (like script
1004    * focus) should match the :focus-visible pseudo-class.
1005    */
1006   bool UnknownFocusMethodShouldShowOutline() const;
1007 
1008   /**
1009    * Retrieves the method that was used to focus the current node.
1010    */
1011   virtual uint32_t GetFocusMethod() = 0;
1012 
1013   /*
1014    * Tells the window that it now has focus or has lost focus, based on the
1015    * state of aFocus. If this method returns true, then the document loaded
1016    * in the window has never received a focus event and expects to receive
1017    * one. If false is returned, the document has received a focus event before
1018    * and should only receive one if the window is being focused.
1019    *
1020    * aFocusMethod may be set to one of the focus method constants in
1021    * nsIFocusManager to indicate how focus was set.
1022    */
1023   virtual bool TakeFocus(bool aFocus, uint32_t aFocusMethod) = 0;
1024 
1025   /**
1026    * Indicates that the window may now accept a document focus event. This
1027    * should be called once a document has been loaded into the window.
1028    */
1029   virtual void SetReadyForFocus() = 0;
1030 
1031   /**
1032    * Whether the focused content within the window should show a focus ring.
1033    */
1034   virtual bool ShouldShowFocusRing() = 0;
1035 
1036   /**
1037    * Set the keyboard indicator state for accelerators and focus rings.
1038    */
1039   virtual void SetKeyboardIndicators(UIStateChangeType aShowFocusRings) = 0;
1040 
1041   /**
1042    * Indicates that the page in the window has been hidden. This is used to
1043    * reset the focus state.
1044    */
1045   virtual void PageHidden() = 0;
1046 
1047   /**
1048    * Return the window id of this window
1049    */
1050   uint64_t WindowID() const { return mWindowID; }
1051 
1052   /**
1053    * Dispatch a custom event with name aEventName targeted at this window.
1054    * Returns whether the default action should be performed.
1055    *
1056    * Outer windows only.
1057    */
1058   virtual bool DispatchCustomEvent(
1059       const nsAString& aEventName,
1060       mozilla::ChromeOnlyDispatch aChromeOnlyDispatch =
1061           mozilla::ChromeOnlyDispatch::eNo) = 0;
1062 
1063   /**
1064    * Like nsIDOMWindow::Open, except that we don't navigate to the given URL.
1065    *
1066    * Outer windows only.
1067    */
1068   virtual nsresult OpenNoNavigate(const nsAString& aUrl, const nsAString& aName,
1069                                   const nsAString& aOptions,
1070                                   mozilla::dom::BrowsingContext** _retval) = 0;
1071 
1072   /**
1073    * Fire a popup blocked event on the document.
1074    */
1075   virtual void FirePopupBlockedEvent(Document* aDoc, nsIURI* aPopupURI,
1076                                      const nsAString& aPopupWindowName,
1077                                      const nsAString& aPopupWindowFeatures) = 0;
1078 
1079   // WebIDL-ish APIs
1080   void MarkUncollectableForCCGeneration(uint32_t aGeneration) {
1081     mMarkedCCGeneration = aGeneration;
1082   }
1083 
1084   uint32_t GetMarkedCCGeneration() { return mMarkedCCGeneration; }
1085 
1086   // XXX(nika): These feel like they should be inner window only, but they're
1087   // called on the outer window.
1088   virtual mozilla::dom::Navigator* GetNavigator() = 0;
1089   virtual mozilla::dom::Location* GetLocation() = 0;
1090 
1091   virtual nsresult GetPrompter(nsIPrompt** aPrompt) = 0;
1092   virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
1093   virtual already_AddRefed<mozilla::dom::Selection> GetSelection() = 0;
1094   virtual mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder>
1095   GetOpener() = 0;
1096 
1097   // aLoadState will be passed on through to the windowwatcher.
1098   // aForceNoOpener will act just like a "noopener" feature in aOptions except
1099   //                will not affect any other window features.
1100   virtual nsresult Open(const nsAString& aUrl, const nsAString& aName,
1101                         const nsAString& aOptions,
1102                         nsDocShellLoadState* aLoadState, bool aForceNoOpener,
1103                         mozilla::dom::BrowsingContext** _retval) = 0;
1104   virtual nsresult OpenDialog(const nsAString& aUrl, const nsAString& aName,
1105                               const nsAString& aOptions,
1106                               nsISupports* aExtraArgument,
1107                               mozilla::dom::BrowsingContext** _retval) = 0;
1108 
1109   virtual nsresult GetInnerWidth(double* aWidth) = 0;
1110   virtual nsresult GetInnerHeight(double* aHeight) = 0;
1111 
1112   virtual mozilla::dom::Element* GetFrameElement() = 0;
1113 
1114   virtual bool Closed() = 0;
1115   virtual bool GetFullScreen() = 0;
1116   virtual nsresult SetFullScreen(bool aFullscreen) = 0;
1117 
1118   virtual nsresult Focus(mozilla::dom::CallerType aCallerType) = 0;
1119   virtual nsresult Close() = 0;
1120 
1121   virtual nsresult MoveBy(int32_t aXDif, int32_t aYDif) = 0;
1122 
1123   virtual void UpdateCommands(const nsAString& anAction,
1124                               mozilla::dom::Selection* aSel,
1125                               int16_t aReason) = 0;
1126 
1127   mozilla::dom::DocGroup* GetDocGroup() const;
1128   virtual nsISerialEventTarget* EventTargetFor(
1129       mozilla::TaskCategory aCategory) const = 0;
1130 
1131   already_AddRefed<nsIDocShellTreeOwner> GetTreeOwner();
1132   already_AddRefed<nsIBaseWindow> GetTreeOwnerWindow();
1133   already_AddRefed<nsIWebBrowserChrome> GetWebBrowserChrome();
1134 
1135  protected:
1136   // Lazily instantiate an about:blank document if necessary, and if
1137   // we have what it takes to do so.
1138   void MaybeCreateDoc();
1139 
1140   void SetChromeEventHandlerInternal(
1141       mozilla::dom::EventTarget* aChromeEventHandler);
1142 
1143   virtual void UpdateParentTarget() = 0;
1144 
1145   // These two variables are special in that they're set to the same
1146   // value on both the outer window and the current inner window. Make
1147   // sure you keep them in sync!
1148   nsCOMPtr<mozilla::dom::EventTarget> mChromeEventHandler;  // strong
1149   RefPtr<Document> mDoc;
1150   // Cache the URI when mDoc is cleared.
1151   nsCOMPtr<nsIURI> mDocumentURI;  // strong
1152 
1153   nsCOMPtr<mozilla::dom::EventTarget> mParentTarget;                 // strong
1154   RefPtr<mozilla::dom::ContentFrameMessageManager> mMessageManager;  // strong
1155 
1156   nsCOMPtr<mozilla::dom::Element> mFrameElement;
1157 
1158   // These references are used by nsGlobalWindow.
1159   nsCOMPtr<nsIDocShell> mDocShell;
1160   RefPtr<mozilla::dom::BrowsingContext> mBrowsingContext;
1161 
1162   uint32_t mModalStateDepth;
1163 
1164   uint32_t mSuppressEventHandlingDepth;
1165 
1166   // Tracks whether our docshell is active.  If it is, mIsBackground
1167   // is false.  Too bad we have so many different concepts of
1168   // "active".
1169   bool mIsBackground;
1170 
1171   // current desktop mode flag.
1172   bool mDesktopModeViewport;
1173 
1174   bool mIsRootOuterWindow;
1175 
1176   // And these are the references between inner and outer windows.
1177   nsPIDOMWindowInner* MOZ_NON_OWNING_REF mInnerWindow;
1178 
1179   // A unique (as long as our 64-bit counter doesn't roll over) id for
1180   // this window.
1181   uint64_t mWindowID;
1182 
1183   uint32_t mMarkedCCGeneration;
1184 };
1185 
1186 NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowOuter, NS_PIDOMWINDOWOUTER_IID)
1187 
1188 #include "nsPIDOMWindowInlines.h"
1189 
1190 #endif  // nsPIDOMWindow_h__
1191