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