LCOV - code coverage report
Current view: top level - dom/base - nsGlobalWindowInner.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 405 3299 12.3 %
Date: 2018-08-07 16:35:00 Functions: 0 0 -
Legend: Lines: hit not hit

          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             : #include "nsGlobalWindow.h"
       8             : 
       9             : #include <algorithm>
      10             : 
      11             : #include "mozilla/MemoryReporting.h"
      12             : 
      13             : // Local Includes
      14             : #include "Navigator.h"
      15             : #include "nsContentSecurityManager.h"
      16             : #include "nsScreen.h"
      17             : #include "nsHistory.h"
      18             : #include "nsDOMNavigationTiming.h"
      19             : #include "nsIDOMStorageManager.h"
      20             : #include "mozilla/dom/DOMJSProxyHandler.h"
      21             : #include "mozilla/dom/DOMPrefs.h"
      22             : #include "mozilla/dom/EventTarget.h"
      23             : #include "mozilla/dom/LocalStorage.h"
      24             : #include "mozilla/dom/Storage.h"
      25             : #include "mozilla/dom/IdleRequest.h"
      26             : #include "mozilla/dom/Performance.h"
      27             : #include "mozilla/dom/StorageEvent.h"
      28             : #include "mozilla/dom/StorageEventBinding.h"
      29             : #include "mozilla/dom/StorageNotifierService.h"
      30             : #include "mozilla/dom/StorageUtils.h"
      31             : #include "mozilla/dom/Timeout.h"
      32             : #include "mozilla/dom/TimeoutHandler.h"
      33             : #include "mozilla/dom/TimeoutManager.h"
      34             : #include "mozilla/IntegerPrintfMacros.h"
      35             : #if defined(MOZ_WIDGET_ANDROID)
      36             : #include "mozilla/dom/WindowOrientationObserver.h"
      37             : #endif
      38             : #include "nsDOMOfflineResourceList.h"
      39             : #include "nsError.h"
      40             : #include "nsIIdleService.h"
      41             : #include "nsISizeOfEventTarget.h"
      42             : #include "nsDOMJSUtils.h"
      43             : #include "nsArrayUtils.h"
      44             : #include "nsDOMWindowList.h"
      45             : #include "mozilla/dom/WakeLock.h"
      46             : #include "mozilla/dom/power/PowerManagerService.h"
      47             : #include "nsIDocShellTreeOwner.h"
      48             : #include "nsIDocumentLoader.h"
      49             : #include "nsIInterfaceRequestorUtils.h"
      50             : #include "nsIPermissionManager.h"
      51             : #include "nsIScriptContext.h"
      52             : #include "nsIScriptTimeoutHandler.h"
      53             : #include "nsITimeoutHandler.h"
      54             : #include "nsIController.h"
      55             : #include "nsISlowScriptDebug.h"
      56             : #include "nsWindowMemoryReporter.h"
      57             : #include "nsWindowSizes.h"
      58             : #include "WindowNamedPropertiesHandler.h"
      59             : #include "nsFrameSelection.h"
      60             : #include "nsNetUtil.h"
      61             : #include "nsVariant.h"
      62             : #include "nsPrintfCString.h"
      63             : #include "mozilla/intl/LocaleService.h"
      64             : #include "WindowDestroyedEvent.h"
      65             : 
      66             : // Helper Classes
      67             : #include "nsJSUtils.h"
      68             : #include "jsapi.h"              // for JSAutoRequest
      69             : #include "js/Wrapper.h"
      70             : #include "nsCharSeparatedTokenizer.h"
      71             : #include "nsReadableUtils.h"
      72             : #include "nsJSEnvironment.h"
      73             : #include "mozilla/dom/ScriptSettings.h"
      74             : #include "mozilla/Preferences.h"
      75             : #include "mozilla/Likely.h"
      76             : #include "mozilla/Sprintf.h"
      77             : #include "mozilla/Unused.h"
      78             : 
      79             : // Other Classes
      80             : #include "mozilla/dom/BarProps.h"
      81             : #include "nsContentCID.h"
      82             : #include "nsLayoutStatics.h"
      83             : #include "nsCCUncollectableMarker.h"
      84             : #include "mozilla/dom/WorkerCommon.h"
      85             : #include "mozilla/dom/ToJSValue.h"
      86             : #include "nsJSPrincipals.h"
      87             : #include "mozilla/Attributes.h"
      88             : #include "mozilla/Debug.h"
      89             : #include "mozilla/EventListenerManager.h"
      90             : #include "mozilla/EventStates.h"
      91             : #include "mozilla/MouseEvents.h"
      92             : #include "mozilla/ProcessHangMonitor.h"
      93             : #include "mozilla/ThrottledEventQueue.h"
      94             : #include "AudioChannelService.h"
      95             : #include "nsAboutProtocolUtils.h"
      96             : #include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
      97             : #include "PostMessageEvent.h"
      98             : #include "mozilla/dom/DocGroup.h"
      99             : #include "mozilla/dom/TabGroup.h"
     100             : 
     101             : // Interfaces Needed
     102             : #include "nsIFrame.h"
     103             : #include "nsCanvasFrame.h"
     104             : #include "nsIWidget.h"
     105             : #include "nsIWidgetListener.h"
     106             : #include "nsIBaseWindow.h"
     107             : #include "nsIDeviceSensors.h"
     108             : #include "nsIContent.h"
     109             : #include "nsIDocShell.h"
     110             : #include "nsIDocument.h"
     111             : #include "Crypto.h"
     112             : #include "nsIDOMOfflineResourceList.h"
     113             : #include "nsDOMString.h"
     114             : #include "nsIEmbeddingSiteWindow.h"
     115             : #include "nsThreadUtils.h"
     116             : #include "nsILoadContext.h"
     117             : #include "nsIPresShell.h"
     118             : #include "nsIScrollableFrame.h"
     119             : #include "nsView.h"
     120             : #include "nsViewManager.h"
     121             : #include "nsISelectionController.h"
     122             : #include "nsIPrompt.h"
     123             : #include "nsIPromptService.h"
     124             : #include "nsIPromptFactory.h"
     125             : #include "nsIAddonPolicyService.h"
     126             : #include "nsIWritablePropertyBag2.h"
     127             : #include "nsIWebNavigation.h"
     128             : #include "nsIWebBrowserChrome.h"
     129             : #include "nsIWebBrowserFind.h"  // For window.find()
     130             : #include "nsIWindowMediator.h"  // For window.find()
     131             : #include "nsDOMCID.h"
     132             : #include "nsDOMWindowUtils.h"
     133             : #include "nsIWindowWatcher.h"
     134             : #include "nsPIWindowWatcher.h"
     135             : #include "nsIContentViewer.h"
     136             : #include "nsIScriptError.h"
     137             : #include "nsIControllers.h"
     138             : #include "nsIControllerContext.h"
     139             : #include "nsGlobalWindowCommands.h"
     140             : #include "nsQueryObject.h"
     141             : #include "nsContentUtils.h"
     142             : #include "nsCSSProps.h"
     143             : #include "nsIURIFixup.h"
     144             : #ifndef DEBUG
     145             : #include "nsIAppStartup.h"
     146             : #include "nsToolkitCompsCID.h"
     147             : #endif
     148             : #include "nsCDefaultURIFixup.h"
     149             : #include "mozilla/EventDispatcher.h"
     150             : #include "mozilla/EventStateManager.h"
     151             : #include "nsIObserverService.h"
     152             : #include "nsFocusManager.h"
     153             : #include "nsIXULWindow.h"
     154             : #include "nsITimedChannel.h"
     155             : #include "nsServiceManagerUtils.h"
     156             : #ifdef MOZ_XUL
     157             : #include "nsIDOMXULControlElement.h"
     158             : #include "nsMenuPopupFrame.h"
     159             : #endif
     160             : #include "mozilla/dom/CustomEvent.h"
     161             : #include "nsIJARChannel.h"
     162             : #include "nsIScreenManager.h"
     163             : #include "nsIEffectiveTLDService.h"
     164             : #include "nsICSSDeclaration.h"
     165             : 
     166             : #include "xpcprivate.h"
     167             : 
     168             : #ifdef NS_PRINTING
     169             : #include "nsIPrintSettings.h"
     170             : #include "nsIPrintSettingsService.h"
     171             : #include "nsIWebBrowserPrint.h"
     172             : #endif
     173             : 
     174             : #include "nsWindowRoot.h"
     175             : #include "nsNetCID.h"
     176             : #include "nsIArray.h"
     177             : 
     178             : #include "nsBindingManager.h"
     179             : #include "nsXBLService.h"
     180             : 
     181             : #include "nsIDragService.h"
     182             : #include "mozilla/dom/Element.h"
     183             : #include "mozilla/dom/Selection.h"
     184             : #include "nsFrameLoader.h"
     185             : #include "nsISupportsPrimitives.h"
     186             : #include "nsXPCOMCID.h"
     187             : #include "mozilla/Logging.h"
     188             : #include "prenv.h"
     189             : 
     190             : #include "mozilla/dom/IDBFactory.h"
     191             : #include "mozilla/dom/MessageChannel.h"
     192             : #include "mozilla/dom/Promise.h"
     193             : 
     194             : #include "mozilla/dom/Gamepad.h"
     195             : #include "mozilla/dom/GamepadManager.h"
     196             : 
     197             : #include "gfxVR.h"
     198             : #include "mozilla/dom/VRDisplay.h"
     199             : #include "mozilla/dom/VRDisplayEvent.h"
     200             : #include "mozilla/dom/VRDisplayEventBinding.h"
     201             : #include "mozilla/dom/VREventObserver.h"
     202             : 
     203             : #include "nsRefreshDriver.h"
     204             : #include "Layers.h"
     205             : 
     206             : #include "mozilla/BasePrincipal.h"
     207             : #include "mozilla/Services.h"
     208             : #include "mozilla/Telemetry.h"
     209             : #include "mozilla/dom/Location.h"
     210             : #include "nsHTMLDocument.h"
     211             : #include "nsWrapperCacheInlines.h"
     212             : #include "mozilla/DOMEventTargetHelper.h"
     213             : #include "prrng.h"
     214             : #include "nsSandboxFlags.h"
     215             : #include "mozilla/dom/AudioContext.h"
     216             : #include "mozilla/dom/BrowserElementDictionariesBinding.h"
     217             : #include "mozilla/dom/cache/CacheStorage.h"
     218             : #include "mozilla/dom/Console.h"
     219             : #include "mozilla/dom/Fetch.h"
     220             : #include "mozilla/dom/FunctionBinding.h"
     221             : #include "mozilla/dom/HashChangeEvent.h"
     222             : #include "mozilla/dom/IntlUtils.h"
     223             : #include "mozilla/dom/PopStateEvent.h"
     224             : #include "mozilla/dom/PopupBlockedEvent.h"
     225             : #include "mozilla/dom/PrimitiveConversions.h"
     226             : #include "mozilla/dom/WindowBinding.h"
     227             : #include "nsITabChild.h"
     228             : #include "mozilla/dom/MediaQueryList.h"
     229             : #include "mozilla/dom/ScriptSettings.h"
     230             : #include "mozilla/dom/NavigatorBinding.h"
     231             : #include "mozilla/dom/ImageBitmap.h"
     232             : #include "mozilla/dom/ImageBitmapBinding.h"
     233             : #include "mozilla/dom/InstallTriggerBinding.h"
     234             : #include "mozilla/dom/ServiceWorker.h"
     235             : #include "mozilla/dom/ServiceWorkerRegistration.h"
     236             : #include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
     237             : #include "mozilla/dom/U2F.h"
     238             : #include "mozilla/dom/WebIDLGlobalNameHash.h"
     239             : #include "mozilla/dom/Worklet.h"
     240             : #ifdef HAVE_SIDEBAR
     241             : #include "mozilla/dom/ExternalBinding.h"
     242             : #endif
     243             : 
     244             : #ifdef MOZ_WEBSPEECH
     245             : #include "mozilla/dom/SpeechSynthesis.h"
     246             : #endif
     247             : 
     248             : #include "mozilla/dom/ClientManager.h"
     249             : #include "mozilla/dom/ClientSource.h"
     250             : #include "mozilla/dom/ClientState.h"
     251             : 
     252             : // Apple system headers seem to have a check() macro.  <sigh>
     253             : #ifdef check
     254             : class nsIScriptTimeoutHandler;
     255             : #undef check
     256             : #endif // check
     257             : #include "AccessCheck.h"
     258             : 
     259             : #ifdef ANDROID
     260             : #include <android/log.h>
     261             : #endif
     262             : 
     263             : #ifdef XP_WIN
     264             : #include <process.h>
     265             : #define getpid _getpid
     266             : #else
     267             : #include <unistd.h> // for getpid()
     268             : #endif
     269             : 
     270             : using namespace mozilla;
     271             : using namespace mozilla::dom;
     272             : using namespace mozilla::dom::ipc;
     273             : using mozilla::TimeStamp;
     274             : using mozilla::TimeDuration;
     275             : using mozilla::dom::cache::CacheStorage;
     276             : 
     277             : #define FORWARD_TO_OUTER(method, args, err_rval)                        \
     278             :   PR_BEGIN_MACRO                                                        \
     279             :   nsGlobalWindowOuter *outer = GetOuterWindowInternal();                \
     280             :   if (!HasActiveDocument()) {                                           \
     281             :     NS_WARNING(outer ?                                                  \
     282             :                "Inner window does not have active document." :          \
     283             :                "No outer window available!");                           \
     284             :     return err_rval;                                                    \
     285             :   }                                                                     \
     286             :   return outer->method args;                                            \
     287             :   PR_END_MACRO
     288             : 
     289             : #define FORWARD_TO_OUTER_OR_THROW(method, args, errorresult, err_rval)  \
     290             :   PR_BEGIN_MACRO                                                        \
     291             :   nsGlobalWindowOuter *outer = GetOuterWindowInternal();                \
     292             :   if (MOZ_LIKELY(HasActiveDocument())) {                                \
     293             :     return outer->method args;                                          \
     294             :   }                                                                     \
     295             :   if (!outer) {                                                         \
     296             :     NS_WARNING("No outer window available!");                           \
     297             :     errorresult.Throw(NS_ERROR_NOT_INITIALIZED);                        \
     298             :   } else {                                                              \
     299             :     errorresult.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);              \
     300             :   }                                                                     \
     301             :   return err_rval;                                                      \
     302             :   PR_END_MACRO
     303             : 
     304             : #define FORWARD_TO_OUTER_VOID(method, args)                             \
     305             :   PR_BEGIN_MACRO                                                        \
     306             :   nsGlobalWindowOuter *outer = GetOuterWindowInternal();                \
     307             :   if (!HasActiveDocument()) {                                           \
     308             :     NS_WARNING(outer ?                                                  \
     309             :                "Inner window does not have active document." :          \
     310             :                "No outer window available!");                           \
     311             :     return;                                                             \
     312             :   }                                                                     \
     313             :   outer->method args;                                                   \
     314             :   return;                                                               \
     315             :   PR_END_MACRO
     316             : 
     317             : #define DOM_TOUCH_LISTENER_ADDED "dom-touch-listener-added"
     318             : #define MEMORY_PRESSURE_OBSERVER_TOPIC "memory-pressure"
     319             : 
     320             : // Amount of time allowed between alert/prompt/confirm before enabling
     321             : // the stop dialog checkbox.
     322             : #define DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT 3 // 3 sec
     323             : 
     324             : // Maximum number of successive dialogs before we prompt users to disable
     325             : // dialogs for this window.
     326             : #define MAX_SUCCESSIVE_DIALOG_COUNT 5
     327             : 
     328             : // Idle fuzz time upper limit
     329             : #define MAX_IDLE_FUZZ_TIME_MS 90000
     330             : 
     331             : // Min idle notification time in seconds.
     332             : #define MIN_IDLE_NOTIFICATION_TIME_S 1
     333             : 
     334             : static LazyLogModule gDOMLeakPRLogInner("DOMLeakInner");
     335             : 
     336             : static bool                 gIdleObserversAPIFuzzTimeDisabled = false;
     337             : static FILE                *gDumpFile                         = nullptr;
     338             : 
     339             : nsGlobalWindowInner::InnerWindowByIdTable *nsGlobalWindowInner::sInnerWindowsById = nullptr;
     340             : 
     341             : bool nsGlobalWindowInner::sDragServiceDisabled = false;
     342             : bool nsGlobalWindowInner::sMouseDown = false;
     343             : 
     344             : /**
     345             :  * An indirect observer object that means we don't have to implement nsIObserver
     346             :  * on nsGlobalWindow, where any script could see it.
     347             :  */
     348             : class nsGlobalWindowObserver final : public nsIObserver
     349             :                                    , public nsIInterfaceRequestor
     350             :                                    , public StorageNotificationObserver
     351             : {
     352             : public:
     353           0 :   explicit nsGlobalWindowObserver(nsGlobalWindowInner* aWindow) : mWindow(aWindow) {}
     354             :   NS_DECL_ISUPPORTS
     355           0 :   NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) override
     356             :   {
     357           0 :     if (!mWindow)
     358             :       return NS_OK;
     359           0 :     return mWindow->Observe(aSubject, aTopic, aData);
     360             :   }
     361           0 :   void Forget() { mWindow = nullptr; }
     362           0 :   NS_IMETHOD GetInterface(const nsIID& aIID, void** aResult) override
     363             :   {
     364           0 :     if (mWindow && aIID.Equals(NS_GET_IID(nsIDOMWindow)) && mWindow) {
     365           0 :       return mWindow->QueryInterface(aIID, aResult);
     366             :     }
     367             :     return NS_NOINTERFACE;
     368             :   }
     369             : 
     370             :   void
     371           0 :   ObserveStorageNotification(StorageEvent* aEvent,
     372             :                              const char16_t* aStorageType,
     373             :                              bool aPrivateBrowsing) override
     374             :   {
     375           0 :     if (mWindow) {
     376           0 :       mWindow->ObserveStorageNotification(aEvent, aStorageType,
     377           0 :                                           aPrivateBrowsing);
     378             :     }
     379           0 :   }
     380             : 
     381             :   nsIPrincipal*
     382           0 :   GetPrincipal() const override
     383             :   {
     384           0 :     return mWindow ? mWindow->GetPrincipal() : nullptr;
     385             :   }
     386             : 
     387             :   bool
     388           0 :   IsPrivateBrowsing() const override
     389             :   {
     390           0 :     return mWindow ? mWindow->IsPrivateBrowsing() : false;
     391             :   }
     392             : 
     393             :   nsIEventTarget*
     394           0 :   GetEventTarget() const override
     395             :   {
     396           0 :     return mWindow ? mWindow->EventTargetFor(TaskCategory::Other) : nullptr;
     397             :   }
     398             : 
     399             : private:
     400             :   ~nsGlobalWindowObserver() = default;
     401             : 
     402             :   // This reference is non-owning and safe because it's cleared by
     403             :   // nsGlobalWindowInner::FreeInnerObjects().
     404             :   nsGlobalWindowInner* MOZ_NON_OWNING_REF mWindow;
     405             : };
     406             : 
     407           0 : NS_IMPL_ISUPPORTS(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor)
     408             : 
     409             : class IdleRequestExecutor;
     410             : 
     411             : class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler
     412             : {
     413             : public:
     414           0 :   explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor)
     415           0 :     : mExecutor(aExecutor)
     416             :   {
     417           0 :   }
     418             : 
     419             :   NS_DECL_ISUPPORTS_INHERITED
     420           0 :   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestExecutorTimeoutHandler,
     421             :                                            TimeoutHandler)
     422             : 
     423             :   nsresult Call() override;
     424             : 
     425             : private:
     426           0 :   ~IdleRequestExecutorTimeoutHandler() override {}
     427             :   RefPtr<IdleRequestExecutor> mExecutor;
     428             : };
     429             : 
     430           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler, mExecutor)
     431             : 
     432           0 : NS_IMPL_ADDREF_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler)
     433           0 : NS_IMPL_RELEASE_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler)
     434             : 
     435           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler)
     436           0 : NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
     437             : 
     438             : 
     439             : class IdleRequestExecutor final : public nsIRunnable
     440             :                                 , public nsICancelableRunnable
     441             :                                 , public nsINamed
     442             :                                 , public nsIIdleRunnable
     443             : {
     444             : public:
     445           0 :   explicit IdleRequestExecutor(nsGlobalWindowInner* aWindow)
     446           0 :     : mDispatched(false)
     447             :     , mDeadline(TimeStamp::Now())
     448           0 :     , mWindow(aWindow)
     449             :   {
     450           0 :     MOZ_DIAGNOSTIC_ASSERT(mWindow);
     451             : 
     452           0 :     mIdlePeriodLimit = { mDeadline, mWindow->LastIdleRequestHandle() };
     453           0 :     mDelayedExecutorDispatcher = new IdleRequestExecutorTimeoutHandler(this);
     454           0 :   }
     455             : 
     456             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     457           0 :   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable)
     458             : 
     459             :   NS_DECL_NSIRUNNABLE
     460             :   NS_DECL_NSINAMED
     461             :   nsresult Cancel() override;
     462             :   void SetDeadline(TimeStamp aDeadline) override;
     463             : 
     464           0 :   bool IsCancelled() const { return !mWindow || mWindow->IsDying(); }
     465             :   // Checks if aRequest shouldn't execute in the current idle period
     466             :   // since it has been queued from a chained call to
     467             :   // requestIdleCallback from within a running idle callback.
     468           0 :   bool IneligibleForCurrentIdlePeriod(IdleRequest* aRequest) const
     469             :   {
     470           0 :     return aRequest->Handle() >= mIdlePeriodLimit.mLastRequestIdInIdlePeriod &&
     471           0 :            TimeStamp::Now() <= mIdlePeriodLimit.mEndOfIdlePeriod;
     472             :   }
     473             : 
     474             :   void MaybeUpdateIdlePeriodLimit();
     475             : 
     476             :   // Maybe dispatch the IdleRequestExecutor. MabyeDispatch will
     477             :   // schedule a delayed dispatch if the associated window is in the
     478             :   // background or if given a time to wait until dispatching.
     479             :   void MaybeDispatch(TimeStamp aDelayUntil = TimeStamp());
     480             :   void ScheduleDispatch();
     481             : private:
     482           0 :   struct IdlePeriodLimit
     483             :   {
     484             :     TimeStamp mEndOfIdlePeriod;
     485             :     uint32_t mLastRequestIdInIdlePeriod;
     486             :   };
     487             : 
     488             :   void DelayedDispatch(uint32_t aDelay);
     489             : 
     490           0 :   ~IdleRequestExecutor() override {}
     491             : 
     492             :   bool mDispatched;
     493             :   TimeStamp mDeadline;
     494             :   IdlePeriodLimit mIdlePeriodLimit;
     495             :   RefPtr<nsGlobalWindowInner> mWindow;
     496             :   // The timeout handler responsible for dispatching this executor in
     497             :   // the case of immediate dispatch to the idle queue isn't
     498             :   // desirable. This is used if we've dispatched all idle callbacks
     499             :   // that are allowed to run in the current idle period, or if the
     500             :   // associated window is currently in the background.
     501             :   nsCOMPtr<nsITimeoutHandler> mDelayedExecutorDispatcher;
     502             :   // If not Nothing() then this value is the handle to the currently
     503             :   // scheduled delayed executor dispatcher. This is needed to be able
     504             :   // to cancel the timeout handler in case of the executor being
     505             :   // cancelled.
     506             :   Maybe<int32_t> mDelayedExecutorHandle;
     507             : };
     508             : 
     509             : NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequestExecutor)
     510             : 
     511           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutor)
     512           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutor)
     513             : 
     514           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequestExecutor)
     515           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
     516           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDelayedExecutorDispatcher)
     517           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     518             : 
     519           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequestExecutor)
     520           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
     521           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDelayedExecutorDispatcher)
     522           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     523             : 
     524           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor)
     525           0 :   NS_INTERFACE_MAP_ENTRY(nsIRunnable)
     526           0 :   NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)
     527           0 :   NS_INTERFACE_MAP_ENTRY(nsINamed)
     528           0 :   NS_INTERFACE_MAP_ENTRY(nsIIdleRunnable)
     529           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable)
     530           0 : NS_INTERFACE_MAP_END
     531             : 
     532             : NS_IMETHODIMP
     533           0 : IdleRequestExecutor::GetName(nsACString& aName)
     534             : {
     535           0 :     aName.AssignASCII("IdleRequestExecutor");
     536           0 :     return NS_OK;
     537             : }
     538             : 
     539             : NS_IMETHODIMP
     540           0 : IdleRequestExecutor::Run()
     541             : {
     542           0 :   MOZ_ASSERT(NS_IsMainThread());
     543             : 
     544           0 :   mDispatched = false;
     545           0 :   if (mWindow) {
     546           0 :     return mWindow->ExecuteIdleRequest(mDeadline);
     547             :   }
     548             : 
     549             :   return NS_OK;
     550             : }
     551             : 
     552             : nsresult
     553           0 : IdleRequestExecutor::Cancel()
     554             : {
     555           0 :   MOZ_ASSERT(NS_IsMainThread());
     556             : 
     557           0 :   if (mDelayedExecutorHandle && mWindow) {
     558           0 :     mWindow->TimeoutManager().ClearTimeout(
     559             :       mDelayedExecutorHandle.value(),
     560           0 :       Timeout::Reason::eIdleCallbackTimeout);
     561             :   }
     562             : 
     563           0 :   mWindow = nullptr;
     564           0 :   return NS_OK;
     565             : }
     566             : 
     567             : void
     568           0 : IdleRequestExecutor::SetDeadline(TimeStamp aDeadline)
     569             : {
     570           0 :   MOZ_ASSERT(NS_IsMainThread());
     571             : 
     572           0 :   if (!mWindow) {
     573             :     return;
     574             :   }
     575             : 
     576           0 :   mDeadline = aDeadline;
     577             : }
     578             : 
     579             : void
     580           0 : IdleRequestExecutor::MaybeUpdateIdlePeriodLimit()
     581             : {
     582           0 :   if (TimeStamp::Now() > mIdlePeriodLimit.mEndOfIdlePeriod) {
     583           0 :     mIdlePeriodLimit = { mDeadline, mWindow->LastIdleRequestHandle() };
     584             :   }
     585           0 : }
     586             : 
     587             : void
     588           0 : IdleRequestExecutor::MaybeDispatch(TimeStamp aDelayUntil)
     589             : {
     590             :   // If we've already dispatched the executor we don't want to do it
     591             :   // again. Also, if we've called IdleRequestExecutor::Cancel mWindow
     592             :   // will be null, which indicates that we shouldn't dispatch this
     593             :   // executor either.
     594           0 :   if (mDispatched || IsCancelled()) {
     595           0 :     return;
     596             :   }
     597             : 
     598           0 :   mDispatched = true;
     599             : 
     600           0 :   nsPIDOMWindowOuter* outer = mWindow->GetOuterWindow();
     601           0 :   if (outer && outer->AsOuter()->IsBackground()) {
     602             :     // Set a timeout handler with a timeout of 0 ms to throttle idle
     603             :     // callback requests coming from a backround window using
     604             :     // background timeout throttling.
     605           0 :     DelayedDispatch(0);
     606           0 :     return;
     607             :   }
     608             : 
     609           0 :   TimeStamp now = TimeStamp::Now();
     610           0 :   if (!aDelayUntil || aDelayUntil < now) {
     611           0 :     ScheduleDispatch();
     612           0 :     return;
     613             :   }
     614             : 
     615           0 :   TimeDuration delay = aDelayUntil - now;
     616           0 :   DelayedDispatch(static_cast<uint32_t>(delay.ToMilliseconds()));
     617             : }
     618             : 
     619             : void
     620           0 : IdleRequestExecutor::ScheduleDispatch()
     621             : {
     622           0 :   MOZ_ASSERT(mWindow);
     623           0 :   mDelayedExecutorHandle = Nothing();
     624           0 :   RefPtr<IdleRequestExecutor> request = this;
     625           0 :   NS_IdleDispatchToCurrentThread(request.forget());
     626           0 : }
     627             : 
     628             : void
     629           0 : IdleRequestExecutor::DelayedDispatch(uint32_t aDelay)
     630             : {
     631           0 :   MOZ_ASSERT(mWindow);
     632           0 :   MOZ_ASSERT(mDelayedExecutorHandle.isNothing());
     633             :   int32_t handle;
     634           0 :   mWindow->TimeoutManager().SetTimeout(
     635           0 :     mDelayedExecutorDispatcher, aDelay, false, Timeout::Reason::eIdleCallbackTimeout, &handle);
     636           0 :   mDelayedExecutorHandle = Some(handle);
     637           0 : }
     638             : 
     639             : nsresult
     640           0 : IdleRequestExecutorTimeoutHandler::Call()
     641             : {
     642           0 :   if (!mExecutor->IsCancelled()) {
     643           0 :     mExecutor->ScheduleDispatch();
     644             :   }
     645           0 :   return NS_OK;
     646             : }
     647             : 
     648             : void
     649           0 : nsGlobalWindowInner::ScheduleIdleRequestDispatch()
     650             : {
     651           0 :   AssertIsOnMainThread();
     652             : 
     653           0 :   if (!mIdleRequestExecutor) {
     654           0 :     mIdleRequestExecutor = new IdleRequestExecutor(this);
     655             :   }
     656             : 
     657           0 :   mIdleRequestExecutor->MaybeDispatch();
     658           0 : }
     659             : 
     660             : void
     661           0 : nsGlobalWindowInner::SuspendIdleRequests()
     662             : {
     663           0 :   if (mIdleRequestExecutor) {
     664           0 :     mIdleRequestExecutor->Cancel();
     665           0 :     mIdleRequestExecutor = nullptr;
     666             :   }
     667           0 : }
     668             : 
     669             : void
     670           0 : nsGlobalWindowInner::ResumeIdleRequests()
     671             : {
     672           0 :   MOZ_ASSERT(!mIdleRequestExecutor);
     673             : 
     674           0 :   ScheduleIdleRequestDispatch();
     675           0 : }
     676             : 
     677             : void
     678           0 : nsGlobalWindowInner::RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest)
     679             : {
     680           0 :   AssertIsOnMainThread();
     681             : 
     682           0 :   if (aRequest->HasTimeout()) {
     683           0 :     mTimeoutManager->ClearTimeout(aRequest->GetTimeoutHandle(),
     684           0 :                                   Timeout::Reason::eIdleCallbackTimeout);
     685             :   }
     686             : 
     687           0 :   aRequest->removeFrom(mIdleRequestCallbacks);
     688           0 : }
     689             : 
     690             : nsresult
     691           0 : nsGlobalWindowInner::RunIdleRequest(IdleRequest* aRequest,
     692             :                                DOMHighResTimeStamp aDeadline,
     693             :                                bool aDidTimeout)
     694             : {
     695           0 :   AssertIsOnMainThread();
     696           0 :   RefPtr<IdleRequest> request(aRequest);
     697           0 :   RemoveIdleCallback(request);
     698           0 :   return request->IdleRun(this, aDeadline, aDidTimeout);
     699             : }
     700             : 
     701             : nsresult
     702           0 : nsGlobalWindowInner::ExecuteIdleRequest(TimeStamp aDeadline)
     703             : {
     704           0 :   AssertIsOnMainThread();
     705           0 :   RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
     706             : 
     707           0 :   if (!request) {
     708             :     // There are no more idle requests, so stop scheduling idle
     709             :     // request callbacks.
     710             :     return NS_OK;
     711             :   }
     712             : 
     713             :   // If the request that we're trying to execute has been queued
     714             :   // during the current idle period, then dispatch it again at the end
     715             :   // of the idle period.
     716           0 :   if (mIdleRequestExecutor->IneligibleForCurrentIdlePeriod(request)) {
     717           0 :     mIdleRequestExecutor->MaybeDispatch(aDeadline);
     718           0 :     return NS_OK;
     719             :   }
     720             : 
     721           0 :   DOMHighResTimeStamp deadline = 0.0;
     722             : 
     723           0 :   if (Performance* perf = GetPerformance()) {
     724           0 :     deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline);
     725             :   }
     726             : 
     727           0 :   mIdleRequestExecutor->MaybeUpdateIdlePeriodLimit();
     728           0 :   nsresult result = RunIdleRequest(request, deadline, false);
     729             : 
     730             :   // Running the idle callback could've suspended the window, in which
     731             :   // case mIdleRequestExecutor will be null.
     732           0 :   if (mIdleRequestExecutor) {
     733           0 :     mIdleRequestExecutor->MaybeDispatch();
     734             :   }
     735             :   return result;
     736             : }
     737             : 
     738             : class IdleRequestTimeoutHandler final : public TimeoutHandler
     739             : {
     740             : public:
     741           0 :   IdleRequestTimeoutHandler(JSContext* aCx,
     742             :                             IdleRequest* aIdleRequest,
     743             :                             nsPIDOMWindowInner* aWindow)
     744           0 :     : TimeoutHandler(aCx)
     745             :     , mIdleRequest(aIdleRequest)
     746           0 :     , mWindow(aWindow)
     747             :   {
     748           0 :   }
     749             : 
     750             :   NS_DECL_ISUPPORTS_INHERITED
     751           0 :   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestTimeoutHandler,
     752             :                                            TimeoutHandler)
     753             : 
     754           0 :   nsresult Call() override
     755             :   {
     756           0 :     return nsGlobalWindowInner::Cast(mWindow)->RunIdleRequest(mIdleRequest, 0.0, true);
     757             :   }
     758             : 
     759             : private:
     760           0 :   ~IdleRequestTimeoutHandler() override {}
     761             : 
     762             :   RefPtr<IdleRequest> mIdleRequest;
     763             :   nsCOMPtr<nsPIDOMWindowInner> mWindow;
     764             : };
     765             : 
     766           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestTimeoutHandler,
     767             :                                    TimeoutHandler,
     768             :                                    mIdleRequest,
     769             :                                    mWindow)
     770             : 
     771           0 : NS_IMPL_ADDREF_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler)
     772           0 : NS_IMPL_RELEASE_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler)
     773             : 
     774           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestTimeoutHandler)
     775           0 : NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
     776             : 
     777             : uint32_t
     778           0 : nsGlobalWindowInner::RequestIdleCallback(JSContext* aCx,
     779             :                                          IdleRequestCallback& aCallback,
     780             :                                          const IdleRequestOptions& aOptions,
     781             :                                          ErrorResult& aError)
     782             : {
     783           0 :   AssertIsOnMainThread();
     784             : 
     785           0 :   if (IsDying()) {
     786             :    return 0;
     787             :   }
     788             : 
     789           0 :   uint32_t handle = mIdleRequestCallbackCounter++;
     790             : 
     791             :   RefPtr<IdleRequest> request =
     792           0 :     new IdleRequest(&aCallback, handle);
     793             : 
     794           0 :   if (aOptions.mTimeout.WasPassed()) {
     795             :     int32_t timeoutHandle;
     796           0 :     nsCOMPtr<nsITimeoutHandler> handler(new IdleRequestTimeoutHandler(aCx, request, this));
     797             : 
     798           0 :     nsresult rv = mTimeoutManager->SetTimeout(
     799           0 :         handler, aOptions.mTimeout.Value(), false,
     800           0 :         Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle);
     801             : 
     802           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     803           0 :       return 0;
     804             :     }
     805             : 
     806           0 :     request->SetTimeoutHandle(timeoutHandle);
     807             :   }
     808             : 
     809           0 :   mIdleRequestCallbacks.insertBack(request);
     810             : 
     811           0 :   if (!IsSuspended()) {
     812           0 :     ScheduleIdleRequestDispatch();
     813             :   }
     814             : 
     815             :   return handle;
     816             : }
     817             : 
     818             : void
     819           0 : nsGlobalWindowInner::CancelIdleCallback(uint32_t aHandle)
     820             : {
     821           0 :   for (IdleRequest* r : mIdleRequestCallbacks) {
     822           0 :     if (r->Handle() == aHandle) {
     823           0 :       RemoveIdleCallback(r);
     824           0 :       break;
     825             :     }
     826             :   }
     827           0 : }
     828             : 
     829             : void
     830           0 : nsGlobalWindowInner::DisableIdleCallbackRequests()
     831             : {
     832           0 :   if (mIdleRequestExecutor) {
     833           0 :     mIdleRequestExecutor->Cancel();
     834           0 :     mIdleRequestExecutor = nullptr;
     835             :   }
     836             : 
     837           0 :   while (!mIdleRequestCallbacks.isEmpty()) {
     838           0 :     RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
     839           0 :     RemoveIdleCallback(request);
     840             :   }
     841           0 : }
     842             : 
     843             : bool
     844           0 : nsGlobalWindowInner::IsBackgroundInternal() const
     845             : {
     846           0 :   return !mOuterWindow || mOuterWindow->IsBackground();
     847             : }
     848             : 
     849             : class PromiseDocumentFlushedResolver final {
     850             : public:
     851           0 :   PromiseDocumentFlushedResolver(Promise* aPromise,
     852             :                                  PromiseDocumentFlushedCallback& aCallback)
     853           0 :   : mPromise(aPromise)
     854           0 :   , mCallback(&aCallback)
     855             :   {
     856           0 :   }
     857             : 
     858           0 :   virtual ~PromiseDocumentFlushedResolver() = default;
     859             : 
     860           0 :   void Call()
     861             :   {
     862           0 :     ErrorResult error;
     863           0 :     JS::Rooted<JS::Value> returnVal(RootingCx());
     864           0 :     mCallback->Call(&returnVal, error);
     865             : 
     866           0 :     if (error.Failed()) {
     867           0 :       mPromise->MaybeReject(error);
     868             :     } else {
     869           0 :       mPromise->MaybeResolve(returnVal);
     870             :     }
     871           0 :   }
     872             : 
     873           0 :   void Cancel()
     874             :   {
     875           0 :     mPromise->MaybeReject(NS_ERROR_ABORT);
     876           0 :   }
     877             : 
     878             :   RefPtr<Promise> mPromise;
     879             :   RefPtr<PromiseDocumentFlushedCallback> mCallback;
     880             : };
     881             : 
     882             : //*****************************************************************************
     883             : //***    nsGlobalWindowInner: Object Management
     884             : //*****************************************************************************
     885             : 
     886           0 : nsGlobalWindowInner::nsGlobalWindowInner(nsGlobalWindowOuter *aOuterWindow)
     887             :   : nsPIDOMWindowInner(aOuterWindow->AsOuter()),
     888             :     mIdleFuzzFactor(0),
     889             :     mIdleCallbackIndex(-1),
     890             :     mCurrentlyIdle(false),
     891             :     mAddActiveEventFuzzTime(true),
     892             :     mWasOffline(false),
     893             :     mHasHadSlowScript(false),
     894             :     mNotifyIdleObserversIdleOnThaw(false),
     895             :     mNotifyIdleObserversActiveOnThaw(false),
     896             :     mIsChrome(false),
     897             :     mCleanMessageManager(false),
     898             :     mNeedsFocus(true),
     899             :     mHasFocus(false),
     900             :     mShowFocusRingForContent(false),
     901             :     mFocusByKeyOccurred(false),
     902             :     mHasGamepad(false),
     903             :     mHasVREvents(false),
     904             :     mHasVRDisplayActivateEvents(false),
     905             :     mHasSeenGamepadInput(false),
     906             :     mSuspendDepth(0),
     907             :     mFreezeDepth(0),
     908             :     mFocusMethod(0),
     909             :     mSerial(0),
     910             :     mIdleRequestCallbackCounter(1),
     911             :     mIdleRequestExecutor(nullptr),
     912             :     mDialogAbuseCount(0),
     913             :     mAreDialogsEnabled(true),
     914             :     mObservingDidRefresh(false),
     915             :     mIteratingDocumentFlushedResolvers(false),
     916             :     mCanSkipCCGeneration(0),
     917           0 :     mBeforeUnloadListenerCount(0)
     918             : {
     919           0 :   AssertIsOnMainThread();
     920             : 
     921           0 :   nsLayoutStatics::AddRef();
     922             : 
     923             :   // Initialize the PRCList (this).
     924           0 :   PR_INIT_CLIST(this);
     925             : 
     926           0 :   if (aOuterWindow) {
     927             :     // |this| is an inner window, add this inner window to the outer
     928             :     // window list of inners.
     929           0 :     PR_INSERT_AFTER(this, aOuterWindow);
     930             : 
     931             :     mTimeoutManager =
     932           0 :       MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindowInner::Cast(AsInner()));
     933             : 
     934           0 :     mObserver = new nsGlobalWindowObserver(this);
     935           0 :     if (mObserver) {
     936           0 :       nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     937           0 :       if (os) {
     938             :         // Watch for online/offline status changes so we can fire events. Use
     939             :         // a strong reference.
     940           0 :         os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
     941           0 :                         false);
     942             : 
     943           0 :         os->AddObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC, false);
     944             :       }
     945             : 
     946           0 :       Preferences::AddStrongObserver(mObserver, "intl.accept_languages");
     947             : 
     948             :       // Watch for storage notifications so we can fire storage events.
     949             :       RefPtr<StorageNotifierService> sns =
     950           0 :         StorageNotifierService::GetOrCreate();
     951           0 :       if (sns) {
     952           0 :         sns->Register(mObserver);
     953             :       }
     954             :     }
     955             :   } else {
     956             :     // |this| is an outer window. Outer windows start out frozen and
     957             :     // remain frozen until they get an inner window.
     958           0 :     MOZ_ASSERT(IsFrozen());
     959             :   }
     960             : 
     961           0 :   if (XRE_IsContentProcess()) {
     962           0 :     nsCOMPtr<nsIDocShell> docShell = GetDocShell();
     963           0 :     if (docShell) {
     964           0 :       mTabChild = docShell->GetTabChild();
     965             :     }
     966             :   }
     967             : 
     968             :   // We could have failed the first time through trying
     969             :   // to create the entropy collector, so we should
     970             :   // try to get one until we succeed.
     971             : 
     972           0 :   mSerial = nsContentUtils::InnerOrOuterWindowCreated();
     973             : 
     974             :   static bool sFirstTime = true;
     975           0 :   if (sFirstTime) {
     976           0 :     sFirstTime = false;
     977           0 :     TimeoutManager::Initialize();
     978             :     Preferences::AddBoolVarCache(&gIdleObserversAPIFuzzTimeDisabled,
     979             :                                  "dom.idle-observers-api.fuzz_time.disabled",
     980           0 :                                  false);
     981             :   }
     982             : 
     983           0 :   if (gDumpFile == nullptr) {
     984           0 :     nsAutoCString fname;
     985           0 :     Preferences::GetCString("browser.dom.window.dump.file", fname);
     986           0 :     if (!fname.IsEmpty()) {
     987             :       // If this fails to open, Dump() knows to just go to stdout on null.
     988           0 :       gDumpFile = fopen(fname.get(), "wb+");
     989             :     } else {
     990           0 :       gDumpFile = stdout;
     991             :     }
     992             :   }
     993             : 
     994             : #ifdef DEBUG
     995           0 :   if (!PR_GetEnv("MOZ_QUIET")) {
     996           0 :     printf_stderr("++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n",
     997             :                   nsContentUtils::GetCurrentInnerOrOuterWindowCount(),
     998           0 :                   static_cast<void*>(ToCanonicalSupports(this)),
     999             :                   getpid(),
    1000             :                   mSerial,
    1001           0 :                   static_cast<void*>(ToCanonicalSupports(aOuterWindow)));
    1002             :   }
    1003             : #endif
    1004             : 
    1005           0 :   MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
    1006             :           ("DOMWINDOW %p created outer=%p", this, aOuterWindow));
    1007             : 
    1008             :   // Add ourselves to the inner windows list.
    1009           0 :   MOZ_ASSERT(sInnerWindowsById, "Inner Windows hash table must be created!");
    1010           0 :   MOZ_ASSERT(!sInnerWindowsById->Get(mWindowID),
    1011             :              "This window shouldn't be in the hash table yet!");
    1012             :   // We seem to see crashes in release builds because of null |sInnerWindowsById|.
    1013           0 :   if (sInnerWindowsById) {
    1014           0 :     sInnerWindowsById->Put(mWindowID, this);
    1015             :   }
    1016           0 : }
    1017             : 
    1018             : #ifdef DEBUG
    1019             : 
    1020             : /* static */
    1021             : void
    1022           0 : nsGlobalWindowInner::AssertIsOnMainThread()
    1023             : {
    1024           0 :   MOZ_ASSERT(NS_IsMainThread());
    1025           0 : }
    1026             : 
    1027             : #endif // DEBUG
    1028             : 
    1029             : /* static */
    1030             : void
    1031           0 : nsGlobalWindowInner::Init()
    1032             : {
    1033           0 :   AssertIsOnMainThread();
    1034             : 
    1035           0 :   NS_ASSERTION(gDOMLeakPRLogInner, "gDOMLeakPRLogInner should have been initialized!");
    1036             : 
    1037           0 :   sInnerWindowsById = new InnerWindowByIdTable();
    1038           0 : }
    1039             : 
    1040           0 : nsGlobalWindowInner::~nsGlobalWindowInner()
    1041             : {
    1042           0 :   AssertIsOnMainThread();
    1043             : 
    1044           0 :   if (IsChromeWindow()) {
    1045           0 :     MOZ_ASSERT(mCleanMessageManager,
    1046             :               "chrome windows may always disconnect the msg manager");
    1047             : 
    1048           0 :     DisconnectAndClearGroupMessageManagers();
    1049             : 
    1050           0 :     if (mChromeFields.mMessageManager) {
    1051             :       static_cast<nsFrameMessageManager *>(
    1052           0 :         mChromeFields.mMessageManager.get())->Disconnect();
    1053             :     }
    1054             : 
    1055           0 :     mCleanMessageManager = false;
    1056             :   }
    1057             : 
    1058             :   // In most cases this should already have been called, but call it again
    1059             :   // here to catch any corner cases.
    1060           0 :   FreeInnerObjects();
    1061             : 
    1062           0 :   if (sInnerWindowsById) {
    1063           0 :     MOZ_ASSERT(sInnerWindowsById->Get(mWindowID),
    1064             :                 "This window should be in the hash table");
    1065           0 :     sInnerWindowsById->Remove(mWindowID);
    1066             :   }
    1067             : 
    1068           0 :   nsContentUtils::InnerOrOuterWindowDestroyed();
    1069             : 
    1070             : #ifdef DEBUG
    1071           0 :   if (!PR_GetEnv("MOZ_QUIET")) {
    1072           0 :     nsAutoCString url;
    1073           0 :     if (mLastOpenedURI) {
    1074           0 :       url = mLastOpenedURI->GetSpecOrDefault();
    1075             : 
    1076             :       // Data URLs can be very long, so truncate to avoid flooding the log.
    1077           0 :       const uint32_t maxURLLength = 1000;
    1078           0 :       if (url.Length() > maxURLLength) {
    1079           0 :         url.Truncate(maxURLLength);
    1080             :       }
    1081             :     }
    1082             : 
    1083           0 :     nsGlobalWindowOuter* outer = nsGlobalWindowOuter::Cast(mOuterWindow);
    1084           0 :     printf_stderr("--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = %s]\n",
    1085             :                   nsContentUtils::GetCurrentInnerOrOuterWindowCount(),
    1086           0 :                   static_cast<void*>(ToCanonicalSupports(this)),
    1087             :                   getpid(),
    1088             :                   mSerial,
    1089           0 :                   static_cast<void*>(ToCanonicalSupports(outer)),
    1090           0 :                   url.get());
    1091             :   }
    1092             : #endif
    1093             : 
    1094           0 :   MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug, ("DOMWINDOW %p destroyed", this));
    1095             : 
    1096           0 :   Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
    1097           0 :                         mMutationBits ? 1 : 0);
    1098             : 
    1099             :   // An inner window is destroyed, pull it out of the outer window's
    1100             :   // list if inner windows.
    1101             : 
    1102           0 :   PR_REMOVE_LINK(this);
    1103             : 
    1104             :   // If our outer window's inner window is this window, null out the
    1105             :   // outer window's reference to this window that's being deleted.
    1106           0 :   nsGlobalWindowOuter *outer = GetOuterWindowInternal();
    1107           0 :   if (outer) {
    1108           0 :     outer->MaybeClearInnerWindow(this);
    1109             :   }
    1110             : 
    1111             :   // We don't have to leave the tab group if we are an inner window.
    1112             : 
    1113           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
    1114           0 :   if (ac)
    1115           0 :     ac->RemoveWindowAsListener(this);
    1116             : 
    1117           0 :   nsLayoutStatics::Release();
    1118           0 : }
    1119             : 
    1120             : // static
    1121             : void
    1122           0 : nsGlobalWindowInner::ShutDown()
    1123             : {
    1124           0 :   AssertIsOnMainThread();
    1125             : 
    1126           0 :   if (gDumpFile && gDumpFile != stdout) {
    1127           0 :     fclose(gDumpFile);
    1128             :   }
    1129           0 :   gDumpFile = nullptr;
    1130             : 
    1131           0 :   delete sInnerWindowsById;
    1132           0 :   sInnerWindowsById = nullptr;
    1133           0 : }
    1134             : 
    1135             : // static
    1136             : void
    1137           0 : nsGlobalWindowInner::CleanupCachedXBLHandlers()
    1138             : {
    1139           0 :   if (mCachedXBLPrototypeHandlers &&
    1140           0 :       mCachedXBLPrototypeHandlers->Count() > 0) {
    1141           0 :     mCachedXBLPrototypeHandlers->Clear();
    1142             :   }
    1143           0 : }
    1144             : 
    1145             : void
    1146           0 : nsGlobalWindowInner::FreeInnerObjects()
    1147             : {
    1148           0 :   if (IsDying()) {
    1149             :     return;
    1150             :   }
    1151           0 :   StartDying();
    1152             : 
    1153             :   // Make sure that this is called before we null out the document and
    1154             :   // other members that the window destroyed observers could
    1155             :   // re-create.
    1156           0 :   NotifyDOMWindowDestroyed(this);
    1157           0 :   if (auto* reporter = nsWindowMemoryReporter::Get()) {
    1158           0 :     reporter->ObserveDOMWindowDetached(this);
    1159             :   }
    1160             : 
    1161             :   // Kill all of the workers for this window.
    1162           0 :   CancelWorkersForWindow(this);
    1163             : 
    1164           0 :   if (mTimeoutManager) {
    1165           0 :     mTimeoutManager->ClearAllTimeouts();
    1166             :   }
    1167             : 
    1168           0 :   if (mIdleTimer) {
    1169           0 :     mIdleTimer->Cancel();
    1170           0 :     mIdleTimer = nullptr;
    1171             :   }
    1172             : 
    1173           0 :   mIdleObservers.Clear();
    1174             : 
    1175           0 :   DisableIdleCallbackRequests();
    1176             : 
    1177           0 :   mChromeEventHandler = nullptr;
    1178             : 
    1179           0 :   if (mListenerManager) {
    1180           0 :     mListenerManager->Disconnect();
    1181           0 :     mListenerManager = nullptr;
    1182             :   }
    1183             : 
    1184           0 :   mHistory = nullptr;
    1185             : 
    1186          14 :   if (mNavigator) {
    1187           0 :     mNavigator->OnNavigation();
    1188           0 :     mNavigator->Invalidate();
    1189           0 :     mNavigator = nullptr;
    1190             :   }
    1191             : 
    1192           7 :   mScreen = nullptr;
    1193             : 
    1194             : #if defined(MOZ_WIDGET_ANDROID)
    1195             :   mOrientationChangeObserver = nullptr;
    1196             : #endif
    1197             : 
    1198          14 :   if (mDoc) {
    1199             :     // Remember the document's principal and URI.
    1200           7 :     mDocumentPrincipal = mDoc->NodePrincipal();
    1201           0 :     mDocumentURI = mDoc->GetDocumentURI();
    1202           0 :     mDocBaseURI = mDoc->GetDocBaseURI();
    1203             : 
    1204           7 :     while (mDoc->EventHandlingSuppressed()) {
    1205           0 :       mDoc->UnsuppressEventHandlingAndFireEvents(false);
    1206             :     }
    1207             : 
    1208           7 :     if (mObservingDidRefresh) {
    1209           0 :       nsIPresShell* shell = mDoc->GetShell();
    1210           0 :       if (shell) {
    1211           0 :         Unused << shell->RemovePostRefreshObserver(this);
    1212             :       }
    1213             :     }
    1214             :   }
    1215             : 
    1216             :   // Remove our reference to the document and the document principal.
    1217           7 :   mFocusedElement = nullptr;
    1218             : 
    1219          14 :   if (mApplicationCache) {
    1220           0 :     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();
    1221           0 :     mApplicationCache = nullptr;
    1222             :   }
    1223             : 
    1224          14 :   if (mIndexedDB) {
    1225           0 :     mIndexedDB->DisconnectFromWindow(this);
    1226           0 :     mIndexedDB = nullptr;
    1227             :   }
    1228             : 
    1229           7 :   UnlinkHostObjectURIs();
    1230             : 
    1231           7 :   NotifyWindowIDDestroyed("inner-window-destroyed");
    1232             : 
    1233           7 :   CleanupCachedXBLHandlers();
    1234             : 
    1235          14 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    1236           0 :     mAudioContexts[i]->Shutdown();
    1237             :   }
    1238           7 :   mAudioContexts.Clear();
    1239             : 
    1240           7 :   DisableGamepadUpdates();
    1241           0 :   mHasGamepad = false;
    1242           0 :   mGamepads.Clear();
    1243           0 :   DisableVRUpdates();
    1244           0 :   mHasVREvents = false;
    1245           0 :   mHasVRDisplayActivateEvents = false;
    1246           0 :   mVRDisplays.Clear();
    1247             : 
    1248             :   // This breaks a cycle between the window and the ClientSource object.
    1249           7 :   mClientSource.reset();
    1250             : 
    1251          14 :   if (mTabChild) {
    1252             :     // Remove any remaining listeners, and reset mBeforeUnloadListenerCount.
    1253           0 :     for (int i = 0; i < mBeforeUnloadListenerCount; ++i) {
    1254           0 :       mTabChild->BeforeUnloadRemoved();
    1255             :     }
    1256           0 :     mBeforeUnloadListenerCount = 0;
    1257             :   }
    1258             : 
    1259             :   // If we have any promiseDocumentFlushed callbacks, fire them now so
    1260             :   // that the Promises can resolve.
    1261           7 :   CallDocumentFlushedResolvers();
    1262           0 :   mObservingDidRefresh = false;
    1263             : 
    1264           7 :   DisconnectEventTargetObjects();
    1265             : 
    1266          14 :   if (mObserver) {
    1267           0 :     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1268           0 :     if (os) {
    1269           0 :       os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
    1270           0 :       os->RemoveObserver(mObserver, MEMORY_PRESSURE_OBSERVER_TOPIC);
    1271             :     }
    1272             : 
    1273          14 :     RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate();
    1274           0 :     if (sns) {
    1275           0 :      sns->Unregister(mObserver);
    1276             :     }
    1277             : 
    1278          14 :     if (mIdleService) {
    1279           0 :       mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
    1280             :     }
    1281             : 
    1282          14 :     Preferences::RemoveObserver(mObserver, "intl.accept_languages");
    1283             : 
    1284             :     // Drop its reference to this dying window, in case for some bogus reason
    1285             :     // the object stays around.
    1286           7 :     mObserver->Forget();
    1287             :   }
    1288             : 
    1289           7 :   mMenubar = nullptr;
    1290           0 :   mToolbar = nullptr;
    1291           0 :   mLocationbar = nullptr;
    1292           0 :   mPersonalbar = nullptr;
    1293           0 :   mStatusbar = nullptr;
    1294           0 :   mScrollbars = nullptr;
    1295             : 
    1296           7 :   mConsole = nullptr;
    1297             : 
    1298           7 :   mAudioWorklet = nullptr;
    1299           0 :   mPaintWorklet = nullptr;
    1300             : 
    1301           7 :   mExternal = nullptr;
    1302           0 :   mInstallTrigger = nullptr;
    1303             : 
    1304           7 :   mPerformance = nullptr;
    1305             : 
    1306             : #ifdef MOZ_WEBSPEECH
    1307           7 :   mSpeechSynthesis = nullptr;
    1308             : #endif
    1309             : 
    1310           7 :   mParentTarget = nullptr;
    1311             : 
    1312           7 :   if (mCleanMessageManager) {
    1313           0 :     MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
    1314           0 :     if (mChromeFields.mMessageManager) {
    1315           0 :       mChromeFields.mMessageManager->Disconnect();
    1316             :     }
    1317             :   }
    1318             : 
    1319           7 :   mIntlUtils = nullptr;
    1320             : }
    1321             : 
    1322             : //*****************************************************************************
    1323             : // nsGlobalWindowInner::nsISupports
    1324             : //*****************************************************************************
    1325             : 
    1326             : // QueryInterface implementation for nsGlobalWindowInner
    1327        6338 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindowInner)
    1328           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    1329           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, EventTarget)
    1330           0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)
    1331           0 :   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
    1332           0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
    1333           0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
    1334           0 :   NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
    1335           0 :   NS_INTERFACE_MAP_ENTRY(nsPIDOMWindowInner)
    1336           0 :   NS_INTERFACE_MAP_ENTRY(mozIDOMWindow)
    1337           0 :   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMChromeWindow, IsChromeWindow())
    1338           0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    1339           0 :   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
    1340           0 : NS_INTERFACE_MAP_END
    1341             : 
    1342             : 
    1343       25947 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindowInner)
    1344           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindowInner)
    1345             : 
    1346           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindowInner)
    1347           0 :   if (tmp->IsBlackForCC(false)) {
    1348           0 :     if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
    1349             :       return true;
    1350             :     }
    1351           0 :     tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
    1352           0 :     if (tmp->mCachedXBLPrototypeHandlers) {
    1353           0 :       for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
    1354           0 :            !iter.Done();
    1355           0 :            iter.Next()) {
    1356           0 :         iter.Data().exposeToActiveJS();
    1357             :       }
    1358             :     }
    1359           0 :     if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
    1360           0 :       elm->MarkForCC();
    1361             :     }
    1362           0 :     if (tmp->mTimeoutManager) {
    1363           0 :       tmp->mTimeoutManager->UnmarkGrayTimers();
    1364             :     }
    1365             :     return true;
    1366             :   }
    1367             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
    1368             : 
    1369           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindowInner)
    1370           0 :   return tmp->IsBlackForCC(true);
    1371             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
    1372             : 
    1373           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindowInner)
    1374           0 :   return tmp->IsBlackForCC(false);
    1375             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
    1376             : 
    1377             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindowInner)
    1378             : 
    1379           2 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)
    1380           0 :   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
    1381             :     char name[512];
    1382           0 :     nsAutoCString uri;
    1383           0 :     if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
    1384           0 :       uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();
    1385             :     }
    1386           0 :     SprintfLiteral(name, "nsGlobalWindowInner # %" PRIu64 " inner %s", tmp->mWindowID,
    1387           0 :                    uri.get());
    1388           0 :     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
    1389             :   } else {
    1390           2 :     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindowInner, tmp->mRefCnt.get())
    1391             :   }
    1392             : 
    1393           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
    1394             : 
    1395           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
    1396             : 
    1397             : #ifdef MOZ_WEBSPEECH
    1398           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)
    1399             : #endif
    1400             : 
    1401           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)
    1402             : 
    1403           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopInnerWindow)
    1404             : 
    1405           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
    1406             : 
    1407           2 :   if (tmp->mTimeoutManager) {
    1408           0 :     tmp->mTimeoutManager->ForEachUnorderedTimeout([&cb](Timeout* timeout) {
    1409           0 :       cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(Timeout));
    1410           0 :     });
    1411             :   }
    1412             : 
    1413           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
    1414           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)
    1415           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)
    1416             : 
    1417           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)
    1418           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)
    1419           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplicationCache)
    1420           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
    1421           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
    1422           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
    1423           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
    1424           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
    1425             : 
    1426           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)
    1427           0 :   for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
    1428           0 :     cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));
    1429             :   }
    1430             : 
    1431           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
    1432             : 
    1433           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mClientSource)
    1434             : 
    1435           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)
    1436             : 
    1437           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
    1438           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)
    1439             : 
    1440             :   // Traverse stuff from nsPIDOMWindow
    1441           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
    1442           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
    1443           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedElement)
    1444             : 
    1445           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)
    1446           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)
    1447           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)
    1448           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)
    1449           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)
    1450           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)
    1451           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
    1452           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mU2F)
    1453           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
    1454           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioWorklet)
    1455           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)
    1456           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)
    1457           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInstallTrigger)
    1458           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)
    1459             : 
    1460           1 :   tmp->TraverseHostObjectURIs(cb);
    1461             : 
    1462           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)
    1463           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)
    1464             : 
    1465           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPromises)
    1466             : 
    1467           2 :   for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) {
    1468           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mPromise);
    1469           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentFlushedResolvers[i]->mCallback);
    1470             :   }
    1471             : 
    1472           1 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1473             : 
    1474           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
    1475           0 :   tmp->CleanupCachedXBLHandlers();
    1476             : 
    1477           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
    1478             : 
    1479           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
    1480             : 
    1481             : 
    1482             : #ifdef MOZ_WEBSPEECH
    1483           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)
    1484             : #endif
    1485             : 
    1486           0 :   if (tmp->mOuterWindow) {
    1487             :     nsGlobalWindowOuter::Cast(tmp->mOuterWindow)->
    1488           0 :       MaybeClearInnerWindow(tmp);
    1489           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mOuterWindow)
    1490             :   }
    1491             : 
    1492           0 :   if (tmp->mListenerManager) {
    1493           0 :     tmp->mListenerManager->Disconnect();
    1494           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
    1495             :   }
    1496             : 
    1497             :   // Here the Timeouts list would've been unlinked, but we rely on
    1498             :   // that Timeout objects have been traced and will remove themselves
    1499             :   // while unlinking.
    1500             : 
    1501           0 :   tmp->UpdateTopInnerWindow();
    1502           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTopInnerWindow)
    1503             : 
    1504           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
    1505           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)
    1506           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)
    1507           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
    1508           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
    1509           0 :   if (tmp->mApplicationCache) {
    1510           0 :     static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())->Disconnect();
    1511           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
    1512             :   }
    1513           0 :   if (tmp->mIndexedDB) {
    1514           0 :     tmp->mIndexedDB->DisconnectFromWindow(tmp);
    1515           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
    1516             :   }
    1517           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
    1518           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)
    1519           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
    1520           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
    1521           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
    1522             : 
    1523           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)
    1524             : 
    1525           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
    1526           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)
    1527             : 
    1528             :   // Unlink stuff from nsPIDOMWindow
    1529           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
    1530           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
    1531           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedElement)
    1532             : 
    1533           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)
    1534           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)
    1535           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)
    1536           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)
    1537           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)
    1538           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)
    1539           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
    1540           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mU2F)
    1541           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
    1542           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioWorklet)
    1543           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)
    1544           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)
    1545           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mInstallTrigger)
    1546           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)
    1547             : 
    1548           0 :   tmp->UnlinkHostObjectURIs();
    1549             : 
    1550           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
    1551             : 
    1552             :   // Here the IdleRequest list would've been unlinked, but we rely on
    1553             :   // that IdleRequest objects have been traced and will remove
    1554             :   // themselves while unlinking.
    1555             : 
    1556           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mClientSource)
    1557             : 
    1558           0 :   if (tmp->IsChromeWindow()) {
    1559           0 :     if (tmp->mChromeFields.mMessageManager) {
    1560             :       static_cast<nsFrameMessageManager*>(
    1561           0 :         tmp->mChromeFields.mMessageManager.get())->Disconnect();
    1562           0 :       NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mMessageManager)
    1563             :     }
    1564           0 :     tmp->DisconnectAndClearGroupMessageManagers();
    1565           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mGroupMessageManagers)
    1566             :   }
    1567             : 
    1568           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPromises)
    1569           0 :   for (size_t i = 0; i < tmp->mDocumentFlushedResolvers.Length(); i++) {
    1570           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mPromise);
    1571           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentFlushedResolvers[i]->mCallback);
    1572             :   }
    1573           0 :   tmp->mDocumentFlushedResolvers.Clear();
    1574             : 
    1575           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
    1576           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1577             : 
    1578             : #ifdef DEBUG
    1579             : void
    1580           0 : nsGlobalWindowInner::RiskyUnlink()
    1581             : {
    1582           0 :   NS_CYCLE_COLLECTION_INNERNAME.Unlink(this);
    1583           0 : }
    1584             : #endif
    1585             : 
    1586           4 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindowInner)
    1587           0 :   if (tmp->mCachedXBLPrototypeHandlers) {
    1588           0 :     for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
    1589           0 :          !iter.Done();
    1590           0 :          iter.Next()) {
    1591           0 :       aCallbacks.Trace(&iter.Data(), "Cached XBL prototype handler", aClosure);
    1592             :     }
    1593             :   }
    1594           2 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
    1595           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    1596             : 
    1597             : bool
    1598           0 : nsGlobalWindowInner::IsBlackForCC(bool aTracingNeeded)
    1599             : {
    1600           0 :   if (!nsCCUncollectableMarker::sGeneration) {
    1601             :     return false;
    1602             :   }
    1603             : 
    1604           0 :   return (nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration()) ||
    1605           0 :           HasKnownLiveWrapper()) &&
    1606           0 :          (!aTracingNeeded ||
    1607           0 :           HasNothingToTrace(ToSupports(this)));
    1608             : }
    1609             : 
    1610             : //*****************************************************************************
    1611             : // nsGlobalWindowInner::nsIScriptGlobalObject
    1612             : //*****************************************************************************
    1613             : 
    1614             : nsresult
    1615         591 : nsGlobalWindowInner::EnsureScriptEnvironment()
    1616             : {
    1617             :   // NOTE: We can't use FORWARD_TO_OUTER here because we don't want to fail if
    1618             :   // we're called on an inactive inner window.
    1619         591 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    1620           0 :   if (!outer) {
    1621           0 :     NS_WARNING("No outer window available!");
    1622           0 :     return NS_ERROR_FAILURE;
    1623             :   }
    1624         591 :   return outer->EnsureScriptEnvironment();
    1625             : }
    1626             : 
    1627             : nsIScriptContext *
    1628         586 : nsGlobalWindowInner::GetScriptContext()
    1629             : {
    1630         586 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    1631           0 :   if (!outer) {
    1632             :     return nullptr;
    1633             :   }
    1634         586 :   return outer->GetScriptContext();
    1635             : }
    1636             : 
    1637             : JSObject *
    1638        6617 : nsGlobalWindowInner::GetGlobalJSObject()
    1639             : {
    1640        6617 :   return FastGetGlobalJSObject();
    1641             : }
    1642             : 
    1643             : void
    1644           0 : nsGlobalWindowInner::TraceGlobalJSObject(JSTracer* aTrc)
    1645             : {
    1646           0 :   TraceWrapper(aTrc, "active window global");
    1647           0 : }
    1648             : 
    1649             : PopupControlState
    1650           0 : nsGlobalWindowInner::GetPopupControlState() const
    1651             : {
    1652           0 :   return nsContentUtils::GetPopupControlState();
    1653             : }
    1654             : 
    1655             : nsresult
    1656           0 : nsGlobalWindowInner::SetNewDocument(nsIDocument* aDocument,
    1657             :                                     nsISupports* aState,
    1658             :                                     bool aForceReuseInnerWindow)
    1659             : {
    1660           0 :   MOZ_ASSERT(mDocumentPrincipal == nullptr,
    1661             :              "mDocumentPrincipal prematurely set!");
    1662           0 :   MOZ_ASSERT(aDocument);
    1663             : 
    1664           0 :   if (!mOuterWindow) {
    1665             :     return NS_ERROR_NOT_INITIALIZED;
    1666             :   }
    1667             : 
    1668             :   // Refuse to set a new document if the call came from an inner
    1669             :   // window that's not the current inner window.
    1670           0 :   if (mOuterWindow->GetCurrentInnerWindow() != this) {
    1671             :     return NS_ERROR_NOT_AVAILABLE;
    1672             :   }
    1673             : 
    1674           0 :   return GetOuterWindowInternal()->SetNewDocument(aDocument, aState,
    1675           0 :                                                   aForceReuseInnerWindow);
    1676             : }
    1677             : 
    1678             : void
    1679          14 : nsGlobalWindowInner::InnerSetNewDocument(JSContext* aCx, nsIDocument* aDocument)
    1680             : {
    1681          14 :   MOZ_ASSERT(aDocument);
    1682             : 
    1683          14 :   if (MOZ_LOG_TEST(gDOMLeakPRLogInner, LogLevel::Debug)) {
    1684           0 :     nsIURI *uri = aDocument->GetDocumentURI();
    1685           0 :     MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
    1686             :             ("DOMWINDOW %p SetNewDocument %s",
    1687             :              this, uri ? uri->GetSpecOrDefault().get() : ""));
    1688             :   }
    1689             : 
    1690          14 :   mDoc = aDocument;
    1691           0 :   ClearDocumentDependentSlots(aCx);
    1692           0 :   mFocusedElement = nullptr;
    1693           0 :   mLocalStorage = nullptr;
    1694           0 :   mSessionStorage = nullptr;
    1695             : 
    1696             : #ifdef DEBUG
    1697          28 :   mLastOpenedURI = aDocument->GetDocumentURI();
    1698             : #endif
    1699             : 
    1700          14 :   Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
    1701           0 :                         mMutationBits ? 1 : 0);
    1702             : 
    1703             :   // Clear our mutation bitfield.
    1704          14 :   mMutationBits = 0;
    1705           0 : }
    1706             : 
    1707             : nsresult
    1708          15 : nsGlobalWindowInner::EnsureClientSource()
    1709             : {
    1710          30 :   MOZ_DIAGNOSTIC_ASSERT(mDoc);
    1711             : 
    1712          15 :   bool newClientSource = false;
    1713             : 
    1714             :   // Get the load info for the document if we performed a load.  Be careful not
    1715             :   // to look at local URLs, though. Local URLs are those that have a scheme of:
    1716             :   //  * about:
    1717             :   //  * data:
    1718             :   //  * blob:
    1719             :   // We also do an additional check here so that we only treat about:blank
    1720             :   // and about:srcdoc as local URLs.  Other internal firefox about: URLs should
    1721             :   // not be treated this way.
    1722          30 :   nsCOMPtr<nsILoadInfo> loadInfo;
    1723           0 :   nsCOMPtr<nsIChannel> channel = mDoc->GetChannel();
    1724           0 :   if (channel) {
    1725           0 :     nsCOMPtr<nsIURI> uri;
    1726           0 :     Unused << channel->GetURI(getter_AddRefs(uri));
    1727             : 
    1728           7 :     bool ignoreLoadInfo = false;
    1729             : 
    1730             :     // Note, this is mostly copied from NS_IsAboutBlank().  Its duplicated
    1731             :     // here so we can efficiently check about:srcdoc as well.
    1732           7 :     bool isAbout = false;
    1733           0 :     if (NS_SUCCEEDED(uri->SchemeIs("about", &isAbout)) && isAbout) {
    1734           0 :       nsCString spec = uri->GetSpecOrDefault();
    1735           0 :       ignoreLoadInfo = spec.EqualsLiteral("about:blank") ||
    1736           0 :                        spec.EqualsLiteral("about:srcdoc");
    1737             :     } else {
    1738             :       // Its not an about: URL, so now check for our other URL types.
    1739           6 :       bool isData = false;
    1740           0 :       bool isBlob = false;
    1741           0 :       ignoreLoadInfo = (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData) ||
    1742           0 :                        (NS_SUCCEEDED(uri->SchemeIs("blob", &isBlob)) && isBlob);
    1743             :     }
    1744             : 
    1745           7 :     if (!ignoreLoadInfo) {
    1746           0 :       loadInfo = channel->GetLoadInfo();
    1747             :     }
    1748             :   }
    1749             : 
    1750             :   // Take the initial client source from the docshell immediately.  Even if we
    1751             :   // don't end up using it here we should consume it.
    1752          30 :   UniquePtr<ClientSource> initialClientSource;
    1753           0 :   nsIDocShell* docshell = GetDocShell();
    1754           0 :   if (docshell) {
    1755           0 :     initialClientSource = docshell->TakeInitialClientSource();
    1756             :   }
    1757             : 
    1758             :   // Try to get the reserved client from the LoadInfo.  A Client is
    1759             :   // reserved at the start of the channel load if there is not an
    1760             :   // initial about:blank document that will be reused.  It is also
    1761             :   // created if the channel load encounters a cross-origin redirect.
    1762          15 :   if (loadInfo) {
    1763           0 :     UniquePtr<ClientSource> reservedClient = loadInfo->TakeReservedClientSource();
    1764           0 :     if (reservedClient) {
    1765           0 :       mClientSource.reset();
    1766           0 :       mClientSource = std::move(reservedClient);
    1767           0 :       newClientSource = true;
    1768             :     }
    1769             :   }
    1770             : 
    1771             :   // We don't have a LoadInfo reserved client, but maybe we should
    1772             :   // be inheriting an initial one from the docshell.  This means
    1773             :   // that the docshell started the channel load before creating the
    1774             :   // initial about:blank document.  This is an optimization, though,
    1775             :   // and it created an initial Client as a placeholder for the document.
    1776             :   // In this case we want to inherit this placeholder Client here.
    1777          30 :   if (!mClientSource) {
    1778           0 :     mClientSource = std::move(initialClientSource);
    1779           0 :     if (mClientSource) {
    1780           0 :       newClientSource = true;
    1781             :     }
    1782             :   }
    1783             : 
    1784             :   // Verify the final ClientSource principal matches the final document
    1785             :   // principal.  The ClientChannelHelper handles things like network
    1786             :   // redirects, but there are other ways the document principal can change.
    1787             :   // For example, if something sets the nsIChannel.owner property, then
    1788             :   // the final channel principal can be anything.  Unfortunately there is
    1789             :   // no good way to detect this until after the channel completes loading.
    1790             :   //
    1791             :   // For now we handle this just by reseting the ClientSource.  This will
    1792             :   // result in a new ClientSource with the correct principal being created.
    1793             :   // To APIs like ServiceWorker and Clients API it will look like there was
    1794             :   // an initial content page created that was then immediately replaced.
    1795             :   // This is pretty close to what we are actually doing.
    1796          30 :   if (mClientSource) {
    1797           0 :     nsCOMPtr<nsIPrincipal> clientPrincipal(mClientSource->Info().GetPrincipal());
    1798           0 :     if (!clientPrincipal || !clientPrincipal->Equals(mDoc->NodePrincipal())) {
    1799           0 :       mClientSource.reset();
    1800             :     }
    1801             :   }
    1802             : 
    1803             :   // If we don't have a reserved client or an initial client, then create
    1804             :   // one now.  This can happen in certain cases where we avoid preallocating
    1805             :   // the client in the docshell.  This mainly occurs in situations where
    1806             :   // the principal is not clearly inherited from the parent; e.g. sandboxed
    1807             :   // iframes, window.open(), etc.
    1808             :   //
    1809             :   // We also do this late ClientSource creation if the final document ended
    1810             :   // up with a different principal.
    1811             :   //
    1812             :   // TODO: We may not be marking initial about:blank documents created
    1813             :   //       this way as controlled by a service worker properly.  The
    1814             :   //       controller should be coming from the same place as the inheritted
    1815             :   //       principal.  We do this in docshell, but as mentioned we aren't
    1816             :   //       smart enough to handle all cases yet.  For example, a
    1817             :   //       window.open() with new URL should inherit the controller from
    1818             :   //       the opener, but we probably don't handle that yet.
    1819          30 :   if (!mClientSource) {
    1820           0 :     mClientSource = ClientManager::CreateSource(ClientType::Window,
    1821             :                                                 EventTargetFor(TaskCategory::Other),
    1822          14 :                                                 mDoc->NodePrincipal());
    1823           0 :     MOZ_DIAGNOSTIC_ASSERT(mClientSource);
    1824             :     newClientSource = true;
    1825             : 
    1826             :     // Note, we don't apply the loadinfo controller below if we create
    1827             :     // the ClientSource here.
    1828             :   }
    1829             : 
    1830             :   // The load may have started controlling the Client as well.  If
    1831             :   // so, mark it as controlled immediately here.  The actor may
    1832             :   // or may not have been notified by the parent side about being
    1833             :   // controlled yet.
    1834             :   //
    1835             :   // Note: We should be careful not to control a client that was created late.
    1836             :   //       These clients were not seen by the ServiceWorkerManager when it
    1837             :   //       marked the LoadInfo controlled and it won't know about them.  Its
    1838             :   //       also possible we are creating the client late due to the final
    1839             :   //       principal changing and these clients should definitely not be
    1840             :   //       controlled by a service worker with a different principal.
    1841           8 :   else if (loadInfo) {
    1842           0 :     const Maybe<ServiceWorkerDescriptor> controller = loadInfo->GetController();
    1843           0 :     if (controller.isSome()) {
    1844           0 :       mClientSource->SetController(controller.ref());
    1845             :     }
    1846             : 
    1847             :     // We also have to handle the case where te initial about:blank is
    1848             :     // controlled due to inheritting the service worker from its parent,
    1849             :     // but the actual nsIChannel load is not covered by any service worker.
    1850             :     // In this case we want the final page to be uncontrolled.  There is
    1851             :     // an open spec issue about how exactly this should be handled, but for
    1852             :     // now we just force creation of a new ClientSource to clear the
    1853             :     // controller.
    1854             :     //
    1855             :     //  https://github.com/w3c/ServiceWorker/issues/1232
    1856             :     //
    1857           4 :     else if (mClientSource->GetController().isSome()) {
    1858           0 :       mClientSource.reset();
    1859             :       mClientSource =
    1860           0 :         ClientManager::CreateSource(ClientType::Window,
    1861             :                                     EventTargetFor(TaskCategory::Other),
    1862           0 :                                     mDoc->NodePrincipal());
    1863           0 :       MOZ_DIAGNOSTIC_ASSERT(mClientSource);
    1864             :       newClientSource = true;
    1865             :     }
    1866             :   }
    1867             : 
    1868             :   // Its possible that we got a client just after being frozen in
    1869             :   // the bfcache.  In that case freeze the client immediately.
    1870          15 :   if (newClientSource && IsFrozen()) {
    1871           0 :     mClientSource->Freeze();
    1872             :   }
    1873             : 
    1874          15 :   return NS_OK;
    1875             : }
    1876             : 
    1877             : nsresult
    1878          15 : nsGlobalWindowInner::ExecutionReady()
    1879             : {
    1880          15 :   nsresult rv = EnsureClientSource();
    1881           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1882             : 
    1883          15 :   rv = mClientSource->WindowExecutionReady(AsInner());
    1884           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1885             : 
    1886             :   return NS_OK;
    1887             : }
    1888             : 
    1889             : void
    1890           0 : nsGlobalWindowInner::SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
    1891             :                                      bool aOriginalOpener)
    1892             : {
    1893           0 :   FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener, aOriginalOpener));
    1894             : }
    1895             : 
    1896             : void
    1897          14 : nsGlobalWindowInner::UpdateParentTarget()
    1898             : {
    1899             :   // NOTE: This method is identical to
    1900             :   // nsGlobalWindowOuter::UpdateParentTarget(). IF YOU UPDATE THIS METHOD,
    1901             :   // UPDATE THE OTHER ONE TOO!
    1902             : 
    1903             :   // Try to get our frame element's tab child global (its in-process message
    1904             :   // manager).  If that fails, fall back to the chrome event handler's tab
    1905             :   // child global, and if it doesn't have one, just use the chrome event
    1906             :   // handler itself.
    1907             : 
    1908          42 :   nsCOMPtr<Element> frameElement = GetOuterWindow()->GetFrameElementInternal();
    1909             :   nsCOMPtr<EventTarget> eventTarget =
    1910          28 :     nsContentUtils::TryGetTabChildGlobalAsEventTarget(frameElement);
    1911             : 
    1912          14 :   if (!eventTarget) {
    1913           0 :     nsGlobalWindowOuter* topWin = GetScriptableTopInternal();
    1914           0 :     if (topWin) {
    1915           0 :       frameElement = topWin->AsOuter()->GetFrameElementInternal();
    1916             :       eventTarget =
    1917           9 :         nsContentUtils::TryGetTabChildGlobalAsEventTarget(frameElement);
    1918             :     }
    1919             :   }
    1920             : 
    1921          14 :   if (!eventTarget) {
    1922             :     eventTarget =
    1923          18 :       nsContentUtils::TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);
    1924             :   }
    1925             : 
    1926          14 :   if (!eventTarget) {
    1927           0 :     eventTarget = mChromeEventHandler;
    1928             :   }
    1929             : 
    1930          14 :   mParentTarget = eventTarget;
    1931           0 : }
    1932             : 
    1933             : EventTarget*
    1934          29 : nsGlobalWindowInner::GetTargetForDOMEvent()
    1935             : {
    1936          29 :   return GetOuterWindowInternal();
    1937             : }
    1938             : 
    1939             : void
    1940         170 : nsGlobalWindowInner::GetEventTargetParent(EventChainPreVisitor& aVisitor)
    1941             : {
    1942         170 :   EventMessage msg = aVisitor.mEvent->mMessage;
    1943             : 
    1944         170 :   aVisitor.mCanHandle = true;
    1945           0 :   aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
    1946           0 :   if (msg == eResize && aVisitor.mEvent->IsTrusted()) {
    1947             :     // QIing to window so that we can keep the old behavior also in case
    1948             :     // a child window is handling resize.
    1949             :     nsCOMPtr<nsPIDOMWindowInner> window =
    1950           4 :       do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
    1951           0 :     if (window) {
    1952           0 :       mIsHandlingResizeEvent = true;
    1953             :     }
    1954         169 :   } else if (msg == eMouseDown && aVisitor.mEvent->IsTrusted()) {
    1955           0 :     sMouseDown = true;
    1956           0 :   } else if ((msg == eMouseUp || msg == eDragEnd) &&
    1957           0 :              aVisitor.mEvent->IsTrusted()) {
    1958           0 :     sMouseDown = false;
    1959           0 :     if (sDragServiceDisabled) {
    1960             :       nsCOMPtr<nsIDragService> ds =
    1961           0 :         do_GetService("@mozilla.org/widget/dragservice;1");
    1962           0 :       if (ds) {
    1963           0 :         sDragServiceDisabled = false;
    1964           0 :         ds->Unsuppress();
    1965             :       }
    1966             :     }
    1967             :   }
    1968             : 
    1969         340 :   aVisitor.SetParentTarget(GetParentTarget(), true);
    1970             : 
    1971             :   // Handle 'active' event.
    1972         510 :   if (!mIdleObservers.IsEmpty() &&
    1973           0 :       aVisitor.mEvent->IsTrusted() &&
    1974           0 :       (aVisitor.mEvent->HasMouseEventMessage() ||
    1975           0 :        aVisitor.mEvent->HasDragEventMessage())) {
    1976           0 :     mAddActiveEventFuzzTime = false;
    1977             :   }
    1978         170 : }
    1979             : 
    1980             : bool
    1981           0 : nsGlobalWindowInner::DialogsAreBeingAbused()
    1982             : {
    1983           0 :   NS_ASSERTION(GetScriptableTopInternal() &&
    1984             :                GetScriptableTopInternal()->GetCurrentInnerWindowInternal() == this,
    1985             :                "DialogsAreBeingAbused called with invalid window");
    1986             : 
    1987           0 :   if (mLastDialogQuitTime.IsNull() ||
    1988           0 :       nsContentUtils::IsCallerChrome()) {
    1989             :     return false;
    1990             :   }
    1991             : 
    1992           0 :   TimeDuration dialogInterval(TimeStamp::Now() - mLastDialogQuitTime);
    1993           0 :   if (dialogInterval.ToSeconds() <
    1994           0 :       Preferences::GetInt("dom.successive_dialog_time_limit",
    1995             :                           DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT)) {
    1996           0 :     mDialogAbuseCount++;
    1997             : 
    1998           0 :     return GetPopupControlState() > openAllowed ||
    1999             :            mDialogAbuseCount > MAX_SUCCESSIVE_DIALOG_COUNT;
    2000             :   }
    2001             : 
    2002             :   // Reset the abuse counter
    2003           0 :   mDialogAbuseCount = 0;
    2004             : 
    2005           0 :   return false;
    2006             : }
    2007             : 
    2008             : void
    2009           0 : nsGlobalWindowInner::DisableDialogs()
    2010             : {
    2011           0 :   FORWARD_TO_OUTER_VOID(DisableDialogs, ());
    2012             : }
    2013             : 
    2014             : void
    2015           0 : nsGlobalWindowInner::EnableDialogs()
    2016             : {
    2017           0 :   FORWARD_TO_OUTER_VOID(EnableDialogs, ());
    2018             : }
    2019             : 
    2020             : nsresult
    2021         128 : nsGlobalWindowInner::PostHandleEvent(EventChainPostVisitor& aVisitor)
    2022             : {
    2023             :   // Return early if there is nothing to do.
    2024         128 :   switch (aVisitor.mEvent->mMessage) {
    2025             :     case eResize:
    2026             :     case eUnload:
    2027             :     case eLoad:
    2028             :       break;
    2029             :     default:
    2030             :       return NS_OK;
    2031             :   }
    2032             : 
    2033             :   /* mChromeEventHandler and mContext go dangling in the middle of this
    2034             :    function under some circumstances (events that destroy the window)
    2035             :    without this addref. */
    2036          48 :   RefPtr<EventTarget> kungFuDeathGrip1(mChromeEventHandler);
    2037             :   mozilla::Unused << kungFuDeathGrip1; // These aren't referred to through the function
    2038          32 :   nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
    2039             :   mozilla::Unused << kungFuDeathGrip2; // These aren't referred to through the function
    2040             : 
    2041             : 
    2042          16 :   if (aVisitor.mEvent->mMessage == eResize) {
    2043           0 :     mIsHandlingResizeEvent = false;
    2044           0 :   } else if (aVisitor.mEvent->mMessage == eUnload &&
    2045           0 :              aVisitor.mEvent->IsTrusted()) {
    2046             : 
    2047             :     // If any VR display presentation is active at unload, the next page
    2048             :     // will receive a vrdisplayactive event to indicate that it should
    2049             :     // immediately begin vr presentation. This should occur when navigating
    2050             :     // forwards, navigating backwards, and on page reload.
    2051          24 :     for (const auto& display : mVRDisplays) {
    2052           0 :       if (display->IsPresenting()) {
    2053             :         // Save this VR display ID to trigger vrdisplayactivate event
    2054             :         // after the next load event.
    2055           0 :         nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    2056           0 :         if (outer) {
    2057           0 :           outer->SetAutoActivateVRDisplayID(display->DisplayId());
    2058             :         }
    2059             : 
    2060             :         // XXX The WebVR 1.1 spec does not define which of multiple VR
    2061             :         // presenting VR displays will be chosen during navigation.
    2062             :         // As the underlying platform VR API's currently only allow a single
    2063             :         // VR display, it is safe to choose the first VR display for now.
    2064             :         break;
    2065             :       }
    2066             :     }
    2067             :     // Execute bindingdetached handlers before we tear ourselves
    2068             :     // down.
    2069          16 :     if (mDoc) {
    2070           0 :       mDoc->BindingManager()->ExecuteDetachedHandlers();
    2071             :     }
    2072           8 :     mIsDocumentLoaded = false;
    2073           0 :   } else if (aVisitor.mEvent->mMessage == eLoad &&
    2074           0 :              aVisitor.mEvent->IsTrusted()) {
    2075             :     // This is page load event since load events don't propagate to |window|.
    2076             :     // @see nsDocument::GetEventTargetParent.
    2077           7 :     mIsDocumentLoaded = true;
    2078             : 
    2079           7 :     mTimeoutManager->OnDocumentLoaded();
    2080             : 
    2081          21 :     nsCOMPtr<Element> element = GetOuterWindow()->GetFrameElementInternal();
    2082           0 :     nsIDocShell* docShell = GetDocShell();
    2083           0 :     if (element && GetParentInternal() &&
    2084           0 :         docShell && docShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
    2085             :       // If we're not in chrome, or at a chrome boundary, fire the
    2086             :       // onload event for the frame element.
    2087             : 
    2088           0 :       nsEventStatus status = nsEventStatus_eIgnore;
    2089           0 :       WidgetEvent event(aVisitor.mEvent->IsTrusted(), eLoad);
    2090           0 :       event.mFlags.mBubbles = false;
    2091           0 :       event.mFlags.mCancelable = false;
    2092             : 
    2093             :       // Most of the time we could get a pres context to pass in here,
    2094             :       // but not always (i.e. if this window is not shown there won't
    2095             :       // be a pres context available). Since we're not firing a GUI
    2096             :       // event we don't need a pres context anyway so we just pass
    2097             :       // null as the pres context all the time here.
    2098           0 :       EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
    2099             :     }
    2100             : 
    2101          14 :     if (mVREventObserver) {
    2102           0 :       mVREventObserver->NotifyAfterLoad();
    2103             :     }
    2104             : 
    2105           7 :     uint32_t autoActivateVRDisplayID = 0;
    2106           0 :     nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    2107           0 :     if (outer) {
    2108           0 :       autoActivateVRDisplayID = outer->GetAutoActivateVRDisplayID();
    2109             :     }
    2110           7 :     if (autoActivateVRDisplayID) {
    2111             :       DispatchVRDisplayActivate(autoActivateVRDisplayID,
    2112           0 :                                 VRDisplayEventReason::Navigation);
    2113             :     }
    2114             :   }
    2115             : 
    2116             :   return NS_OK;
    2117             : }
    2118             : 
    2119             : nsresult
    2120           2 : nsGlobalWindowInner::DefineArgumentsProperty(nsIArray *aArguments)
    2121             : {
    2122           4 :   nsIScriptContext *ctx = GetOuterWindowInternal()->mContext;
    2123           0 :   NS_ENSURE_TRUE(aArguments && ctx, NS_ERROR_NOT_INITIALIZED);
    2124             : 
    2125           4 :   JS::Rooted<JSObject*> obj(RootingCx(), GetWrapperPreserveColor());
    2126           0 :   return ctx->SetProperty(obj, "arguments", aArguments);
    2127             : }
    2128             : 
    2129             : //*****************************************************************************
    2130             : // nsGlobalWindowInner::nsIScriptObjectPrincipal
    2131             : //*****************************************************************************
    2132             : 
    2133             : nsIPrincipal*
    2134           1 : nsGlobalWindowInner::GetPrincipal()
    2135             : {
    2136           2 :   if (mDoc) {
    2137             :     // If we have a document, get the principal from the document
    2138           1 :     return mDoc->NodePrincipal();
    2139             :   }
    2140             : 
    2141           0 :   if (mDocumentPrincipal) {
    2142             :     return mDocumentPrincipal;
    2143             :   }
    2144             : 
    2145             :   // If we don't have a principal and we don't have a document we
    2146             :   // ask the parent window for the principal. This can happen when
    2147             :   // loading a frameset that has a <frame src="javascript:xxx">, in
    2148             :   // that case the global window is used in JS before we've loaded
    2149             :   // a document into the window.
    2150             : 
    2151             :   nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
    2152           0 :     do_QueryInterface(GetParentInternal());
    2153             : 
    2154           0 :   if (objPrincipal) {
    2155           0 :     return objPrincipal->GetPrincipal();
    2156             :   }
    2157             : 
    2158             :   return nullptr;
    2159             : }
    2160             : 
    2161             : //*****************************************************************************
    2162             : // nsGlobalWindowInner::nsIDOMWindow
    2163             : //*****************************************************************************
    2164             : 
    2165             : bool
    2166           0 : nsPIDOMWindowInner::AddAudioContext(AudioContext* aAudioContext)
    2167             : {
    2168           0 :   mAudioContexts.AppendElement(aAudioContext);
    2169             : 
    2170             :   // Return true if the context should be muted and false if not.
    2171           0 :   nsIDocShell* docShell = GetDocShell();
    2172           0 :   return docShell && !docShell->GetAllowMedia() && !aAudioContext->IsOffline();
    2173             : }
    2174             : 
    2175             : void
    2176           0 : nsPIDOMWindowInner::RemoveAudioContext(AudioContext* aAudioContext)
    2177             : {
    2178           0 :   mAudioContexts.RemoveElement(aAudioContext);
    2179           0 : }
    2180             : 
    2181             : void
    2182           0 : nsPIDOMWindowInner::MuteAudioContexts()
    2183             : {
    2184           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    2185           0 :     if (!mAudioContexts[i]->IsOffline()) {
    2186           0 :       mAudioContexts[i]->Mute();
    2187             :     }
    2188             :   }
    2189           0 : }
    2190             : 
    2191             : void
    2192           0 : nsPIDOMWindowInner::UnmuteAudioContexts()
    2193             : {
    2194           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    2195           0 :     if (!mAudioContexts[i]->IsOffline()) {
    2196           0 :       mAudioContexts[i]->Unmute();
    2197             :     }
    2198             :   }
    2199           0 : }
    2200             : 
    2201             : nsGlobalWindowInner*
    2202          14 : nsGlobalWindowInner::Window()
    2203             : {
    2204          14 :   return this;
    2205             : }
    2206             : 
    2207             : nsGlobalWindowInner*
    2208          14 : nsGlobalWindowInner::Self()
    2209             : {
    2210          14 :   return this;
    2211             : }
    2212             : 
    2213             : Navigator*
    2214           0 : nsPIDOMWindowInner::Navigator()
    2215             : {
    2216           0 :   if (!mNavigator) {
    2217           0 :     mNavigator = new mozilla::dom::Navigator(this);
    2218             :   }
    2219             : 
    2220           0 :   return mNavigator;
    2221             : }
    2222             : 
    2223             : nsScreen*
    2224           4 : nsGlobalWindowInner::GetScreen(ErrorResult& aError)
    2225             : {
    2226           8 :   if (!mScreen) {
    2227           0 :     mScreen = nsScreen::Create(this);
    2228           0 :     if (!mScreen) {
    2229           0 :       aError.Throw(NS_ERROR_UNEXPECTED);
    2230           0 :       return nullptr;
    2231             :     }
    2232             :   }
    2233             : 
    2234           8 :   return mScreen;
    2235             : }
    2236             : 
    2237             : nsHistory*
    2238           0 : nsGlobalWindowInner::GetHistory(ErrorResult& aError)
    2239             : {
    2240           0 :   if (!mHistory) {
    2241           0 :     mHistory = new nsHistory(this);
    2242             :   }
    2243             : 
    2244           0 :   return mHistory;
    2245             : }
    2246             : 
    2247             : CustomElementRegistry*
    2248        6799 : nsGlobalWindowInner::CustomElements()
    2249             : {
    2250       13598 :   if (!mCustomElements) {
    2251           0 :     mCustomElements = new CustomElementRegistry(this);
    2252             :   }
    2253             : 
    2254       13598 :   return mCustomElements;
    2255             : }
    2256             : 
    2257             : Performance*
    2258          94 : nsPIDOMWindowInner::GetPerformance()
    2259             : {
    2260          94 :   CreatePerformanceObjectIfNeeded();
    2261           0 :   return mPerformance;
    2262             : }
    2263             : 
    2264             : void
    2265          94 : nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
    2266             : {
    2267         216 :   if (mPerformance || !mDoc) {
    2268           0 :     return;
    2269             :   }
    2270          42 :   RefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
    2271           0 :   nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
    2272           0 :   bool timingEnabled = false;
    2273           0 :   if (!timedChannel ||
    2274           0 :       !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
    2275           0 :       !timingEnabled) {
    2276           0 :     timedChannel = nullptr;
    2277             :   }
    2278          14 :   if (timing) {
    2279           0 :     mPerformance = Performance::CreateForMainThread(this, mDoc->NodePrincipal(), timing, timedChannel);
    2280             :   }
    2281             : }
    2282             : 
    2283             : bool
    2284           0 : nsPIDOMWindowInner::IsSecureContext() const
    2285             : {
    2286           0 :   return nsGlobalWindowInner::Cast(this)->IsSecureContext();
    2287             : }
    2288             : 
    2289             : void
    2290           0 : nsPIDOMWindowInner::Suspend()
    2291             : {
    2292           0 :   nsGlobalWindowInner::Cast(this)->Suspend();
    2293           0 : }
    2294             : 
    2295             : void
    2296           0 : nsPIDOMWindowInner::Resume()
    2297             : {
    2298           0 :   nsGlobalWindowInner::Cast(this)->Resume();
    2299           0 : }
    2300             : 
    2301             : void
    2302           0 : nsPIDOMWindowInner::Freeze()
    2303             : {
    2304           0 :   nsGlobalWindowInner::Cast(this)->Freeze();
    2305           0 : }
    2306             : 
    2307             : void
    2308           0 : nsPIDOMWindowInner::Thaw()
    2309             : {
    2310           0 :   nsGlobalWindowInner::Cast(this)->Thaw();
    2311           0 : }
    2312             : 
    2313             : void
    2314          14 : nsPIDOMWindowInner::SyncStateFromParentWindow()
    2315             : {
    2316          14 :   nsGlobalWindowInner::Cast(this)->SyncStateFromParentWindow();
    2317           0 : }
    2318             : 
    2319             : Maybe<ClientInfo>
    2320          82 : nsPIDOMWindowInner::GetClientInfo() const
    2321             : {
    2322          82 :   return nsGlobalWindowInner::Cast(this)->GetClientInfo();
    2323             : }
    2324             : 
    2325             : Maybe<ClientState>
    2326           0 : nsPIDOMWindowInner::GetClientState() const
    2327             : {
    2328           0 :   return nsGlobalWindowInner::Cast(this)->GetClientState();
    2329             : }
    2330             : 
    2331             : Maybe<ServiceWorkerDescriptor>
    2332         104 : nsPIDOMWindowInner::GetController() const
    2333             : {
    2334         104 :   return nsGlobalWindowInner::Cast(this)->GetController();
    2335             : }
    2336             : 
    2337             : RefPtr<mozilla::dom::ServiceWorker>
    2338           0 : nsPIDOMWindowInner::GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor)
    2339             : {
    2340           0 :   return nsGlobalWindowInner::Cast(this)->GetOrCreateServiceWorker(aDescriptor);
    2341             : }
    2342             : 
    2343             : void
    2344           0 : nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
    2345             : {
    2346           0 :   nsGlobalWindowInner::Cast(this)->NoteCalledRegisterForServiceWorkerScope(aScope);
    2347           0 : }
    2348             : 
    2349             : bool
    2350           0 : nsGlobalWindowInner::ShouldReportForServiceWorkerScope(const nsAString& aScope)
    2351             : {
    2352           0 :   bool result = false;
    2353             : 
    2354           0 :   nsPIDOMWindowOuter* topOuter = GetScriptableTop();
    2355           0 :   NS_ENSURE_TRUE(topOuter, false);
    2356             : 
    2357             :   nsGlobalWindowInner* topInner =
    2358           0 :     nsGlobalWindowInner::Cast(topOuter->GetCurrentInnerWindow());
    2359           0 :   NS_ENSURE_TRUE(topInner, false);
    2360             : 
    2361           0 :   topInner->ShouldReportForServiceWorkerScopeInternal(NS_ConvertUTF16toUTF8(aScope),
    2362           0 :                                                       &result);
    2363           0 :   return result;
    2364             : }
    2365             : 
    2366             : already_AddRefed<InstallTriggerImpl>
    2367           0 : nsGlobalWindowInner::GetInstallTrigger()
    2368             : {
    2369           0 :   if (!mInstallTrigger) {
    2370           0 :     JS::Rooted<JSObject*> jsImplObj(RootingCx());
    2371           0 :     ErrorResult rv;
    2372           0 :     ConstructJSImplementation("@mozilla.org/addons/installtrigger;1", this,
    2373           0 :                               &jsImplObj, rv);
    2374           0 :     if (rv.Failed()) {
    2375           0 :       rv.SuppressException();
    2376           0 :       return nullptr;
    2377             :     }
    2378           0 :     mInstallTrigger = new InstallTriggerImpl(jsImplObj, this);
    2379             :   }
    2380             : 
    2381           0 :   return do_AddRef(mInstallTrigger);
    2382             : }
    2383             : 
    2384             : nsGlobalWindowInner::CallState
    2385           0 : nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal(const nsACString& aScope,
    2386             :                                                                bool* aResultOut)
    2387             : {
    2388           0 :   MOZ_DIAGNOSTIC_ASSERT(aResultOut);
    2389             : 
    2390             :   // First check to see if this window is controlled.  If so, then we have
    2391             :   // found a match and are done.
    2392           0 :   const Maybe<ServiceWorkerDescriptor> swd = GetController();
    2393           0 :   if (swd.isSome() && swd.ref().Scope() == aScope) {
    2394           0 :     *aResultOut = true;
    2395           0 :     return CallState::Stop;
    2396             :   }
    2397             : 
    2398             :   // Next, check to see if this window has called navigator.serviceWorker.register()
    2399             :   // for this scope.  If so, then treat this as a match so console reports
    2400             :   // appear in the devtools console.
    2401           0 :   if (mClientSource && mClientSource->CalledRegisterForServiceWorkerScope(aScope)) {
    2402           0 :     *aResultOut = true;
    2403           0 :     return CallState::Stop;
    2404             :   }
    2405             : 
    2406             :   // Finally check the current docshell nsILoadGroup to see if there are any
    2407             :   // outstanding navigation requests.  If so, match the scope against the
    2408             :   // channel's URL.  We want to show console reports during the FetchEvent
    2409             :   // intercepting the navigation itself.
    2410           0 :   nsCOMPtr<nsIDocumentLoader> loader(do_QueryInterface(GetDocShell()));
    2411           0 :   if (loader) {
    2412           0 :     nsCOMPtr<nsILoadGroup> loadgroup;
    2413           0 :     Unused << loader->GetLoadGroup(getter_AddRefs(loadgroup));
    2414           0 :     if (loadgroup) {
    2415           0 :       nsCOMPtr<nsISimpleEnumerator> iter;
    2416           0 :       Unused << loadgroup->GetRequests(getter_AddRefs(iter));
    2417           0 :       if (iter) {
    2418           0 :         nsCOMPtr<nsISupports> tmp;
    2419           0 :         bool hasMore = true;
    2420             :         // Check each network request in the load group.
    2421           0 :         while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
    2422           0 :           iter->GetNext(getter_AddRefs(tmp));
    2423           0 :           nsCOMPtr<nsIChannel> loadingChannel(do_QueryInterface(tmp));
    2424             :           // Ignore subresource requests.  Logging for a subresource
    2425             :           // FetchEvent should be handled above since the client is
    2426             :           // already controlled.
    2427           0 :           if (!loadingChannel ||
    2428           0 :               !nsContentUtils::IsNonSubresourceRequest(loadingChannel)) {
    2429           0 :             continue;
    2430             :           }
    2431           0 :           nsCOMPtr<nsIURI> loadingURL;
    2432           0 :           Unused << loadingChannel->GetURI(getter_AddRefs(loadingURL));
    2433           0 :           if (!loadingURL) {
    2434           0 :             continue;
    2435             :           }
    2436           0 :           nsAutoCString loadingSpec;
    2437           0 :           Unused << loadingURL->GetSpec(loadingSpec);
    2438             :           // Perform a simple substring comparison to match the scope
    2439             :           // against the channel URL.
    2440           0 :           if (StringBeginsWith(loadingSpec, aScope)) {
    2441           0 :             *aResultOut = true;
    2442           0 :             return CallState::Stop;
    2443             :           }
    2444             :         }
    2445             :       }
    2446             :     }
    2447             :   }
    2448             : 
    2449             :   // The current window doesn't care about this service worker, but maybe
    2450             :   // one of our child frames does.
    2451           0 :   return CallOnChildren(&nsGlobalWindowInner::ShouldReportForServiceWorkerScopeInternal,
    2452           0 :                         aScope, aResultOut);
    2453             : }
    2454             : 
    2455             : void
    2456           0 : nsGlobalWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
    2457             : {
    2458           0 :   if (!mClientSource) {
    2459             :     return;
    2460             :   }
    2461             : 
    2462           0 :   mClientSource->NoteCalledRegisterForServiceWorkerScope(aScope);
    2463             : }
    2464             : 
    2465             : void
    2466           0 : nsGlobalWindowInner::MigrateStateForDocumentOpen(nsGlobalWindowInner* aOldInner)
    2467             : {
    2468           0 :   MOZ_DIAGNOSTIC_ASSERT(aOldInner);
    2469           0 :   MOZ_DIAGNOSTIC_ASSERT(aOldInner != this);
    2470           0 :   MOZ_DIAGNOSTIC_ASSERT(mDoc);
    2471             : 
    2472             :   // Rebind DETH objects to the new global created by document.open().
    2473             :   // XXX: Is this correct?  We should consider if the spec and our
    2474             :   //      implementation should change to match other browsers by
    2475             :   //      just reusing the current window.  (Bug 1449992)
    2476           0 :   aOldInner->ForEachEventTargetObject(
    2477           0 :     [&] (DOMEventTargetHelper* aDETH, bool* aDoneOut) {
    2478           0 :       aDETH->BindToOwner(this->AsInner());
    2479           0 :     });
    2480             : 
    2481             :   // Move the old Performance object from the old window to the new window.
    2482             :   // The Performance object was also rebound in the DETH loop above.
    2483           0 :   mPerformance = aOldInner->mPerformance.forget();
    2484             : 
    2485           0 :   if (aOldInner->mIndexedDB) {
    2486           0 :     aOldInner->mIndexedDB->RebindToNewWindow(this);
    2487           0 :     mIndexedDB = aOldInner->mIndexedDB.forget();
    2488             :   }
    2489           0 : }
    2490             : 
    2491             : void
    2492           0 : nsGlobalWindowInner::UpdateTopInnerWindow()
    2493             : {
    2494           0 :   if (IsTopInnerWindow() || !mTopInnerWindow) {
    2495             :     return;
    2496             :   }
    2497             : 
    2498           0 :   mTopInnerWindow->UpdateWebSocketCount(-(int32_t)mNumOfOpenWebSockets);
    2499             : }
    2500             : 
    2501             : void
    2502           0 : nsPIDOMWindowInner::AddPeerConnection()
    2503             : {
    2504           0 :   MOZ_ASSERT(NS_IsMainThread());
    2505           0 :   mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections++
    2506           0 :                   : mActivePeerConnections++;
    2507           0 : }
    2508             : 
    2509             : void
    2510           0 : nsPIDOMWindowInner::RemovePeerConnection()
    2511             : {
    2512           0 :   MOZ_ASSERT(NS_IsMainThread());
    2513           0 :   MOZ_ASSERT(mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections
    2514             :                              : mActivePeerConnections);
    2515             : 
    2516           0 :   mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections--
    2517           0 :                   : mActivePeerConnections--;
    2518           0 : }
    2519             : 
    2520             : bool
    2521           0 : nsPIDOMWindowInner::HasActivePeerConnections()
    2522             : {
    2523           0 :   MOZ_ASSERT(NS_IsMainThread());
    2524           0 :   return mTopInnerWindow ? mTopInnerWindow->mActivePeerConnections
    2525           0 :                          : mActivePeerConnections;
    2526             : }
    2527             : 
    2528             : bool
    2529           0 : nsPIDOMWindowInner::IsPlayingAudio()
    2530             : {
    2531           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); i++) {
    2532           0 :     if (mAudioContexts[i]->IsRunning()) {
    2533             :       return true;
    2534             :     }
    2535             :   }
    2536           0 :   RefPtr<AudioChannelService> acs = AudioChannelService::Get();
    2537           0 :   if (!acs) {
    2538             :     return false;
    2539             :   }
    2540           0 :   auto outer = GetOuterWindow();
    2541           0 :   if (!outer) {
    2542             :     // We've been unlinked and are about to die.  Not a good time to pretend to
    2543             :     // be playing audio.
    2544             :     return false;
    2545             :   }
    2546           0 :   return acs->IsWindowActive(outer);
    2547             : }
    2548             : 
    2549             : bool
    2550           0 : nsPIDOMWindowInner::IsDocumentLoaded() const
    2551             : {
    2552           0 :   return mIsDocumentLoaded;
    2553             : }
    2554             : 
    2555             : mozilla::dom::TimeoutManager&
    2556           0 : nsPIDOMWindowInner::TimeoutManager()
    2557             : {
    2558           0 :   return *mTimeoutManager;
    2559             : }
    2560             : 
    2561             : bool
    2562           0 : nsPIDOMWindowInner::IsRunningTimeout()
    2563             : {
    2564           0 :   return TimeoutManager().IsRunningTimeout();
    2565             : }
    2566             : 
    2567             : void
    2568          14 : nsPIDOMWindowInner::TryToCacheTopInnerWindow()
    2569             : {
    2570          14 :   if (mHasTriedToCacheTopInnerWindow) {
    2571             :     return;
    2572             :   }
    2573             : 
    2574          14 :   nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(this);
    2575             : 
    2576          14 :   MOZ_ASSERT(!window->IsDying());
    2577             : 
    2578          14 :   mHasTriedToCacheTopInnerWindow = true;
    2579             : 
    2580          14 :   MOZ_ASSERT(window);
    2581             : 
    2582          42 :   if (nsCOMPtr<nsPIDOMWindowOuter> topOutter = window->GetScriptableTop()) {
    2583           0 :     mTopInnerWindow = topOutter->GetCurrentInnerWindow();
    2584             :   }
    2585             : }
    2586             : 
    2587             : void
    2588           0 : nsPIDOMWindowInner::UpdateActiveIndexedDBTransactionCount(int32_t aDelta)
    2589             : {
    2590           0 :   MOZ_ASSERT(NS_IsMainThread());
    2591             : 
    2592           0 :   if (aDelta == 0) {
    2593             :     return;
    2594             :   }
    2595             : 
    2596           0 :   TabGroup()->IndexedDBTransactionCounter() += aDelta;
    2597             : }
    2598             : 
    2599             : void
    2600           0 : nsPIDOMWindowInner::UpdateActiveIndexedDBDatabaseCount(int32_t aDelta)
    2601             : {
    2602           0 :   MOZ_ASSERT(NS_IsMainThread());
    2603             : 
    2604           0 :   if (aDelta == 0) {
    2605             :     return;
    2606             :   }
    2607             : 
    2608             :   // We count databases but not transactions because only active databases
    2609             :   // could block throttling.
    2610             :   uint32_t& counter = mTopInnerWindow ?
    2611           0 :     mTopInnerWindow->mNumOfIndexedDBDatabases : mNumOfIndexedDBDatabases;
    2612             : 
    2613           0 :   counter+= aDelta;
    2614             : 
    2615           0 :   TabGroup()->IndexedDBDatabaseCounter() += aDelta;
    2616             : }
    2617             : 
    2618             : bool
    2619           0 : nsPIDOMWindowInner::HasActiveIndexedDBDatabases()
    2620             : {
    2621           0 :   MOZ_ASSERT(NS_IsMainThread());
    2622             : 
    2623           0 :   return mTopInnerWindow ?
    2624           0 :     mTopInnerWindow->mNumOfIndexedDBDatabases > 0 :
    2625           0 :     mNumOfIndexedDBDatabases > 0;
    2626             : }
    2627             : 
    2628             : void
    2629           0 : nsPIDOMWindowInner::UpdateWebSocketCount(int32_t aDelta)
    2630             : {
    2631           0 :   MOZ_ASSERT(NS_IsMainThread());
    2632             : 
    2633           0 :   if (aDelta == 0) {
    2634             :     return;
    2635             :   }
    2636             : 
    2637           0 :   if (mTopInnerWindow && !IsTopInnerWindow()) {
    2638           0 :     mTopInnerWindow->UpdateWebSocketCount(aDelta);
    2639             :   }
    2640             : 
    2641           0 :   MOZ_DIAGNOSTIC_ASSERT(
    2642             :     aDelta > 0 || ((aDelta + mNumOfOpenWebSockets) < mNumOfOpenWebSockets));
    2643             : 
    2644           0 :   mNumOfOpenWebSockets += aDelta;
    2645             : }
    2646             : 
    2647             : bool
    2648           0 : nsPIDOMWindowInner::HasOpenWebSockets() const
    2649             : {
    2650           0 :   MOZ_ASSERT(NS_IsMainThread());
    2651             : 
    2652           0 :   return mNumOfOpenWebSockets ||
    2653           0 :          (mTopInnerWindow && mTopInnerWindow->mNumOfOpenWebSockets);
    2654             : }
    2655             : 
    2656             : bool
    2657           0 : nsPIDOMWindowInner::GetAudioCaptured() const
    2658             : {
    2659           0 :   return mAudioCaptured;
    2660             : }
    2661             : 
    2662             : nsresult
    2663           0 : nsPIDOMWindowInner::SetAudioCapture(bool aCapture)
    2664             : {
    2665           0 :   mAudioCaptured = aCapture;
    2666             : 
    2667           0 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
    2668           0 :   if (service) {
    2669           0 :     service->SetWindowAudioCaptured(GetOuterWindow(), mWindowID, aCapture);
    2670             :   }
    2671             : 
    2672           0 :   return NS_OK;
    2673             : }
    2674             : 
    2675             : // nsISpeechSynthesisGetter
    2676             : 
    2677             : #ifdef MOZ_WEBSPEECH
    2678             : SpeechSynthesis*
    2679           0 : nsGlobalWindowInner::GetSpeechSynthesis(ErrorResult& aError)
    2680             : {
    2681           0 :   if (!mSpeechSynthesis) {
    2682           0 :     mSpeechSynthesis = new SpeechSynthesis(this);
    2683             :   }
    2684             : 
    2685           0 :   return mSpeechSynthesis;
    2686             : }
    2687             : 
    2688             : bool
    2689           0 : nsGlobalWindowInner::HasActiveSpeechSynthesis()
    2690             : {
    2691           0 :   if (mSpeechSynthesis) {
    2692           0 :     return !mSpeechSynthesis->HasEmptyQueue();
    2693             :   }
    2694             : 
    2695             :   return false;
    2696             : }
    2697             : 
    2698             : #endif
    2699             : 
    2700             : already_AddRefed<nsPIDOMWindowOuter>
    2701           2 : nsGlobalWindowInner::GetParent(ErrorResult& aError)
    2702             : {
    2703           2 :   FORWARD_TO_OUTER_OR_THROW(GetParentOuter, (), aError, nullptr);
    2704             : }
    2705             : 
    2706             : /**
    2707             :  * GetScriptableParent is called when script reads window.parent.
    2708             :  *
    2709             :  * In contrast to GetRealParent, GetScriptableParent respects <iframe
    2710             :  * mozbrowser> boundaries, so if |this| is contained by an <iframe
    2711             :  * mozbrowser>, we will return |this| as its own parent.
    2712             :  */
    2713             : nsPIDOMWindowOuter*
    2714           0 : nsGlobalWindowInner::GetScriptableParent()
    2715             : {
    2716           0 :   FORWARD_TO_OUTER(GetScriptableParent, (), nullptr);
    2717             : }
    2718             : 
    2719             : /**
    2720             :  * Behavies identically to GetScriptableParent extept that it returns null
    2721             :  * if GetScriptableParent would return this window.
    2722             :  */
    2723             : nsPIDOMWindowOuter*
    2724           0 : nsGlobalWindowInner::GetScriptableParentOrNull()
    2725             : {
    2726           0 :   FORWARD_TO_OUTER(GetScriptableParentOrNull, (), nullptr);
    2727             : }
    2728             : 
    2729             : /**
    2730             :  * GetScriptableTop is called when script reads window.top.
    2731             :  *
    2732             :  * In contrast to GetRealTop, GetScriptableTop respects <iframe mozbrowser>
    2733             :  * boundaries.  If we encounter a window owned by an <iframe mozbrowser> while
    2734             :  * walking up the window hierarchy, we'll stop and return that window.
    2735             :  */
    2736             : nsPIDOMWindowOuter*
    2737          24 : nsGlobalWindowInner::GetScriptableTop()
    2738             : {
    2739          24 :   FORWARD_TO_OUTER(GetScriptableTop, (), nullptr);
    2740             : }
    2741             : 
    2742             : void
    2743           0 : nsGlobalWindowInner::GetContent(JSContext* aCx,
    2744             :                                 JS::MutableHandle<JSObject*> aRetval,
    2745             :                                 CallerType aCallerType,
    2746             :                                 ErrorResult& aError)
    2747             : {
    2748           0 :   FORWARD_TO_OUTER_OR_THROW(GetContentOuter,
    2749             :                             (aCx, aRetval, aCallerType, aError), aError, );
    2750             : }
    2751             : 
    2752             : BarProp*
    2753           0 : nsGlobalWindowInner::GetMenubar(ErrorResult& aError)
    2754             : {
    2755           0 :   if (!mMenubar) {
    2756           0 :     mMenubar = new MenubarProp(this);
    2757             :   }
    2758             : 
    2759           0 :   return mMenubar;
    2760             : }
    2761             : 
    2762             : BarProp*
    2763           3 : nsGlobalWindowInner::GetToolbar(ErrorResult& aError)
    2764             : {
    2765           6 :   if (!mToolbar) {
    2766           0 :     mToolbar = new ToolbarProp(this);
    2767             :   }
    2768             : 
    2769           6 :   return mToolbar;
    2770             : }
    2771             : 
    2772             : BarProp*
    2773           0 : nsGlobalWindowInner::GetLocationbar(ErrorResult& aError)
    2774             : {
    2775           0 :   if (!mLocationbar) {
    2776           0 :     mLocationbar = new LocationbarProp(this);
    2777             :   }
    2778           0 :   return mLocationbar;
    2779             : }
    2780             : 
    2781             : BarProp*
    2782           0 : nsGlobalWindowInner::GetPersonalbar(ErrorResult& aError)
    2783             : {
    2784           0 :   if (!mPersonalbar) {
    2785           0 :     mPersonalbar = new PersonalbarProp(this);
    2786             :   }
    2787           0 :   return mPersonalbar;
    2788             : }
    2789             : 
    2790             : BarProp*
    2791           0 : nsGlobalWindowInner::GetStatusbar(ErrorResult& aError)
    2792             : {
    2793           0 :   if (!mStatusbar) {
    2794           0 :     mStatusbar = new StatusbarProp(this);
    2795             :   }
    2796           0 :   return mStatusbar;
    2797             : }
    2798             : 
    2799             : BarProp*
    2800           0 : nsGlobalWindowInner::GetScrollbars(ErrorResult& aError)
    2801             : {
    2802           0 :   if (!mScrollbars) {
    2803           0 :     mScrollbars = new ScrollbarsProp(this);
    2804             :   }
    2805             : 
    2806           0 :   return mScrollbars;
    2807             : }
    2808             : 
    2809             : bool
    2810           8 : nsGlobalWindowInner::GetClosed(ErrorResult& aError)
    2811             : {
    2812           8 :   FORWARD_TO_OUTER_OR_THROW(GetClosedOuter, (), aError, false);
    2813             : }
    2814             : 
    2815             : nsDOMWindowList*
    2816           0 : nsGlobalWindowInner::GetFrames()
    2817             : {
    2818           0 :   FORWARD_TO_OUTER(GetFrames, (), nullptr);
    2819             : }
    2820             : 
    2821             : already_AddRefed<nsPIDOMWindowOuter>
    2822           0 : nsGlobalWindowInner::IndexedGetter(uint32_t aIndex)
    2823             : {
    2824           0 :   FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr);
    2825             : }
    2826             : 
    2827             : namespace {
    2828             : 
    2829             : struct InterfaceShimEntry {
    2830             :   const char *geckoName;
    2831             :   const char *domName;
    2832             : };
    2833             : 
    2834             : } // anonymous namespace
    2835             : 
    2836             : // We add shims from Components.interfaces.nsIDOMFoo to window.Foo for each
    2837             : // interface that has interface constants that sites might be getting off
    2838             : // of Ci.
    2839             : const InterfaceShimEntry kInterfaceShimMap[] =
    2840             : { { "nsIXMLHttpRequest", "XMLHttpRequest" },
    2841             :   { "nsIDOMDOMException", "DOMException" },
    2842             :   { "nsIDOMNode", "Node" },
    2843             :   { "nsIDOMCSSRule", "CSSRule" },
    2844             :   { "nsIDOMEvent", "Event" },
    2845             :   { "nsIDOMNSEvent", "Event" },
    2846             :   { "nsIDOMKeyEvent", "KeyEvent" },
    2847             :   { "nsIDOMMouseEvent", "MouseEvent" },
    2848             :   { "nsIDOMMouseScrollEvent", "MouseScrollEvent" },
    2849             :   { "nsIDOMMutationEvent", "MutationEvent" },
    2850             :   { "nsIDOMUIEvent", "UIEvent" },
    2851             :   { "nsIDOMHTMLMediaElement", "HTMLMediaElement" },
    2852             :   { "nsIDOMRange", "Range" },
    2853             :   { "nsIDOMSVGLength", "SVGLength" },
    2854             :   // Think about whether Ci.nsINodeFilter can just go away for websites!
    2855             :   { "nsIDOMNodeFilter", "NodeFilter" },
    2856             :   { "nsIDOMXPathResult", "XPathResult" } };
    2857             : 
    2858             : bool
    2859           0 : nsGlobalWindowInner::ResolveComponentsShim(
    2860             :   JSContext *aCx,
    2861             :   JS::Handle<JSObject*> aGlobal,
    2862             :   JS::MutableHandle<JS::PropertyDescriptor> aDesc)
    2863             : {
    2864             :   // Keep track of how often this happens.
    2865           0 :   Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true);
    2866             : 
    2867             :   // Warn once.
    2868           0 :   nsCOMPtr<nsIDocument> doc = GetExtantDoc();
    2869           0 :   if (doc) {
    2870           0 :     doc->WarnOnceAbout(nsIDocument::eComponents, /* asError = */ true);
    2871             :   }
    2872             : 
    2873             :   // Create a fake Components object.
    2874           0 :   AssertSameCompartment(aCx, aGlobal);
    2875           0 :   JS::Rooted<JSObject*> components(aCx, JS_NewPlainObject(aCx));
    2876           0 :   if (NS_WARN_IF(!components)) {
    2877             :     return false;
    2878             :   }
    2879             : 
    2880             :   // Create a fake interfaces object.
    2881           0 :   JS::Rooted<JSObject*> interfaces(aCx, JS_NewPlainObject(aCx));
    2882           0 :   if (NS_WARN_IF(!interfaces)) {
    2883             :     return false;
    2884             :   }
    2885             :   bool ok =
    2886           0 :     JS_DefineProperty(aCx, components, "interfaces", interfaces,
    2887           0 :                       JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
    2888           0 :   if (NS_WARN_IF(!ok)) {
    2889             :     return false;
    2890             :   }
    2891             : 
    2892             :   // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM
    2893             :   // interfaces with constants.
    2894           0 :   for (uint32_t i = 0; i < ArrayLength(kInterfaceShimMap); ++i) {
    2895             : 
    2896             :     // Grab the names from the table.
    2897           0 :     const char *geckoName = kInterfaceShimMap[i].geckoName;
    2898           0 :     const char *domName = kInterfaceShimMap[i].domName;
    2899             : 
    2900             :     // Look up the appopriate interface object on the global.
    2901           0 :     JS::Rooted<JS::Value> v(aCx, JS::UndefinedValue());
    2902           0 :     ok = JS_GetProperty(aCx, aGlobal, domName, &v);
    2903           0 :     if (NS_WARN_IF(!ok)) {
    2904           0 :       return false;
    2905             :     }
    2906           0 :     if (!v.isObject()) {
    2907           0 :       NS_WARNING("Unable to find interface object on global");
    2908           0 :       continue;
    2909             :     }
    2910             : 
    2911             :     // Define the shim on the interfaces object.
    2912           0 :     ok = JS_DefineProperty(aCx, interfaces, geckoName, v,
    2913           0 :                            JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
    2914           0 :     if (NS_WARN_IF(!ok)) {
    2915             :       return false;
    2916             :     }
    2917             :   }
    2918             : 
    2919           0 :   FillPropertyDescriptor(aDesc, aGlobal, JS::ObjectValue(*components), false);
    2920             : 
    2921           0 :   return true;
    2922             : }
    2923             : 
    2924             : #ifdef RELEASE_OR_BETA
    2925             : #define USE_CONTROLLERS_SHIM
    2926             : #endif
    2927             : 
    2928             : #ifdef USE_CONTROLLERS_SHIM
    2929             : static const JSClass ControllersShimClass = {
    2930             :     "Controllers", 0
    2931             : };
    2932             : static const JSClass XULControllersShimClass = {
    2933             :     "XULControllers", 0
    2934             : };
    2935             : #endif
    2936             : 
    2937             : bool
    2938        4384 : nsGlobalWindowInner::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
    2939             :                                JS::Handle<jsid> aId,
    2940             :                                JS::MutableHandle<JS::PropertyDescriptor> aDesc)
    2941             : {
    2942             :   // Note: Keep this in sync with MayResolve.
    2943             : 
    2944             :   // Note: The infallibleInit call in GlobalResolve depends on this check.
    2945        8768 :   if (!JSID_IS_STRING(aId)) {
    2946             :     return true;
    2947             :   }
    2948             : 
    2949             :   bool found;
    2950        4384 :   if (!WebIDLGlobalNameHash::DefineIfEnabled(aCx, aObj, aId, aDesc, &found)) {
    2951             :     return false;
    2952             :   }
    2953             : 
    2954        4384 :   if (found) {
    2955             :     return true;
    2956             :   }
    2957             : 
    2958             :   // We support a cut-down Components.interfaces in case websites are
    2959             :   // using Components.interfaces.nsIFoo.CONSTANT_NAME for the ones
    2960             :   // that have constants.
    2961             :   static bool watchingComponentsPref = false;
    2962             :   static bool useComponentsShim = false;
    2963        4374 :   if (!watchingComponentsPref) {
    2964           0 :     watchingComponentsPref = true;
    2965             :     Preferences::AddBoolVarCache(&useComponentsShim, "dom.use_components_shim",
    2966           1 :                                  true);
    2967             :   }
    2968        4374 :   if (useComponentsShim &&
    2969           0 :       aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) {
    2970           0 :     return ResolveComponentsShim(aCx, aObj, aDesc);
    2971             :   }
    2972             : 
    2973             :   // We also support a "window.controllers" thing; apparently some
    2974             :   // sites use it for browser-sniffing.  See bug 1010577.
    2975             : #ifdef USE_CONTROLLERS_SHIM
    2976             :   // Note: We use |aObj| rather than |this| to get the principal here, because
    2977             :   // this is called during Window setup when the Document isn't necessarily
    2978             :   // hooked up yet.
    2979             :   if ((aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) ||
    2980             :        aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS_CLASS)) &&
    2981             :       !xpc::IsXrayWrapper(aObj) &&
    2982             :       !nsContentUtils::IsSystemPrincipal(nsContentUtils::ObjectPrincipal(aObj)))
    2983             :   {
    2984             :     if (GetExtantDoc()) {
    2985             :       GetExtantDoc()->WarnOnceAbout(nsIDocument::eWindow_Cc_ontrollers);
    2986             :     }
    2987             :     const JSClass* clazz;
    2988             :     if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS)) {
    2989             :       clazz = &XULControllersShimClass;
    2990             :     } else {
    2991             :       clazz = &ControllersShimClass;
    2992             :     }
    2993             :     MOZ_ASSERT(JS_IsGlobalObject(aObj));
    2994             :     JS::Rooted<JSObject*> shim(aCx, JS_NewObject(aCx, clazz));
    2995             :     if (NS_WARN_IF(!shim)) {
    2996             :       return false;
    2997             :     }
    2998             :     FillPropertyDescriptor(aDesc, aObj, JS::ObjectValue(*shim),
    2999             :                            /* readOnly = */ false);
    3000             :     return true;
    3001             :   }
    3002             : #endif
    3003             : 
    3004             :   return true;
    3005             : }
    3006             : 
    3007             : /* static */
    3008             : bool
    3009          10 : nsGlobalWindowInner::MayResolve(jsid aId)
    3010             : {
    3011             :   // Note: This function does not fail and may not have any side-effects.
    3012             :   // Note: Keep this in sync with DoResolve.
    3013          10 :   if (!JSID_IS_STRING(aId)) {
    3014             :     return false;
    3015             :   }
    3016             : 
    3017          20 :   if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) {
    3018             :     return true;
    3019             :   }
    3020             : 
    3021          40 :   if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) ||
    3022           0 :       aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS_CLASS)) {
    3023             :     // We only resolve .controllers/.Controllers in release builds and on non-chrome
    3024             :     // windows, but let's not worry about any of that stuff.
    3025             :     return true;
    3026             :   }
    3027             : 
    3028          10 :   return WebIDLGlobalNameHash::MayResolve(aId);
    3029             : }
    3030             : 
    3031             : void
    3032           0 : nsGlobalWindowInner::GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
    3033             :                                          bool aEnumerableOnly, ErrorResult& aRv)
    3034             : {
    3035           0 :   if (aEnumerableOnly) {
    3036             :     // The names we would return from here get defined on the window via one of
    3037             :     // two codepaths.  The ones coming from the WebIDLGlobalNameHash will end up
    3038             :     // in the DefineConstructor function in BindingUtils, which always defines
    3039             :     // things as non-enumerable.  The ones coming from the script namespace
    3040             :     // manager get defined by our resolve hook using FillPropertyDescriptor with
    3041             :     // 0 for the property attributes, so non-enumerable as well.
    3042             :     //
    3043             :     // So in the aEnumerableOnly case we have nothing to do.
    3044           0 :     return;
    3045             :   }
    3046             : 
    3047             :   // "Components" is marked as enumerable but only resolved on demand :-/.
    3048             :   //aNames.AppendElement(NS_LITERAL_STRING("Components"));
    3049             : 
    3050           0 :   JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
    3051             : 
    3052             :   // There are actually two ways we can get called here: For normal
    3053             :   // enumeration or for Xray enumeration.  In the latter case, we want to
    3054             :   // return all possible WebIDL names, because we don't really support
    3055             :   // deleting these names off our Xray; trying to resolve them will just make
    3056             :   // them come back.  In the former case, we want to avoid returning deleted
    3057             :   // names.  But the JS engine already knows about the non-deleted
    3058             :   // already-resolved names, so we can just return the so-far-unresolved ones.
    3059             :   //
    3060             :   // We can tell which case we're in by whether aCx is in our wrapper's
    3061             :   // compartment.  If not, we're in the Xray case.
    3062             :   WebIDLGlobalNameHash::NameType nameType =
    3063           0 :     js::IsObjectInContextCompartment(wrapper, aCx) ?
    3064             :       WebIDLGlobalNameHash::UnresolvedNamesOnly :
    3065           0 :       WebIDLGlobalNameHash::AllNames;
    3066           0 :   if (!WebIDLGlobalNameHash::GetNames(aCx, wrapper, nameType, aNames)) {
    3067           0 :     aRv.NoteJSContextException(aCx);
    3068             :   }
    3069             : }
    3070             : 
    3071             : /* static */ bool
    3072          56 : nsGlobalWindowInner::IsPrivilegedChromeWindow(JSContext* aCx, JSObject* aObj)
    3073             : {
    3074             :   // For now, have to deal with XPConnect objects here.
    3075         148 :   return xpc::WindowOrNull(aObj)->IsChromeWindow() &&
    3076           0 :          nsContentUtils::ObjectPrincipal(aObj) == nsContentUtils::GetSystemPrincipal();
    3077             : }
    3078             : 
    3079             : /* static */ bool
    3080          14 : nsGlobalWindowInner::OfflineCacheAllowedForContext(JSContext* aCx, JSObject* aObj)
    3081             : {
    3082          18 :   return IsSecureContextOrObjectIsFromSecureContext(aCx, aObj) ||
    3083           0 :          Preferences::GetBool("browser.cache.offline.insecure.enable");
    3084             : }
    3085             : 
    3086             : /* static */ bool
    3087          15 : nsGlobalWindowInner::IsRequestIdleCallbackEnabled(JSContext* aCx, JSObject* aObj)
    3088             : {
    3089             :   // The requestIdleCallback should always be enabled for system code.
    3090          15 :   return nsContentUtils::RequestIdleCallbackEnabled() ||
    3091           0 :          nsContentUtils::IsSystemCaller(aCx);
    3092             : }
    3093             : 
    3094             : /* static */ bool
    3095           0 : nsGlobalWindowInner::RegisterProtocolHandlerAllowedForContext(JSContext* aCx, JSObject* aObj)
    3096             : {
    3097           0 :   return IsSecureContextOrObjectIsFromSecureContext(aCx, aObj) ||
    3098           0 :          Preferences::GetBool("dom.registerProtocolHandler.insecure.enabled");
    3099             : }
    3100             : 
    3101             : /* static */ bool
    3102           0 : nsGlobalWindowInner::DeviceSensorsEnabled(JSContext* aCx, JSObject* aObj)
    3103             : {
    3104           0 :   return Preferences::GetBool("device.sensors.enabled");
    3105             : }
    3106             : 
    3107             : nsIDOMOfflineResourceList*
    3108           0 : nsGlobalWindowInner::GetApplicationCache(ErrorResult& aError)
    3109             : {
    3110           0 :   if (!mApplicationCache) {
    3111           0 :     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(GetDocShell()));
    3112           0 :     if (!webNav || !mDoc) {
    3113           0 :       aError.Throw(NS_ERROR_FAILURE);
    3114           0 :       return nullptr;
    3115             :     }
    3116             : 
    3117           0 :     nsCOMPtr<nsIURI> uri;
    3118           0 :     aError = webNav->GetCurrentURI(getter_AddRefs(uri));
    3119           0 :     if (aError.Failed()) {
    3120           0 :       return nullptr;
    3121             :     }
    3122             : 
    3123           0 :     nsCOMPtr<nsIURI> manifestURI;
    3124           0 :     nsContentUtils::GetOfflineAppManifest(mDoc, getter_AddRefs(manifestURI));
    3125             : 
    3126             :     RefPtr<nsDOMOfflineResourceList> applicationCache =
    3127           0 :       new nsDOMOfflineResourceList(manifestURI, uri, mDoc->NodePrincipal(),
    3128           0 :                                    this);
    3129             : 
    3130           0 :     applicationCache->Init();
    3131             : 
    3132           0 :     mApplicationCache = applicationCache;
    3133             :   }
    3134             : 
    3135           0 :   return mApplicationCache;
    3136             : }
    3137             : 
    3138             : already_AddRefed<nsIDOMOfflineResourceList>
    3139           0 : nsGlobalWindowInner::GetApplicationCache()
    3140             : {
    3141           0 :   ErrorResult dummy;
    3142             :   nsCOMPtr<nsIDOMOfflineResourceList> applicationCache =
    3143           0 :     GetApplicationCache(dummy);
    3144           0 :   dummy.SuppressException();
    3145           0 :   return applicationCache.forget();
    3146             : }
    3147             : 
    3148             : Crypto*
    3149           0 : nsGlobalWindowInner::GetCrypto(ErrorResult& aError)
    3150             : {
    3151           0 :   if (!mCrypto) {
    3152           0 :     mCrypto = new Crypto(this);
    3153             :   }
    3154           0 :   return mCrypto;
    3155             : }
    3156             : 
    3157             : mozilla::dom::U2F*
    3158           0 : nsGlobalWindowInner::GetU2f(ErrorResult& aError)
    3159             : {
    3160           0 :   if (!mU2F) {
    3161           0 :     RefPtr<U2F> u2f = new U2F(this);
    3162           0 :     u2f->Init(aError);
    3163           0 :     if (NS_WARN_IF(aError.Failed())) {
    3164           0 :       return nullptr;
    3165             :     }
    3166             : 
    3167           0 :     mU2F = u2f;
    3168             :   }
    3169           0 :   return mU2F;
    3170             : }
    3171             : 
    3172             : nsIControllers*
    3173           1 : nsGlobalWindowInner::GetControllers(ErrorResult& aError)
    3174             : {
    3175           1 :   FORWARD_TO_OUTER_OR_THROW(GetControllersOuter, (aError), aError, nullptr);
    3176             : }
    3177             : 
    3178             : nsresult
    3179           1 : nsGlobalWindowInner::GetControllers(nsIControllers** aResult)
    3180             : {
    3181           2 :   ErrorResult rv;
    3182           0 :   nsCOMPtr<nsIControllers> controllers = GetControllers(rv);
    3183           0 :   controllers.forget(aResult);
    3184             : 
    3185           2 :   return rv.StealNSResult();
    3186             : }
    3187             : 
    3188             : nsPIDOMWindowOuter*
    3189           1 : nsGlobalWindowInner::GetOpenerWindow(ErrorResult& aError)
    3190             : {
    3191           1 :   FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr);
    3192             : }
    3193             : 
    3194             : void
    3195           1 : nsGlobalWindowInner::GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
    3196             :                                ErrorResult& aError)
    3197             : {
    3198           1 :   nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindow(aError);
    3199           0 :   if (aError.Failed() || !opener) {
    3200           0 :     aRetval.setNull();
    3201           0 :     return;
    3202             :   }
    3203             : 
    3204           0 :   aError = nsContentUtils::WrapNative(aCx, opener, aRetval);
    3205             : }
    3206             : 
    3207             : void
    3208           0 : nsGlobalWindowInner::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
    3209             :                                ErrorResult& aError)
    3210             : {
    3211             :   // Check if we were called from a privileged chrome script.  If not, and if
    3212             :   // aOpener is not null, just define aOpener on our inner window's JS object,
    3213             :   // wrapped into the current compartment so that for Xrays we define on the
    3214             :   // Xray expando object, but don't set it on the outer window, so that it'll
    3215             :   // get reset on navigation.  This is just like replaceable properties, but
    3216             :   // we're not quite readonly.
    3217           0 :   if (!aOpener.isNull() && !nsContentUtils::IsCallerChrome()) {
    3218           0 :     RedefineProperty(aCx, "opener", aOpener, aError);
    3219           0 :     return;
    3220             :   }
    3221             : 
    3222           0 :   if (!aOpener.isObjectOrNull()) {
    3223             :     // Chrome code trying to set some random value as opener
    3224           0 :     aError.Throw(NS_ERROR_INVALID_ARG);
    3225           0 :     return;
    3226             :   }
    3227             : 
    3228           0 :   nsPIDOMWindowInner* win = nullptr;
    3229           0 :   if (aOpener.isObject()) {
    3230           0 :     JSObject* unwrapped = js::CheckedUnwrap(&aOpener.toObject(),
    3231           0 :                                             /* stopAtWindowProxy = */ false);
    3232           0 :     if (!unwrapped) {
    3233           0 :       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
    3234           0 :       return;
    3235             :     }
    3236             : 
    3237           0 :     auto* globalWindow = xpc::WindowOrNull(unwrapped);
    3238           0 :     if (!globalWindow) {
    3239             :       // Wasn't a window
    3240           0 :       aError.Throw(NS_ERROR_INVALID_ARG);
    3241           0 :       return;
    3242             :     }
    3243             : 
    3244           0 :     win = globalWindow;
    3245             :   }
    3246             : 
    3247           0 :   nsPIDOMWindowOuter* outer = nullptr;
    3248           0 :   if (win) {
    3249           0 :     if (!win->IsCurrentInnerWindow()) {
    3250           0 :       aError.Throw(NS_ERROR_FAILURE);
    3251           0 :       return;
    3252             :     }
    3253           0 :     outer = win->GetOuterWindow();
    3254             :   }
    3255             : 
    3256           0 :   SetOpenerWindow(outer, false);
    3257             : }
    3258             : 
    3259             : void
    3260           0 : nsGlobalWindowInner::GetStatus(nsAString& aStatus, ErrorResult& aError)
    3261             : {
    3262           0 :   FORWARD_TO_OUTER_OR_THROW(GetStatusOuter, (aStatus), aError, );
    3263             : }
    3264             : 
    3265             : void
    3266           0 : nsGlobalWindowInner::SetStatus(const nsAString& aStatus, ErrorResult& aError)
    3267             : {
    3268           0 :   FORWARD_TO_OUTER_OR_THROW(SetStatusOuter, (aStatus), aError, );
    3269             : }
    3270             : 
    3271             : void
    3272           0 : nsGlobalWindowInner::GetName(nsAString& aName, ErrorResult& aError)
    3273             : {
    3274           0 :   FORWARD_TO_OUTER_OR_THROW(GetNameOuter, (aName), aError, );
    3275             : }
    3276             : 
    3277             : void
    3278           0 : nsGlobalWindowInner::SetName(const nsAString& aName, mozilla::ErrorResult& aError)
    3279             : {
    3280           0 :   FORWARD_TO_OUTER_OR_THROW(SetNameOuter, (aName, aError), aError, );
    3281             : }
    3282             : 
    3283             : int32_t
    3284           0 : nsGlobalWindowInner::GetInnerWidth(CallerType aCallerType, ErrorResult& aError)
    3285             : {
    3286             :   // We ignore aCallerType; we only have that argument because some other things
    3287             :   // called by GetReplaceableWindowCoord need it.  If this ever changes, fix
    3288             :   //   nsresult nsGlobalWindowInner::GetInnerWidth(int32_t* aInnerWidth)
    3289             :   // to actually take a useful CallerType and pass it in here.
    3290           0 :   FORWARD_TO_OUTER_OR_THROW(GetInnerWidthOuter, (aError), aError, 0);
    3291             : }
    3292             : 
    3293             : void
    3294           0 : nsGlobalWindowInner::GetInnerWidth(JSContext* aCx,
    3295             :                                    JS::MutableHandle<JS::Value> aValue,
    3296             :                                    CallerType aCallerType,
    3297             :                                    ErrorResult& aError)
    3298             : {
    3299             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetInnerWidth, aValue,
    3300           0 :                             aCallerType, aError);
    3301           0 : }
    3302             : 
    3303             : nsresult
    3304           0 : nsGlobalWindowInner::GetInnerWidth(int32_t* aInnerWidth)
    3305             : {
    3306           0 :   ErrorResult rv;
    3307             :   // Callee doesn't care about the caller type, but play it safe.
    3308           0 :   *aInnerWidth = GetInnerWidth(CallerType::NonSystem, rv);
    3309             : 
    3310           0 :   return rv.StealNSResult();
    3311             : }
    3312             : 
    3313             : void
    3314           0 : nsGlobalWindowInner::SetInnerWidth(int32_t aInnerWidth, CallerType aCallerType,
    3315             :                                    ErrorResult& aError)
    3316             : {
    3317           0 :   FORWARD_TO_OUTER_OR_THROW(SetInnerWidthOuter,
    3318             :                             (aInnerWidth, aCallerType, aError), aError, );
    3319             : }
    3320             : 
    3321             : void
    3322           0 : nsGlobalWindowInner::SetInnerWidth(JSContext* aCx, JS::Handle<JS::Value> aValue,
    3323             :                                    CallerType aCallerType,
    3324             :                                    ErrorResult& aError)
    3325             : {
    3326             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetInnerWidth,
    3327           0 :                             aValue, "innerWidth", aCallerType, aError);
    3328           0 : }
    3329             : 
    3330             : int32_t
    3331           0 : nsGlobalWindowInner::GetInnerHeight(CallerType aCallerType, ErrorResult& aError)
    3332             : {
    3333             :   // We ignore aCallerType; we only have that argument because some other things
    3334             :   // called by GetReplaceableWindowCoord need it.  If this ever changes, fix
    3335             :   //   nsresult nsGlobalWindowInner::GetInnerHeight(int32_t* aInnerWidth)
    3336             :   // to actually take a useful CallerType and pass it in here.
    3337           0 :   FORWARD_TO_OUTER_OR_THROW(GetInnerHeightOuter, (aError), aError, 0);
    3338             : }
    3339             : 
    3340             : void
    3341           0 : nsGlobalWindowInner::GetInnerHeight(JSContext* aCx,
    3342             :                                     JS::MutableHandle<JS::Value> aValue,
    3343             :                                     CallerType aCallerType,
    3344             :                                     ErrorResult& aError)
    3345             : {
    3346             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetInnerHeight, aValue,
    3347           0 :                             aCallerType, aError);
    3348           0 : }
    3349             : 
    3350             : nsresult
    3351           0 : nsGlobalWindowInner::GetInnerHeight(int32_t* aInnerHeight)
    3352             : {
    3353           0 :   ErrorResult rv;
    3354             :   // Callee doesn't care about the caller type, but play it safe.
    3355           0 :   *aInnerHeight = GetInnerHeight(CallerType::NonSystem, rv);
    3356             : 
    3357           0 :   return rv.StealNSResult();
    3358             : }
    3359             : 
    3360             : void
    3361           0 : nsGlobalWindowInner::SetInnerHeight(int32_t aInnerHeight,
    3362             :                                     CallerType aCallerType,
    3363             :                                     ErrorResult& aError)
    3364             : {
    3365           0 :   FORWARD_TO_OUTER_OR_THROW(SetInnerHeightOuter,
    3366             :                             (aInnerHeight, aCallerType, aError), aError, );
    3367             : }
    3368             : 
    3369             : void
    3370           0 : nsGlobalWindowInner::SetInnerHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
    3371             :                                     CallerType aCallerType, ErrorResult& aError)
    3372             : {
    3373             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetInnerHeight,
    3374           0 :                             aValue, "innerHeight", aCallerType, aError);
    3375           0 : }
    3376             : 
    3377             : int32_t
    3378           0 : nsGlobalWindowInner::GetOuterWidth(CallerType aCallerType, ErrorResult& aError)
    3379             : {
    3380           0 :   FORWARD_TO_OUTER_OR_THROW(GetOuterWidthOuter, (aCallerType, aError),
    3381             :                             aError, 0);
    3382             : }
    3383             : 
    3384             : void
    3385           0 : nsGlobalWindowInner::GetOuterWidth(JSContext* aCx,
    3386             :                                    JS::MutableHandle<JS::Value> aValue,
    3387             :                                    CallerType aCallerType,
    3388             :                                    ErrorResult& aError)
    3389             : {
    3390             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetOuterWidth, aValue,
    3391           0 :                             aCallerType, aError);
    3392           0 : }
    3393             : 
    3394             : int32_t
    3395           0 : nsGlobalWindowInner::GetOuterHeight(CallerType aCallerType, ErrorResult& aError)
    3396             : {
    3397           0 :   FORWARD_TO_OUTER_OR_THROW(GetOuterHeightOuter, (aCallerType, aError),
    3398             :                             aError, 0);
    3399             : }
    3400             : 
    3401             : void
    3402           0 : nsGlobalWindowInner::GetOuterHeight(JSContext* aCx,
    3403             :                                     JS::MutableHandle<JS::Value> aValue,
    3404             :                                     CallerType aCallerType,
    3405             :                                     ErrorResult& aError)
    3406             : {
    3407             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetOuterHeight, aValue,
    3408           0 :                             aCallerType, aError);
    3409           0 : }
    3410             : 
    3411             : void
    3412           0 : nsGlobalWindowInner::SetOuterWidth(int32_t aOuterWidth,
    3413             :                                    CallerType aCallerType,
    3414             :                                    ErrorResult& aError)
    3415             : {
    3416           0 :   FORWARD_TO_OUTER_OR_THROW(SetOuterWidthOuter,
    3417             :                             (aOuterWidth, aCallerType, aError), aError, );
    3418             : }
    3419             : 
    3420             : void
    3421           0 : nsGlobalWindowInner::SetOuterWidth(JSContext* aCx, JS::Handle<JS::Value> aValue,
    3422             :                                    CallerType aCallerType,
    3423             :                                    ErrorResult& aError)
    3424             : {
    3425             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetOuterWidth,
    3426           0 :                             aValue, "outerWidth", aCallerType, aError);
    3427           0 : }
    3428             : 
    3429             : void
    3430           0 : nsGlobalWindowInner::SetOuterHeight(int32_t aOuterHeight,
    3431             :                                     CallerType aCallerType,
    3432             :                                     ErrorResult& aError)
    3433             : {
    3434           0 :   FORWARD_TO_OUTER_OR_THROW(SetOuterHeightOuter,
    3435             :                             (aOuterHeight, aCallerType, aError), aError, );
    3436             : }
    3437             : 
    3438             : void
    3439           0 : nsGlobalWindowInner::SetOuterHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
    3440             :                                     CallerType aCallerType,
    3441             :                                     ErrorResult& aError)
    3442             : {
    3443             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetOuterHeight,
    3444           0 :                             aValue, "outerHeight", aCallerType, aError);
    3445           0 : }
    3446             : 
    3447             : int32_t
    3448           0 : nsGlobalWindowInner::GetScreenX(CallerType aCallerType, ErrorResult& aError)
    3449             : {
    3450           0 :   FORWARD_TO_OUTER_OR_THROW(GetScreenXOuter, (aCallerType, aError), aError, 0);
    3451             : }
    3452             : 
    3453             : void
    3454           0 : nsGlobalWindowInner::GetScreenX(JSContext* aCx,
    3455             :                                 JS::MutableHandle<JS::Value> aValue,
    3456             :                                 CallerType aCallerType,
    3457             :                                 ErrorResult& aError)
    3458             : {
    3459             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetScreenX, aValue,
    3460           0 :                             aCallerType, aError);
    3461           0 : }
    3462             : 
    3463             : float
    3464           0 : nsGlobalWindowInner::GetMozInnerScreenX(CallerType aCallerType, ErrorResult& aError)
    3465             : {
    3466           0 :   FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenXOuter, (aCallerType), aError, 0);
    3467             : }
    3468             : 
    3469             : float
    3470           0 : nsGlobalWindowInner::GetMozInnerScreenY(CallerType aCallerType, ErrorResult& aError)
    3471             : {
    3472           0 :   FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenYOuter, (aCallerType), aError, 0);
    3473             : }
    3474             : 
    3475             : double
    3476           2 : nsGlobalWindowInner::GetDevicePixelRatio(CallerType aCallerType, ErrorResult& aError)
    3477             : {
    3478           2 :   FORWARD_TO_OUTER_OR_THROW(GetDevicePixelRatioOuter, (aCallerType), aError, 0.0);
    3479             : }
    3480             : 
    3481             : uint64_t
    3482           0 : nsGlobalWindowInner::GetMozPaintCount(ErrorResult& aError)
    3483             : {
    3484           0 :   FORWARD_TO_OUTER_OR_THROW(GetMozPaintCountOuter, (), aError, 0);
    3485             : }
    3486             : 
    3487             : int32_t
    3488           2 : nsGlobalWindowInner::RequestAnimationFrame(FrameRequestCallback& aCallback,
    3489             :                                            ErrorResult& aError)
    3490             : {
    3491           4 :   if (!mDoc) {
    3492             :     return 0;
    3493             :   }
    3494             : 
    3495           2 :   if (GetWrapperPreserveColor()) {
    3496           0 :     js::NotifyAnimationActivity(GetWrapperPreserveColor());
    3497             :   }
    3498             : 
    3499             :   int32_t handle;
    3500           4 :   aError = mDoc->ScheduleFrameRequestCallback(aCallback, &handle);
    3501           0 :   return handle;
    3502             : }
    3503             : 
    3504             : void
    3505           0 : nsGlobalWindowInner::CancelAnimationFrame(int32_t aHandle, ErrorResult& aError)
    3506             : {
    3507           0 :   if (!mDoc) {
    3508             :     return;
    3509             :   }
    3510             : 
    3511           0 :   mDoc->CancelFrameRequestCallback(aHandle);
    3512             : }
    3513             : 
    3514             : already_AddRefed<MediaQueryList>
    3515           3 : nsGlobalWindowInner::MatchMedia(const nsAString& aMediaQueryList,
    3516             :                                 CallerType aCallerType,
    3517             :                                 ErrorResult& aError)
    3518             : {
    3519             :   // FIXME: This whole forward-to-outer and then get a pres
    3520             :   // shell/context off the docshell dance is sort of silly; it'd make
    3521             :   // more sense to forward to the inner, but it's what everyone else
    3522             :   // (GetSelection, GetScrollXY, etc.) does around here.
    3523           3 :   FORWARD_TO_OUTER_OR_THROW(MatchMediaOuter, (aMediaQueryList, aCallerType), aError, nullptr);
    3524             : }
    3525             : 
    3526             : void
    3527           0 : nsGlobalWindowInner::SetScreenX(int32_t aScreenX,
    3528             :                                 CallerType aCallerType,
    3529             :                                 ErrorResult& aError)
    3530             : {
    3531           0 :   FORWARD_TO_OUTER_OR_THROW(SetScreenXOuter,
    3532             :                             (aScreenX, aCallerType, aError), aError, );
    3533             : }
    3534             : 
    3535             : void
    3536           0 : nsGlobalWindowInner::SetScreenX(JSContext* aCx, JS::Handle<JS::Value> aValue,
    3537             :                                 CallerType aCallerType, ErrorResult& aError)
    3538             : {
    3539             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetScreenX,
    3540           0 :                             aValue, "screenX", aCallerType, aError);
    3541           0 : }
    3542             : 
    3543             : int32_t
    3544           0 : nsGlobalWindowInner::GetScreenY(CallerType aCallerType, ErrorResult& aError)
    3545             : {
    3546           0 :   FORWARD_TO_OUTER_OR_THROW(GetScreenYOuter, (aCallerType, aError), aError, 0);
    3547             : }
    3548             : 
    3549             : void
    3550           0 : nsGlobalWindowInner::GetScreenY(JSContext* aCx,
    3551             :                                 JS::MutableHandle<JS::Value> aValue,
    3552             :                                 CallerType aCallerType, ErrorResult& aError)
    3553             : {
    3554             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::GetScreenY, aValue,
    3555           0 :                             aCallerType, aError);
    3556           0 : }
    3557             : 
    3558             : void
    3559           0 : nsGlobalWindowInner::SetScreenY(int32_t aScreenY,
    3560             :                                 CallerType aCallerType,
    3561             :                                 ErrorResult& aError)
    3562             : {
    3563           0 :   FORWARD_TO_OUTER_OR_THROW(SetScreenYOuter,
    3564             :                             (aScreenY, aCallerType, aError), aError, );
    3565             : }
    3566             : 
    3567             : void
    3568           0 : nsGlobalWindowInner::SetScreenY(JSContext* aCx, JS::Handle<JS::Value> aValue,
    3569             :                                 CallerType aCallerType,
    3570             :                                 ErrorResult& aError)
    3571             : {
    3572             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindowInner::SetScreenY,
    3573           0 :                             aValue, "screenY", aCallerType, aError);
    3574           0 : }
    3575             : 
    3576             : int32_t
    3577           0 : nsGlobalWindowInner::GetScrollMinX(ErrorResult& aError)
    3578             : {
    3579           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, 0);
    3580             : }
    3581             : 
    3582             : int32_t
    3583           0 : nsGlobalWindowInner::GetScrollMinY(ErrorResult& aError)
    3584             : {
    3585           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideTop), aError, 0);
    3586             : }
    3587             : 
    3588             : int32_t
    3589           0 : nsGlobalWindowInner::GetScrollMaxX(ErrorResult& aError)
    3590             : {
    3591           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideRight), aError, 0);
    3592             : }
    3593             : 
    3594             : int32_t
    3595           0 : nsGlobalWindowInner::GetScrollMaxY(ErrorResult& aError)
    3596             : {
    3597           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0);
    3598             : }
    3599             : 
    3600             : double
    3601           0 : nsGlobalWindowInner::GetScrollX(ErrorResult& aError)
    3602             : {
    3603           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0);
    3604             : }
    3605             : 
    3606             : double
    3607           0 : nsGlobalWindowInner::GetScrollY(ErrorResult& aError)
    3608             : {
    3609           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0);
    3610             : }
    3611             : 
    3612             : uint32_t
    3613         295 : nsGlobalWindowInner::Length()
    3614             : {
    3615         295 :   FORWARD_TO_OUTER(Length, (), 0);
    3616             : }
    3617             : 
    3618             : already_AddRefed<nsPIDOMWindowOuter>
    3619          11 : nsGlobalWindowInner::GetTop(mozilla::ErrorResult& aError)
    3620             : {
    3621          11 :   FORWARD_TO_OUTER_OR_THROW(GetTopOuter, (), aError, nullptr);
    3622             : }
    3623             : 
    3624             : nsPIDOMWindowOuter*
    3625          21 : nsGlobalWindowInner::GetChildWindow(const nsAString& aName)
    3626             : {
    3627          21 :   if (GetOuterWindowInternal()) {
    3628           0 :     return GetOuterWindowInternal()->GetChildWindow(aName);
    3629             :   }
    3630             :   return nullptr;
    3631             : }
    3632             : 
    3633             : void
    3634           0 : nsGlobalWindowInner::RefreshRealmPrincipal()
    3635             : {
    3636           0 :   JS::SetRealmPrincipals(js::GetNonCCWObjectRealm(GetWrapperPreserveColor()),
    3637           0 :                          nsJSPrincipals::get(mDoc->NodePrincipal()));
    3638           0 : }
    3639             : 
    3640             : already_AddRefed<nsIWidget>
    3641           4 : nsGlobalWindowInner::GetMainWidget()
    3642             : {
    3643           8 :   FORWARD_TO_OUTER(GetMainWidget, (), nullptr);
    3644             : }
    3645             : 
    3646             : nsIWidget*
    3647           0 : nsGlobalWindowInner::GetNearestWidget() const
    3648             : {
    3649           0 :   if (GetOuterWindowInternal()) {
    3650           0 :     return GetOuterWindowInternal()->GetNearestWidget();
    3651             :   }
    3652             :   return nullptr;
    3653             : }
    3654             : 
    3655             : void
    3656           0 : nsGlobalWindowInner::SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError)
    3657             : {
    3658           0 :   FORWARD_TO_OUTER_OR_THROW(SetFullScreenOuter, (aFullScreen, aError), aError, /* void */);
    3659             : }
    3660             : 
    3661             : bool
    3662          10 : nsGlobalWindowInner::GetFullScreen(ErrorResult& aError)
    3663             : {
    3664          10 :   FORWARD_TO_OUTER_OR_THROW(GetFullScreenOuter, (), aError, false);
    3665             : }
    3666             : 
    3667             : bool
    3668           3 : nsGlobalWindowInner::GetFullScreen()
    3669             : {
    3670           6 :   ErrorResult dummy;
    3671           0 :   bool fullscreen = GetFullScreen(dummy);
    3672           0 :   dummy.SuppressException();
    3673           0 :   return fullscreen;
    3674             : }
    3675             : 
    3676             : void
    3677           0 : nsGlobalWindowInner::Dump(const nsAString& aStr)
    3678             : {
    3679           0 :   if (!DOMPrefs::DumpEnabled()) {
    3680             :     return;
    3681             :   }
    3682             : 
    3683           0 :   char *cstr = ToNewUTF8String(aStr);
    3684             : 
    3685             : #if defined(XP_MACOSX)
    3686             :   // have to convert \r to \n so that printing to the console works
    3687             :   char *c = cstr, *cEnd = cstr + strlen(cstr);
    3688             :   while (c < cEnd) {
    3689             :     if (*c == '\r')
    3690             :       *c = '\n';
    3691             :     c++;
    3692             :   }
    3693             : #endif
    3694             : 
    3695           0 :   if (cstr) {
    3696           0 :     MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug, ("[Window.Dump] %s", cstr));
    3697             : #ifdef XP_WIN
    3698             :     PrintToDebugger(cstr);
    3699             : #endif
    3700             : #ifdef ANDROID
    3701             :     __android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
    3702             : #endif
    3703           0 :     FILE *fp = gDumpFile ? gDumpFile : stdout;
    3704           0 :     fputs(cstr, fp);
    3705           0 :     fflush(fp);
    3706           0 :     free(cstr);
    3707             :   }
    3708             : }
    3709             : 
    3710             : void
    3711           0 : nsGlobalWindowInner::Alert(nsIPrincipal& aSubjectPrincipal,
    3712             :                            ErrorResult& aError)
    3713             : {
    3714           0 :   Alert(EmptyString(), aSubjectPrincipal, aError);
    3715           0 : }
    3716             : 
    3717             : void
    3718           0 : nsGlobalWindowInner::Alert(const nsAString& aMessage,
    3719             :                            nsIPrincipal& aSubjectPrincipal,
    3720             :                            ErrorResult& aError)
    3721             : {
    3722           0 :   FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError),
    3723             :                             aError, );
    3724             : }
    3725             : 
    3726             : bool
    3727           0 : nsGlobalWindowInner::Confirm(const nsAString& aMessage,
    3728             :                              nsIPrincipal& aSubjectPrincipal,
    3729             :                              ErrorResult& aError)
    3730             : {
    3731           0 :   FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError),
    3732             :                             aError, false);
    3733             : }
    3734             : 
    3735             : already_AddRefed<Promise>
    3736           0 : nsGlobalWindowInner::Fetch(const RequestOrUSVString& aInput,
    3737             :                            const RequestInit& aInit,
    3738             :                            CallerType aCallerType, ErrorResult& aRv)
    3739             : {
    3740           0 :   return FetchRequest(this, aInput, aInit, aCallerType, aRv);
    3741             : }
    3742             : 
    3743             : void
    3744           0 : nsGlobalWindowInner::Prompt(const nsAString& aMessage, const nsAString& aInitial,
    3745             :                             nsAString& aReturn,
    3746             :                             nsIPrincipal& aSubjectPrincipal,
    3747             :                             ErrorResult& aError)
    3748             : {
    3749           0 :   FORWARD_TO_OUTER_OR_THROW(PromptOuter,
    3750             :                             (aMessage, aInitial, aReturn, aSubjectPrincipal,
    3751             :                              aError),
    3752             :                             aError, );
    3753             : }
    3754             : 
    3755             : void
    3756           0 : nsGlobalWindowInner::Focus(ErrorResult& aError)
    3757             : {
    3758           0 :   FORWARD_TO_OUTER_OR_THROW(FocusOuter, (aError), aError, );
    3759             : }
    3760             : 
    3761             : nsresult
    3762           0 : nsGlobalWindowInner::Focus()
    3763             : {
    3764           0 :   ErrorResult rv;
    3765           0 :   Focus(rv);
    3766             : 
    3767           0 :   return rv.StealNSResult();
    3768             : }
    3769             : 
    3770             : void
    3771           0 : nsGlobalWindowInner::Blur(ErrorResult& aError)
    3772             : {
    3773           0 :   FORWARD_TO_OUTER_OR_THROW(BlurOuter, (), aError, );
    3774             : }
    3775             : 
    3776             : void
    3777           0 : nsGlobalWindowInner::Back(ErrorResult& aError)
    3778             : {
    3779           0 :   FORWARD_TO_OUTER_OR_THROW(BackOuter, (aError), aError, );
    3780             : }
    3781             : 
    3782             : void
    3783           0 : nsGlobalWindowInner::Forward(ErrorResult& aError)
    3784             : {
    3785           0 :   FORWARD_TO_OUTER_OR_THROW(ForwardOuter, (aError), aError, );
    3786             : }
    3787             : 
    3788             : void
    3789           0 : nsGlobalWindowInner::Home(nsIPrincipal& aSubjectPrincipal, ErrorResult& aError)
    3790             : {
    3791           0 :   FORWARD_TO_OUTER_OR_THROW(HomeOuter, (aSubjectPrincipal, aError), aError, );
    3792             : }
    3793             : 
    3794             : void
    3795           0 : nsGlobalWindowInner::Stop(ErrorResult& aError)
    3796             : {
    3797           0 :   FORWARD_TO_OUTER_OR_THROW(StopOuter, (aError), aError, );
    3798             : }
    3799             : 
    3800             : /* static */
    3801             : bool
    3802          14 : nsGlobalWindowInner::IsWindowPrintEnabled(JSContext*, JSObject*)
    3803             : {
    3804             :   static bool called = false;
    3805             :   static bool printDisabled = false;
    3806          14 :   if (!called) {
    3807           0 :     called = true;
    3808           0 :     Preferences::AddBoolVarCache(&printDisabled, "dom.disable_window_print");
    3809             :   }
    3810          14 :   return !printDisabled;
    3811             : }
    3812             : 
    3813             : void
    3814           0 : nsGlobalWindowInner::Print(ErrorResult& aError)
    3815             : {
    3816           0 :   FORWARD_TO_OUTER_OR_THROW(PrintOuter, (aError), aError, );
    3817             : }
    3818             : 
    3819             : void
    3820           0 : nsGlobalWindowInner::MoveTo(int32_t aXPos, int32_t aYPos,
    3821             :                             CallerType aCallerType, ErrorResult& aError)
    3822             : {
    3823           0 :   FORWARD_TO_OUTER_OR_THROW(MoveToOuter,
    3824             :                             (aXPos, aYPos, aCallerType, aError), aError, );
    3825             : }
    3826             : 
    3827             : void
    3828           0 : nsGlobalWindowInner::MoveBy(int32_t aXDif, int32_t aYDif,
    3829             :                             CallerType aCallerType, ErrorResult& aError)
    3830             : {
    3831           0 :   FORWARD_TO_OUTER_OR_THROW(MoveByOuter,
    3832             :                             (aXDif, aYDif, aCallerType, aError), aError, );
    3833             : }
    3834             : 
    3835             : void
    3836           0 : nsGlobalWindowInner::ResizeTo(int32_t aWidth, int32_t aHeight,
    3837             :                               CallerType aCallerType, ErrorResult& aError)
    3838             : {
    3839           0 :   FORWARD_TO_OUTER_OR_THROW(ResizeToOuter,
    3840             :                             (aWidth, aHeight, aCallerType, aError), aError, );
    3841             : }
    3842             : 
    3843             : void
    3844           0 : nsGlobalWindowInner::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
    3845             :                               CallerType aCallerType, ErrorResult& aError)
    3846             : {
    3847           0 :   FORWARD_TO_OUTER_OR_THROW(ResizeByOuter,
    3848             :                             (aWidthDif, aHeightDif, aCallerType, aError),
    3849             :                             aError, );
    3850             : }
    3851             : 
    3852             : void
    3853           0 : nsGlobalWindowInner::SizeToContent(CallerType aCallerType, ErrorResult& aError)
    3854             : {
    3855           0 :   FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, aError),
    3856             :                             aError, );
    3857             : }
    3858             : 
    3859             : already_AddRefed<nsPIWindowRoot>
    3860           0 : nsGlobalWindowInner::GetTopWindowRoot()
    3861             : {
    3862           0 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    3863           0 :   if (!outer) {
    3864             :     return nullptr;
    3865             :   }
    3866           0 :   return outer->GetTopWindowRoot();
    3867             : }
    3868             : 
    3869             : void
    3870           0 : nsGlobalWindowInner::Scroll(double aXScroll, double aYScroll)
    3871             : {
    3872             :   // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
    3873           0 :   auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
    3874           0 :                                          mozilla::ToZeroIfNonfinite(aYScroll));
    3875           0 :   ScrollTo(scrollPos, ScrollOptions());
    3876           0 : }
    3877             : 
    3878             : void
    3879           0 : nsGlobalWindowInner::ScrollTo(double aXScroll, double aYScroll)
    3880             : {
    3881             :   // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
    3882           0 :   auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
    3883           0 :                                          mozilla::ToZeroIfNonfinite(aYScroll));
    3884           0 :   ScrollTo(scrollPos, ScrollOptions());
    3885           0 : }
    3886             : 
    3887             : void
    3888           0 : nsGlobalWindowInner::ScrollTo(const ScrollToOptions& aOptions)
    3889             : {
    3890             :   // When scrolling to a non-zero offset, we need to determine whether that
    3891             :   // position is within our scrollable range, so we need updated layout
    3892             :   // information which requires a layout flush, otherwise all we need is to
    3893             :   // flush frames to be able to access our scrollable frame here.
    3894           0 :   FlushType flushType = ((aOptions.mLeft.WasPassed() &&
    3895           0 :                           aOptions.mLeft.Value() > 0) ||
    3896           0 :                          (aOptions.mTop.WasPassed() &&
    3897           0 :                           aOptions.mTop.Value() > 0)) ?
    3898             :                           FlushType::Layout :
    3899           0 :                           FlushType::Frames;
    3900           0 :   FlushPendingNotifications(flushType);
    3901           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    3902             : 
    3903           0 :   if (sf) {
    3904           0 :     CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
    3905           0 :     if (aOptions.mLeft.WasPassed()) {
    3906           0 :       scrollPos.x = mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
    3907             :     }
    3908           0 :     if (aOptions.mTop.WasPassed()) {
    3909           0 :       scrollPos.y = mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
    3910             :     }
    3911             : 
    3912           0 :     ScrollTo(scrollPos, aOptions);
    3913             :   }
    3914           0 : }
    3915             : 
    3916             : void
    3917           0 : nsGlobalWindowInner::Scroll(const ScrollToOptions& aOptions)
    3918             : {
    3919           0 :   ScrollTo(aOptions);
    3920           0 : }
    3921             : 
    3922             : void
    3923           0 : nsGlobalWindowInner::ScrollTo(const CSSIntPoint& aScroll,
    3924             :                               const ScrollOptions& aOptions)
    3925             : {
    3926             :   // When scrolling to a non-zero offset, we need to determine whether that
    3927             :   // position is within our scrollable range, so we need updated layout
    3928             :   // information which requires a layout flush, otherwise all we need is to
    3929             :   // flush frames to be able to access our scrollable frame here.
    3930           0 :   FlushType flushType = (aScroll.x || aScroll.y) ?
    3931             :                           FlushType::Layout :
    3932           0 :                           FlushType::Frames;
    3933           0 :   FlushPendingNotifications(flushType);
    3934           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    3935             : 
    3936           0 :   if (sf) {
    3937             :     // Here we calculate what the max pixel value is that we can
    3938             :     // scroll to, we do this by dividing maxint with the pixel to
    3939             :     // twips conversion factor, and subtracting 4, the 4 comes from
    3940             :     // experimenting with this value, anything less makes the view
    3941             :     // code not scroll correctly, I have no idea why. -- jst
    3942           0 :     const int32_t maxpx = nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
    3943             : 
    3944           0 :     CSSIntPoint scroll(aScroll);
    3945           0 :     if (scroll.x > maxpx) {
    3946           0 :       scroll.x = maxpx;
    3947             :     }
    3948             : 
    3949           0 :     if (scroll.y > maxpx) {
    3950           0 :       scroll.y = maxpx;
    3951             :     }
    3952             : 
    3953           0 :     bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
    3954             : 
    3955           0 :     sf->ScrollToCSSPixels(scroll, smoothScroll
    3956             :                             ? nsIScrollableFrame::SMOOTH_MSD
    3957           0 :                             : nsIScrollableFrame::INSTANT);
    3958             :   }
    3959           0 : }
    3960             : 
    3961             : void
    3962           0 : nsGlobalWindowInner::ScrollBy(double aXScrollDif, double aYScrollDif)
    3963             : {
    3964           0 :   FlushPendingNotifications(FlushType::Layout);
    3965           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    3966             : 
    3967           0 :   if (sf) {
    3968             :     // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
    3969           0 :     auto scrollDif = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScrollDif),
    3970           0 :                                            mozilla::ToZeroIfNonfinite(aYScrollDif));
    3971             :     // It seems like it would make more sense for ScrollBy to use
    3972             :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    3973             :     // Perhaps Web content does too.
    3974           0 :     ScrollTo(sf->GetScrollPositionCSSPixels() + scrollDif, ScrollOptions());
    3975             :   }
    3976           0 : }
    3977             : 
    3978             : void
    3979           0 : nsGlobalWindowInner::ScrollBy(const ScrollToOptions& aOptions)
    3980             : {
    3981           0 :   FlushPendingNotifications(FlushType::Layout);
    3982           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    3983             : 
    3984           0 :   if (sf) {
    3985           0 :     CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
    3986           0 :     if (aOptions.mLeft.WasPassed()) {
    3987           0 :       scrollPos.x += mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
    3988             :     }
    3989           0 :     if (aOptions.mTop.WasPassed()) {
    3990           0 :       scrollPos.y += mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
    3991             :     }
    3992             : 
    3993           0 :     ScrollTo(scrollPos, aOptions);
    3994             :   }
    3995           0 : }
    3996             : 
    3997             : void
    3998           0 : nsGlobalWindowInner::ScrollByLines(int32_t numLines,
    3999             :                                    const ScrollOptions& aOptions)
    4000             : {
    4001           0 :   FlushPendingNotifications(FlushType::Layout);
    4002           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    4003           0 :   if (sf) {
    4004             :     // It seems like it would make more sense for ScrollByLines to use
    4005             :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    4006             :     // Perhaps Web content does too.
    4007           0 :     bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
    4008             : 
    4009           0 :     sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES,
    4010             :                  smoothScroll
    4011             :                    ? nsIScrollableFrame::SMOOTH_MSD
    4012           0 :                    : nsIScrollableFrame::INSTANT);
    4013             :   }
    4014           0 : }
    4015             : 
    4016             : void
    4017           0 : nsGlobalWindowInner::ScrollByPages(int32_t numPages,
    4018             :                                    const ScrollOptions& aOptions)
    4019             : {
    4020           0 :   FlushPendingNotifications(FlushType::Layout);
    4021           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    4022           0 :   if (sf) {
    4023             :     // It seems like it would make more sense for ScrollByPages to use
    4024             :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    4025             :     // Perhaps Web content does too.
    4026           0 :     bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
    4027             : 
    4028           0 :     sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
    4029             :                  smoothScroll
    4030             :                    ? nsIScrollableFrame::SMOOTH_MSD
    4031           0 :                    : nsIScrollableFrame::INSTANT);
    4032             :   }
    4033           0 : }
    4034             : 
    4035             : void
    4036           0 : nsGlobalWindowInner::MozScrollSnap()
    4037             : {
    4038           0 :   FlushPendingNotifications(FlushType::Layout);
    4039           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    4040           0 :   if (sf) {
    4041           0 :     sf->ScrollSnap();
    4042             :   }
    4043           0 : }
    4044             : 
    4045             : void
    4046           0 : nsGlobalWindowInner::ClearTimeout(int32_t aHandle)
    4047             : {
    4048           0 :   if (aHandle > 0) {
    4049           0 :     mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
    4050             :   }
    4051           0 : }
    4052             : 
    4053             : void
    4054           0 : nsGlobalWindowInner::ClearInterval(int32_t aHandle)
    4055             : {
    4056           0 :   if (aHandle > 0) {
    4057           0 :     mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
    4058             :   }
    4059           0 : }
    4060             : 
    4061             : void
    4062           0 : nsGlobalWindowInner::SetResizable(bool aResizable) const
    4063             : {
    4064             :   // nop
    4065           0 : }
    4066             : 
    4067             : void
    4068           0 : nsGlobalWindowInner::CaptureEvents()
    4069             : {
    4070           0 :   if (mDoc) {
    4071           0 :     mDoc->WarnOnceAbout(nsIDocument::eUseOfCaptureEvents);
    4072             :   }
    4073           0 : }
    4074             : 
    4075             : void
    4076           0 : nsGlobalWindowInner::ReleaseEvents()
    4077             : {
    4078           0 :   if (mDoc) {
    4079           0 :     mDoc->WarnOnceAbout(nsIDocument::eUseOfReleaseEvents);
    4080             :   }
    4081           0 : }
    4082             : 
    4083             : already_AddRefed<nsPIDOMWindowOuter>
    4084           0 : nsGlobalWindowInner::Open(const nsAString& aUrl, const nsAString& aName,
    4085             :                           const nsAString& aOptions, ErrorResult& aError)
    4086             : {
    4087           0 :   FORWARD_TO_OUTER_OR_THROW(OpenOuter, (aUrl, aName, aOptions, aError), aError,
    4088             :                             nullptr);
    4089             : }
    4090             : 
    4091             : already_AddRefed<nsPIDOMWindowOuter>
    4092           0 : nsGlobalWindowInner::OpenDialog(JSContext* aCx, const nsAString& aUrl,
    4093             :                                 const nsAString& aName, const nsAString& aOptions,
    4094             :                                 const Sequence<JS::Value>& aExtraArgument,
    4095             :                                 ErrorResult& aError)
    4096             : {
    4097           0 :   FORWARD_TO_OUTER_OR_THROW(OpenDialogOuter,
    4098             :                             (aCx, aUrl, aName, aOptions, aExtraArgument, aError),
    4099             :                             aError, nullptr);
    4100             : }
    4101             : 
    4102             : already_AddRefed<nsPIDOMWindowOuter>
    4103           0 : nsGlobalWindowInner::GetFrames(ErrorResult& aError)
    4104             : {
    4105           0 :   FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, nullptr);
    4106             : }
    4107             : 
    4108             : nsGlobalWindowInner*
    4109           0 : nsGlobalWindowInner::CallerInnerWindow()
    4110             : {
    4111           0 :   JSContext *cx = nsContentUtils::GetCurrentJSContext();
    4112           0 :   NS_ENSURE_TRUE(cx, nullptr);
    4113           0 :   nsIGlobalObject* global = GetIncumbentGlobal();
    4114           0 :   NS_ENSURE_TRUE(global, nullptr);
    4115           0 :   JS::Rooted<JSObject*> scope(cx, global->GetGlobalJSObject());
    4116           0 :   NS_ENSURE_TRUE(scope, nullptr);
    4117             : 
    4118             :   // When Jetpack runs content scripts inside a sandbox, it uses
    4119             :   // sandboxPrototype to make them appear as though they're running in the
    4120             :   // scope of the page. So when a content script invokes postMessage, it expects
    4121             :   // the |source| of the received message to be the window set as the
    4122             :   // sandboxPrototype. This used to work incidentally for unrelated reasons, but
    4123             :   // now we need to do some special handling to support it.
    4124           0 :   if (xpc::IsSandbox(scope)) {
    4125           0 :     JSAutoRealm ar(cx, scope);
    4126           0 :     JS::Rooted<JSObject*> scopeProto(cx);
    4127           0 :     bool ok = JS_GetPrototype(cx, scope, &scopeProto);
    4128           0 :     NS_ENSURE_TRUE(ok, nullptr);
    4129           0 :     if (scopeProto && xpc::IsSandboxPrototypeProxy(scopeProto) &&
    4130           0 :         (scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtWindowProxy = */ false)))
    4131             :     {
    4132           0 :       global = xpc::NativeGlobal(scopeProto);
    4133           0 :       NS_ENSURE_TRUE(global, nullptr);
    4134             :     }
    4135             :   }
    4136             : 
    4137             :   // The calling window must be holding a reference, so we can return a weak
    4138             :   // pointer.
    4139           0 :   nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
    4140           0 :   return nsGlobalWindowInner::Cast(win);
    4141             : }
    4142             : 
    4143             : void
    4144           0 : nsGlobalWindowInner::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
    4145             :                                     const nsAString& aTargetOrigin,
    4146             :                                     JS::Handle<JS::Value> aTransfer,
    4147             :                                     nsIPrincipal& aSubjectPrincipal,
    4148             :                                     ErrorResult& aError)
    4149             : {
    4150           0 :   FORWARD_TO_OUTER_OR_THROW(PostMessageMozOuter,
    4151             :                             (aCx, aMessage, aTargetOrigin, aTransfer,
    4152             :                              aSubjectPrincipal, aError),
    4153             :                             aError, );
    4154             : }
    4155             : 
    4156             : void
    4157           0 : nsGlobalWindowInner::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
    4158             :                                     const nsAString& aTargetOrigin,
    4159             :                                     const Sequence<JSObject*>& aTransfer,
    4160             :                                     nsIPrincipal& aSubjectPrincipal,
    4161             :                                     ErrorResult& aRv)
    4162             : {
    4163           0 :   JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
    4164             : 
    4165           0 :   aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer,
    4166           0 :                                                           &transferArray);
    4167           0 :   if (NS_WARN_IF(aRv.Failed())) {
    4168           0 :     return;
    4169             :   }
    4170             : 
    4171           0 :   PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray,
    4172           0 :                  aSubjectPrincipal, aRv);
    4173             : }
    4174             : 
    4175             : void
    4176           0 : nsGlobalWindowInner::Close(ErrorResult& aError)
    4177             : {
    4178           0 :   FORWARD_TO_OUTER_OR_THROW(CloseOuter, (nsContentUtils::IsCallerChrome()), aError, );
    4179             : }
    4180             : 
    4181             : nsresult
    4182           0 : nsGlobalWindowInner::Close()
    4183             : {
    4184           0 :   FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
    4185             : }
    4186             : 
    4187             : void
    4188           0 : nsGlobalWindowInner::ReallyCloseWindow()
    4189             : {
    4190           0 :   FORWARD_TO_OUTER_VOID(ReallyCloseWindow, ());
    4191             : }
    4192             : 
    4193             : bool
    4194          20 : nsGlobalWindowInner::IsInModalState()
    4195             : {
    4196          20 :   FORWARD_TO_OUTER(IsInModalState, (), false);
    4197             : }
    4198             : 
    4199             : // static
    4200             : void
    4201           7 : nsGlobalWindowInner::NotifyDOMWindowDestroyed(nsGlobalWindowInner* aWindow)
    4202             : {
    4203             :   nsCOMPtr<nsIObserverService> observerService =
    4204          14 :     services::GetObserverService();
    4205           0 :   if (observerService) {
    4206           0 :     observerService->
    4207           0 :       NotifyObservers(ToSupports(aWindow),
    4208           0 :                       DOM_WINDOW_DESTROYED_TOPIC, nullptr);
    4209             :   }
    4210           7 : }
    4211             : 
    4212             : void
    4213           7 : nsGlobalWindowInner::NotifyWindowIDDestroyed(const char* aTopic)
    4214             : {
    4215             :   nsCOMPtr<nsIRunnable> runnable =
    4216          14 :     new WindowDestroyedEvent(this, mWindowID, aTopic);
    4217           0 :   Dispatch(TaskCategory::Other, runnable.forget());
    4218           0 : }
    4219             : 
    4220             : // static
    4221             : void
    4222           0 : nsGlobalWindowInner::NotifyDOMWindowFrozen(nsGlobalWindowInner* aWindow)
    4223             : {
    4224           0 :   if (aWindow) {
    4225             :     nsCOMPtr<nsIObserverService> observerService =
    4226           0 :       services::GetObserverService();
    4227           0 :     if (observerService) {
    4228           0 :       observerService->
    4229           0 :         NotifyObservers(ToSupports(aWindow),
    4230           0 :                         DOM_WINDOW_FROZEN_TOPIC, nullptr);
    4231             :     }
    4232             :   }
    4233           0 : }
    4234             : 
    4235             : // static
    4236             : void
    4237           0 : nsGlobalWindowInner::NotifyDOMWindowThawed(nsGlobalWindowInner* aWindow)
    4238             : {
    4239           0 :   if (aWindow) {
    4240             :     nsCOMPtr<nsIObserverService> observerService =
    4241           0 :       services::GetObserverService();
    4242           0 :     if (observerService) {
    4243           0 :       observerService->
    4244           0 :         NotifyObservers(ToSupports(aWindow),
    4245           0 :                         DOM_WINDOW_THAWED_TOPIC, nullptr);
    4246             :     }
    4247             :   }
    4248           0 : }
    4249             : 
    4250             : JSObject*
    4251           5 : nsGlobalWindowInner::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey)
    4252             : {
    4253          10 :   JS::Rooted<JSObject*> handler(RootingCx());
    4254           0 :   if (mCachedXBLPrototypeHandlers) {
    4255           0 :     mCachedXBLPrototypeHandlers->Get(aKey, handler.address());
    4256             :   }
    4257          10 :   return handler;
    4258             : }
    4259             : 
    4260             : void
    4261           4 : nsGlobalWindowInner::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
    4262             :                                               JS::Handle<JSObject*> aHandler)
    4263             : {
    4264           8 :   if (!mCachedXBLPrototypeHandlers) {
    4265           0 :     mCachedXBLPrototypeHandlers = MakeUnique<XBLPrototypeHandlerTable>();
    4266           0 :     PreserveWrapper(ToSupports(this));
    4267             :   }
    4268             : 
    4269           4 :   mCachedXBLPrototypeHandlers->Put(aKey, aHandler);
    4270           0 : }
    4271             : 
    4272             : Element*
    4273           0 : nsGlobalWindowInner::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
    4274             :                                      ErrorResult& aError)
    4275             : {
    4276           0 :   FORWARD_TO_OUTER_OR_THROW(GetFrameElementOuter, (aSubjectPrincipal), aError,
    4277             :                             nullptr);
    4278             : }
    4279             : 
    4280             : Element*
    4281           0 : nsGlobalWindowInner::GetRealFrameElement(ErrorResult& aError)
    4282             : {
    4283           0 :   FORWARD_TO_OUTER_OR_THROW(GetRealFrameElementOuter, (), aError, nullptr);
    4284             : }
    4285             : 
    4286             : /**
    4287             :  * nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper
    4288             :  * around GetRealFrameElement.
    4289             :  */
    4290             : Element*
    4291           0 : nsGlobalWindowInner::GetFrameElement()
    4292             : {
    4293           0 :   return GetRealFrameElement(IgnoreErrors());
    4294             : }
    4295             : 
    4296             : /* static */ bool
    4297           0 : nsGlobalWindowInner::TokenizeDialogOptions(nsAString& aToken,
    4298             :                                            nsAString::const_iterator& aIter,
    4299             :                                            nsAString::const_iterator aEnd)
    4300             : {
    4301           0 :   while (aIter != aEnd && nsCRT::IsAsciiSpace(*aIter)) {
    4302             :     ++aIter;
    4303             :   }
    4304             : 
    4305           0 :   if (aIter == aEnd) {
    4306             :     return false;
    4307             :   }
    4308             : 
    4309           0 :   if (*aIter == ';' || *aIter == ':' || *aIter == '=') {
    4310           0 :     aToken.Assign(*aIter);
    4311           0 :     ++aIter;
    4312           0 :     return true;
    4313             :   }
    4314             : 
    4315             :   nsAString::const_iterator start = aIter;
    4316             : 
    4317             :   // Skip characters until we find whitespace, ';', ':', or '='
    4318           0 :   while (aIter != aEnd && !nsCRT::IsAsciiSpace(*aIter) &&
    4319           0 :          *aIter != ';' &&
    4320           0 :          *aIter != ':' &&
    4321           0 :          *aIter != '=') {
    4322             :     ++aIter;
    4323             :   }
    4324             : 
    4325           0 :   aToken.Assign(Substring(start, aIter));
    4326           0 :   return true;
    4327             : }
    4328             : 
    4329             : // Helper for converting window.showModalDialog() options (list of ';'
    4330             : // separated name (:|=) value pairs) to a format that's parsable by
    4331             : // our normal window opening code.
    4332             : 
    4333             : /* static */
    4334             : void
    4335           0 : nsGlobalWindowInner::ConvertDialogOptions(const nsAString& aOptions,
    4336             :                                           nsAString& aResult)
    4337             : {
    4338           0 :   nsAString::const_iterator end;
    4339           0 :   aOptions.EndReading(end);
    4340             : 
    4341           0 :   nsAString::const_iterator iter;
    4342           0 :   aOptions.BeginReading(iter);
    4343             : 
    4344           0 :   nsAutoString token;
    4345           0 :   nsAutoString name;
    4346           0 :   nsAutoString value;
    4347             : 
    4348             :   while (true) {
    4349           0 :     if (!TokenizeDialogOptions(name, iter, end)) {
    4350             :       break;
    4351             :     }
    4352             : 
    4353             :     // Invalid name.
    4354           0 :     if (name.EqualsLiteral("=") ||
    4355           0 :         name.EqualsLiteral(":") ||
    4356           0 :         name.EqualsLiteral(";")) {
    4357             :       break;
    4358             :     }
    4359             : 
    4360           0 :     if (!TokenizeDialogOptions(token, iter, end)) {
    4361             :       break;
    4362             :     }
    4363             : 
    4364           0 :     if (!token.EqualsLiteral(":") && !token.EqualsLiteral("=")) {
    4365             :       continue;
    4366             :     }
    4367             : 
    4368             :     // We found name followed by ':' or '='. Look for a value.
    4369           0 :     if (!TokenizeDialogOptions(value, iter, end)) {
    4370             :       break;
    4371             :     }
    4372             : 
    4373           0 :     if (name.LowerCaseEqualsLiteral("center")) {
    4374           0 :       if (value.LowerCaseEqualsLiteral("on")  ||
    4375           0 :           value.LowerCaseEqualsLiteral("yes") ||
    4376           0 :           value.LowerCaseEqualsLiteral("1")) {
    4377           0 :         aResult.AppendLiteral(",centerscreen=1");
    4378             :       }
    4379           0 :     } else if (name.LowerCaseEqualsLiteral("dialogwidth")) {
    4380           0 :       if (!value.IsEmpty()) {
    4381           0 :         aResult.AppendLiteral(",width=");
    4382           0 :         aResult.Append(value);
    4383             :       }
    4384           0 :     } else if (name.LowerCaseEqualsLiteral("dialogheight")) {
    4385           0 :       if (!value.IsEmpty()) {
    4386           0 :         aResult.AppendLiteral(",height=");
    4387           0 :         aResult.Append(value);
    4388             :       }
    4389           0 :     } else if (name.LowerCaseEqualsLiteral("dialogtop")) {
    4390           0 :       if (!value.IsEmpty()) {
    4391           0 :         aResult.AppendLiteral(",top=");
    4392           0 :         aResult.Append(value);
    4393             :       }
    4394           0 :     } else if (name.LowerCaseEqualsLiteral("dialogleft")) {
    4395           0 :       if (!value.IsEmpty()) {
    4396           0 :         aResult.AppendLiteral(",left=");
    4397           0 :         aResult.Append(value);
    4398             :       }
    4399           0 :     } else if (name.LowerCaseEqualsLiteral("resizable")) {
    4400           0 :       if (value.LowerCaseEqualsLiteral("on")  ||
    4401           0 :           value.LowerCaseEqualsLiteral("yes") ||
    4402           0 :           value.LowerCaseEqualsLiteral("1")) {
    4403           0 :         aResult.AppendLiteral(",resizable=1");
    4404             :       }
    4405           0 :     } else if (name.LowerCaseEqualsLiteral("scroll")) {
    4406           0 :       if (value.LowerCaseEqualsLiteral("off")  ||
    4407           0 :           value.LowerCaseEqualsLiteral("no") ||
    4408           0 :           value.LowerCaseEqualsLiteral("0")) {
    4409           0 :         aResult.AppendLiteral(",scrollbars=0");
    4410             :       }
    4411             :     }
    4412             : 
    4413           0 :     if (iter == end ||
    4414           0 :         !TokenizeDialogOptions(token, iter, end) ||
    4415           0 :         !token.EqualsLiteral(";")) {
    4416             :       break;
    4417             :     }
    4418             :   }
    4419           0 : }
    4420             : 
    4421             : void
    4422           0 : nsGlobalWindowInner::UpdateCommands(const nsAString& anAction,
    4423             :                                     Selection* aSel,
    4424             :                                     int16_t aReason)
    4425             : {
    4426           0 :   if (GetOuterWindowInternal()) {
    4427           0 :     GetOuterWindowInternal()->UpdateCommands(anAction, aSel, aReason);
    4428             :   }
    4429           0 : }
    4430             : 
    4431             : Selection*
    4432           0 : nsGlobalWindowInner::GetSelection(ErrorResult& aError)
    4433             : {
    4434           0 :   FORWARD_TO_OUTER_OR_THROW(GetSelectionOuter, (), aError, nullptr);
    4435             : }
    4436             : 
    4437             : bool
    4438           0 : nsGlobalWindowInner::Find(const nsAString& aString, bool aCaseSensitive,
    4439             :                           bool aBackwards, bool aWrapAround, bool aWholeWord,
    4440             :                           bool aSearchInFrames, bool aShowDialog,
    4441             :                           ErrorResult& aError)
    4442             : {
    4443           0 :   FORWARD_TO_OUTER_OR_THROW(FindOuter,
    4444             :                             (aString, aCaseSensitive, aBackwards, aWrapAround,
    4445             :                              aWholeWord, aSearchInFrames, aShowDialog, aError),
    4446             :                             aError, false);
    4447             : }
    4448             : 
    4449             : void
    4450           0 : nsGlobalWindowInner::GetOrigin(nsAString& aOrigin)
    4451             : {
    4452           0 :   nsContentUtils::GetUTFOrigin(GetPrincipal(), aOrigin);
    4453           0 : }
    4454             : 
    4455             : void
    4456           0 : nsGlobalWindowInner::Atob(const nsAString& aAsciiBase64String,
    4457             :                           nsAString& aBinaryData, ErrorResult& aError)
    4458             : {
    4459           0 :   aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
    4460           0 : }
    4461             : 
    4462             : void
    4463           0 : nsGlobalWindowInner::Btoa(const nsAString& aBinaryData,
    4464             :                           nsAString& aAsciiBase64String, ErrorResult& aError)
    4465             : {
    4466           0 :   aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
    4467           0 : }
    4468             : 
    4469             : //*****************************************************************************
    4470             : // EventTarget
    4471             : //*****************************************************************************
    4472             : 
    4473             : nsPIDOMWindowOuter*
    4474           0 : nsGlobalWindowInner::GetOwnerGlobalForBindings()
    4475             : {
    4476           0 :   return nsPIDOMWindowOuter::GetFromCurrentInner(this);
    4477             : }
    4478             : 
    4479             : bool
    4480           1 : nsGlobalWindowInner::DispatchEvent(Event& aEvent,
    4481             :                                    CallerType aCallerType,
    4482             :                                    ErrorResult& aRv)
    4483             : {
    4484           1 :   if (!IsCurrentInnerWindow()) {
    4485             :     NS_WARNING("DispatchEvent called on non-current inner window, dropping. "
    4486           0 :                "Please check the window in the caller instead.");
    4487           0 :     aRv.Throw(NS_ERROR_FAILURE);
    4488           0 :     return false;
    4489             :   }
    4490             : 
    4491           2 :   if (!mDoc) {
    4492           0 :     aRv.Throw(NS_ERROR_FAILURE);
    4493           0 :     return false;
    4494             :   }
    4495             : 
    4496             :   // Obtain a presentation shell
    4497           2 :   RefPtr<nsPresContext> presContext = mDoc->GetPresContext();
    4498             : 
    4499           1 :   nsEventStatus status = nsEventStatus_eIgnore;
    4500           0 :   nsresult rv = EventDispatcher::DispatchDOMEvent(ToSupports(this), nullptr,
    4501           0 :                                                   &aEvent, presContext, &status);
    4502           0 :   bool retval = !aEvent.DefaultPrevented(aCallerType);
    4503           0 :   if (NS_FAILED(rv)) {
    4504           0 :     aRv.Throw(rv);
    4505             :   }
    4506             :   return retval;
    4507             : }
    4508             : 
    4509             : bool
    4510          48 : nsGlobalWindowInner::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
    4511             : {
    4512          96 :   return !nsContentUtils::IsChromeDoc(mDoc);
    4513             : }
    4514             : 
    4515             : EventListenerManager*
    4516          53 : nsGlobalWindowInner::GetOrCreateListenerManager()
    4517             : {
    4518         106 :   if (!mListenerManager) {
    4519             :     mListenerManager =
    4520           6 :       new EventListenerManager(static_cast<EventTarget*>(this));
    4521             :   }
    4522             : 
    4523         106 :   return mListenerManager;
    4524             : }
    4525             : 
    4526             : EventListenerManager*
    4527         238 : nsGlobalWindowInner::GetExistingListenerManager() const
    4528             : {
    4529         476 :   return mListenerManager;
    4530             : }
    4531             : 
    4532             : //*****************************************************************************
    4533             : // nsGlobalWindowInner::nsPIDOMWindow
    4534             : //*****************************************************************************
    4535             : 
    4536             : nsPIDOMWindowOuter*
    4537           0 : nsGlobalWindowInner::GetPrivateRoot()
    4538             : {
    4539           0 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    4540           0 :   if (!outer) {
    4541           0 :     NS_WARNING("No outer window available!");
    4542           0 :     return nullptr;
    4543             :   }
    4544           0 :   return outer->GetPrivateRoot();
    4545             : }
    4546             : 
    4547             : Location*
    4548           3 : nsGlobalWindowInner::GetLocation()
    4549             : {
    4550           6 :   if (!mLocation) {
    4551           0 :     mLocation = new dom::Location(this, GetDocShell());
    4552             :   }
    4553             : 
    4554           6 :   return mLocation;
    4555             : }
    4556             : 
    4557             : bool
    4558           0 : nsGlobalWindowInner::IsTopLevelWindowActive()
    4559             : {
    4560           0 :   if (GetOuterWindowInternal()) {
    4561           0 :     return GetOuterWindowInternal()->IsTopLevelWindowActive();
    4562             :   }
    4563             :   return false;
    4564             : }
    4565             : 
    4566             : void
    4567           1 : nsGlobalWindowInner::MaybeUpdateTouchState()
    4568             : {
    4569           1 :   if (mMayHaveTouchEventListener) {
    4570             :     nsCOMPtr<nsIObserverService> observerService =
    4571           2 :       services::GetObserverService();
    4572             : 
    4573           1 :     if (observerService) {
    4574           0 :       observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
    4575             :                                        DOM_TOUCH_LISTENER_ADDED,
    4576           2 :                                        nullptr);
    4577             :     }
    4578             :   }
    4579           1 : }
    4580             : 
    4581             : void
    4582           0 : nsGlobalWindowInner::EnableGamepadUpdates()
    4583             : {
    4584           0 :   if (mHasGamepad) {
    4585           0 :     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
    4586           0 :     if (gamepadManager) {
    4587           0 :       gamepadManager->AddListener(this);
    4588             :     }
    4589             :   }
    4590           0 : }
    4591             : 
    4592             : void
    4593           7 : nsGlobalWindowInner::DisableGamepadUpdates()
    4594             : {
    4595           7 :   if (mHasGamepad) {
    4596           0 :     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
    4597           0 :     if (gamepadManager) {
    4598           0 :       gamepadManager->RemoveListener(this);
    4599             :     }
    4600             :   }
    4601           7 : }
    4602             : 
    4603             : void
    4604           0 : nsGlobalWindowInner::EnableVRUpdates()
    4605             : {
    4606           0 :   if (mHasVREvents && !mVREventObserver) {
    4607           0 :     mVREventObserver = new VREventObserver(this);
    4608             :   }
    4609           0 : }
    4610             : 
    4611             : void
    4612           7 : nsGlobalWindowInner::DisableVRUpdates()
    4613             : {
    4614          14 :   if (mVREventObserver) {
    4615           0 :     mVREventObserver->DisconnectFromOwner();
    4616           0 :     mVREventObserver = nullptr;
    4617             :   }
    4618           7 : }
    4619             : 
    4620             : void
    4621           0 : nsGlobalWindowInner::ResetVRTelemetry(bool aUpdate)
    4622             : {
    4623           0 :   if (mVREventObserver) {
    4624           0 :     mVREventObserver->UpdateSpentTimeIn2DTelemetry(aUpdate);
    4625             :   }
    4626           0 : }
    4627             : 
    4628           0 : static bool ShouldShowFocusRingIfFocusedByMouse(nsIContent* aNode)
    4629             : {
    4630           0 :   if (!aNode) {
    4631             :     return true;
    4632             :   }
    4633           0 :   return !nsContentUtils::ContentIsLink(aNode) &&
    4634           0 :     !aNode->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio);
    4635             : }
    4636             : 
    4637             : void
    4638           2 : nsGlobalWindowInner::SetFocusedElement(Element* aElement,
    4639             :                                        uint32_t aFocusMethod,
    4640             :                                        bool aNeedsFocus)
    4641             : {
    4642           4 :   if (aElement && aElement->GetComposedDoc() != mDoc) {
    4643           0 :     NS_WARNING("Trying to set focus to a node from a wrong document");
    4644           0 :     return;
    4645             :   }
    4646             : 
    4647           2 :   if (IsDying()) {
    4648           0 :     NS_ASSERTION(!aElement, "Trying to focus cleaned up window!");
    4649             :     aElement = nullptr;
    4650             :     aNeedsFocus = false;
    4651             :   }
    4652           4 :   if (mFocusedElement != aElement) {
    4653           0 :     UpdateCanvasFocus(false, aElement);
    4654           0 :     mFocusedElement = aElement;
    4655           0 :     mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
    4656           0 :     mShowFocusRingForContent = false;
    4657             :   }
    4658             : 
    4659           4 :   if (mFocusedElement) {
    4660             :     // if a node was focused by a keypress, turn on focus rings for the
    4661             :     // window.
    4662           2 :     if (mFocusMethod & nsIFocusManager::FLAG_BYKEY) {
    4663           0 :       mFocusByKeyOccurred = true;
    4664           0 :     } else if (
    4665             :       // otherwise, we set mShowFocusRingForContent, as we don't want this to
    4666             :       // be permanent for the window. On Windows, focus rings are only shown
    4667             :       // when the FLAG_SHOWRING flag is used. On other platforms, focus rings
    4668             :       // are only visible on some elements.
    4669             : #ifndef XP_WIN
    4670           2 :       !(mFocusMethod & nsIFocusManager::FLAG_BYMOUSE) ||
    4671           0 :       ShouldShowFocusRingIfFocusedByMouse(aElement) ||
    4672             : #endif
    4673           0 :       aFocusMethod & nsIFocusManager::FLAG_SHOWRING) {
    4674           0 :         mShowFocusRingForContent = true;
    4675             :     }
    4676             :   }
    4677             : 
    4678           2 :   if (aNeedsFocus)
    4679           0 :     mNeedsFocus = aNeedsFocus;
    4680             : }
    4681             : 
    4682             : uint32_t
    4683           3 : nsGlobalWindowInner::GetFocusMethod()
    4684             : {
    4685           3 :   return mFocusMethod;
    4686             : }
    4687             : 
    4688             : bool
    4689           1 : nsGlobalWindowInner::ShouldShowFocusRing()
    4690             : {
    4691           1 :   if (mShowFocusRingForContent || mFocusByKeyOccurred) {
    4692             :     return true;
    4693             :   }
    4694             : 
    4695           0 :   nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
    4696           0 :   return root ? root->ShowFocusRings() : false;
    4697             : }
    4698             : 
    4699             : bool
    4700           1 : nsGlobalWindowInner::TakeFocus(bool aFocus, uint32_t aFocusMethod)
    4701             : {
    4702           1 :   if (IsDying()) {
    4703             :     return false;
    4704             :   }
    4705             : 
    4706           1 :   if (aFocus)
    4707           0 :     mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
    4708             : 
    4709           1 :   if (mHasFocus != aFocus) {
    4710           0 :     mHasFocus = aFocus;
    4711           0 :     UpdateCanvasFocus(true, mFocusedElement);
    4712             :   }
    4713             : 
    4714             :   // if mNeedsFocus is true, then the document has not yet received a
    4715             :   // document-level focus event. If there is a root content node, then return
    4716             :   // true to tell the calling focus manager that a focus event is expected. If
    4717             :   // there is no root content node, the document hasn't loaded enough yet, or
    4718             :   // there isn't one and there is no point in firing a focus event.
    4719           1 :   if (aFocus && mNeedsFocus && mDoc && mDoc->GetRootElement() != nullptr) {
    4720           0 :     mNeedsFocus = false;
    4721           0 :     return true;
    4722             :   }
    4723             : 
    4724           1 :   mNeedsFocus = false;
    4725           0 :   return false;
    4726             : }
    4727             : 
    4728             : void
    4729           6 : nsGlobalWindowInner::SetReadyForFocus()
    4730             : {
    4731           6 :   bool oldNeedsFocus = mNeedsFocus;
    4732           0 :   mNeedsFocus = false;
    4733             : 
    4734           6 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    4735           0 :   if (fm) {
    4736           0 :     fm->WindowShown(GetOuterWindow(), oldNeedsFocus);
    4737             :   }
    4738           6 : }
    4739             : 
    4740             : void
    4741           8 : nsGlobalWindowInner::PageHidden()
    4742             : {
    4743             :   // the window is being hidden, so tell the focus manager that the frame is
    4744             :   // no longer valid. Use the persisted field to determine if the document
    4745             :   // is being destroyed.
    4746             : 
    4747           8 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    4748           0 :   if (fm) {
    4749           0 :     fm->WindowHidden(GetOuterWindow());
    4750             :   }
    4751             : 
    4752           8 :   mNeedsFocus = true;
    4753           0 : }
    4754             : 
    4755           0 : class HashchangeCallback : public Runnable
    4756             : {
    4757             : public:
    4758           0 :   HashchangeCallback(const nsAString& aOldURL,
    4759             :                      const nsAString& aNewURL,
    4760             :                      nsGlobalWindowInner* aWindow)
    4761           0 :     : mozilla::Runnable("HashchangeCallback")
    4762           0 :     , mWindow(aWindow)
    4763             :   {
    4764           0 :     MOZ_ASSERT(mWindow);
    4765           0 :     mOldURL.Assign(aOldURL);
    4766           0 :     mNewURL.Assign(aNewURL);
    4767           0 :   }
    4768             : 
    4769           0 :   NS_IMETHOD Run() override
    4770             :   {
    4771           0 :     MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread.");
    4772           0 :     return mWindow->FireHashchange(mOldURL, mNewURL);
    4773             :   }
    4774             : 
    4775             : private:
    4776             :   nsString mOldURL;
    4777             :   nsString mNewURL;
    4778             :   RefPtr<nsGlobalWindowInner> mWindow;
    4779             : };
    4780             : 
    4781             : nsresult
    4782           0 : nsGlobalWindowInner::DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI)
    4783             : {
    4784             :   // Make sure that aOldURI and aNewURI are identical up to the '#', and that
    4785             :   // their hashes are different.
    4786           0 :   bool equal = false;
    4787           0 :   NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->EqualsExceptRef(aNewURI, &equal)) && equal);
    4788           0 :   nsAutoCString oldHash, newHash;
    4789             :   bool oldHasHash, newHasHash;
    4790           0 :   NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->GetRef(oldHash)) &&
    4791             :                   NS_SUCCEEDED(aNewURI->GetRef(newHash)) &&
    4792             :                   NS_SUCCEEDED(aOldURI->GetHasRef(&oldHasHash)) &&
    4793             :                   NS_SUCCEEDED(aNewURI->GetHasRef(&newHasHash)) &&
    4794             :                   (oldHasHash != newHasHash || !oldHash.Equals(newHash)));
    4795             : 
    4796           0 :   nsAutoCString oldSpec, newSpec;
    4797           0 :   nsresult rv = aOldURI->GetSpec(oldSpec);
    4798           0 :   NS_ENSURE_SUCCESS(rv, rv);
    4799           0 :   rv = aNewURI->GetSpec(newSpec);
    4800           0 :   NS_ENSURE_SUCCESS(rv, rv);
    4801             : 
    4802           0 :   NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
    4803           0 :   NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
    4804             : 
    4805             :   nsCOMPtr<nsIRunnable> callback =
    4806           0 :     new HashchangeCallback(oldWideSpec, newWideSpec, this);
    4807           0 :   return Dispatch(TaskCategory::Other, callback.forget());
    4808             : }
    4809             : 
    4810             : nsresult
    4811           0 : nsGlobalWindowInner::FireHashchange(const nsAString &aOldURL,
    4812             :                                     const nsAString &aNewURL)
    4813             : {
    4814             :   // Don't do anything if the window is frozen.
    4815           0 :   if (IsFrozen()) {
    4816             :     return NS_OK;
    4817             :   }
    4818             : 
    4819             :   // Get a presentation shell for use in creating the hashchange event.
    4820           0 :   NS_ENSURE_STATE(IsCurrentInnerWindow());
    4821             : 
    4822           0 :   HashChangeEventInit init;
    4823           0 :   init.mBubbles = true;
    4824           0 :   init.mCancelable = false;
    4825           0 :   init.mNewURL = aNewURL;
    4826           0 :   init.mOldURL = aOldURL;
    4827             : 
    4828             :   RefPtr<HashChangeEvent> event =
    4829           0 :     HashChangeEvent::Constructor(this, NS_LITERAL_STRING("hashchange"),
    4830           0 :                                  init);
    4831             : 
    4832           0 :   event->SetTrusted(true);
    4833             : 
    4834           0 :   ErrorResult rv;
    4835           0 :   DispatchEvent(*event, rv);
    4836           0 :   return rv.StealNSResult();
    4837             : }
    4838             : 
    4839             : nsresult
    4840           0 : nsGlobalWindowInner::DispatchSyncPopState()
    4841             : {
    4842           0 :   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
    4843             :                "Must be safe to run script here.");
    4844             : 
    4845           0 :   nsresult rv = NS_OK;
    4846             : 
    4847             :   // Bail if the window is frozen.
    4848           0 :   if (IsFrozen()) {
    4849             :     return NS_OK;
    4850             :   }
    4851             : 
    4852             :   // Get the document's pending state object -- it contains the data we're
    4853             :   // going to send along with the popstate event.  The object is serialized
    4854             :   // using structured clone.
    4855           0 :   nsCOMPtr<nsIVariant> stateObj;
    4856           0 :   rv = mDoc->GetStateObject(getter_AddRefs(stateObj));
    4857           0 :   NS_ENSURE_SUCCESS(rv, rv);
    4858             : 
    4859           0 :   bool result = true;
    4860           0 :   AutoJSAPI jsapi;
    4861           0 :   result = jsapi.Init(this);
    4862           0 :   NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
    4863             : 
    4864           0 :   JSContext* cx = jsapi.cx();
    4865           0 :   JS::Rooted<JS::Value> stateJSValue(cx, JS::NullValue());
    4866           0 :   result = stateObj ? VariantToJsval(cx, stateObj, &stateJSValue) : true;
    4867           0 :   NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
    4868             : 
    4869           0 :   RootedDictionary<PopStateEventInit> init(cx);
    4870           0 :   init.mBubbles = true;
    4871           0 :   init.mCancelable = false;
    4872           0 :   init.mState = stateJSValue;
    4873             : 
    4874             :   RefPtr<PopStateEvent> event =
    4875           0 :     PopStateEvent::Constructor(this, NS_LITERAL_STRING("popstate"),
    4876           0 :                                init);
    4877           0 :   event->SetTrusted(true);
    4878           0 :   event->SetTarget(this);
    4879             : 
    4880           0 :   ErrorResult err;
    4881           0 :   DispatchEvent(*event, err);
    4882           0 :   return err.StealNSResult();
    4883             : }
    4884             : 
    4885             : // Find an nsICanvasFrame under aFrame.  Only search the principal
    4886             : // child lists.  aFrame must be non-null.
    4887             : static nsCanvasFrame*
    4888           0 : FindCanvasFrame(nsIFrame* aFrame)
    4889             : {
    4890           0 :     nsCanvasFrame* canvasFrame = do_QueryFrame(aFrame);
    4891           0 :     if (canvasFrame) {
    4892             :         return canvasFrame;
    4893             :     }
    4894             : 
    4895           0 :     for (nsIFrame* kid : aFrame->PrincipalChildList()) {
    4896           0 :         canvasFrame = FindCanvasFrame(kid);
    4897           0 :         if (canvasFrame) {
    4898           0 :             return canvasFrame;
    4899             :         }
    4900             :     }
    4901             : 
    4902           0 :     return nullptr;
    4903             : }
    4904             : 
    4905             : //-------------------------------------------------------
    4906             : // Tells the HTMLFrame/CanvasFrame that is now has focus
    4907             : void
    4908           2 : nsGlobalWindowInner::UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent)
    4909             : {
    4910             :   // this is called from the inner window so use GetDocShell
    4911           2 :   nsIDocShell* docShell = GetDocShell();
    4912           0 :   if (!docShell)
    4913           0 :     return;
    4914             : 
    4915             :   bool editable;
    4916           2 :   docShell->GetEditable(&editable);
    4917           0 :   if (editable)
    4918             :     return;
    4919             : 
    4920           4 :   nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
    4921           0 :   if (!presShell || !mDoc)
    4922           0 :     return;
    4923             : 
    4924           2 :   Element *rootElement = mDoc->GetRootElement();
    4925           0 :   if (rootElement) {
    4926           0 :       if ((mHasFocus || aFocusChanged) &&
    4927           0 :           (mFocusedElement == rootElement || aNewContent == rootElement)) {
    4928           0 :           nsIFrame* frame = rootElement->GetPrimaryFrame();
    4929           0 :           if (frame) {
    4930           0 :               frame = frame->GetParent();
    4931           0 :               nsCanvasFrame* canvasFrame = do_QueryFrame(frame);
    4932           0 :               if (canvasFrame) {
    4933           0 :                   canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
    4934             :               }
    4935             :           }
    4936             :       }
    4937             :   } else {
    4938             :       // Look for the frame the hard way
    4939           0 :       nsIFrame* frame = presShell->GetRootFrame();
    4940           0 :       if (frame) {
    4941           0 :           nsCanvasFrame* canvasFrame = FindCanvasFrame(frame);
    4942           0 :           if (canvasFrame) {
    4943           0 :               canvasFrame->SetHasFocus(false);
    4944             :           }
    4945             :       }
    4946             :   }
    4947             : }
    4948             : 
    4949             : already_AddRefed<nsICSSDeclaration>
    4950           6 : nsGlobalWindowInner::GetComputedStyle(Element& aElt, const nsAString& aPseudoElt,
    4951             :                                       ErrorResult& aError)
    4952             : {
    4953           6 :   return GetComputedStyleHelper(aElt, aPseudoElt, false, aError);
    4954             : }
    4955             : 
    4956             : already_AddRefed<nsICSSDeclaration>
    4957           0 : nsGlobalWindowInner::GetDefaultComputedStyle(Element& aElt,
    4958             :                                              const nsAString& aPseudoElt,
    4959             :                                              ErrorResult& aError)
    4960             : {
    4961           0 :   return GetComputedStyleHelper(aElt, aPseudoElt, true, aError);
    4962             : }
    4963             : 
    4964             : already_AddRefed<nsICSSDeclaration>
    4965           6 : nsGlobalWindowInner::GetComputedStyleHelper(Element& aElt,
    4966             :                                             const nsAString& aPseudoElt,
    4967             :                                             bool aDefaultStylesOnly,
    4968             :                                             ErrorResult& aError)
    4969             : {
    4970           6 :   FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter,
    4971             :                             (aElt, aPseudoElt, aDefaultStylesOnly),
    4972             :                             aError, nullptr);
    4973             : }
    4974             : 
    4975             : Storage*
    4976           0 : nsGlobalWindowInner::GetSessionStorage(ErrorResult& aError)
    4977             : {
    4978           0 :   nsIPrincipal *principal = GetPrincipal();
    4979           0 :   nsIDocShell* docShell = GetDocShell();
    4980             : 
    4981           0 :   if (!principal || !docShell || !Storage::StoragePrefIsEnabled()) {
    4982             :     return nullptr;
    4983             :   }
    4984             : 
    4985           0 :   if (mSessionStorage) {
    4986           0 :     MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
    4987             :             ("nsGlobalWindowInner %p has %p sessionStorage", this, mSessionStorage.get()));
    4988           0 :     bool canAccess = principal->Subsumes(mSessionStorage->Principal());
    4989           0 :     NS_ASSERTION(canAccess,
    4990             :                  "This window owned sessionStorage "
    4991             :                  "that could not be accessed!");
    4992           0 :     if (!canAccess) {
    4993           0 :       mSessionStorage = nullptr;
    4994             :     }
    4995             :   }
    4996             : 
    4997           0 :   if (!mSessionStorage) {
    4998           0 :     nsString documentURI;
    4999           0 :     if (mDoc) {
    5000           0 :       aError = mDoc->GetDocumentURI(documentURI);
    5001           0 :       if (NS_WARN_IF(aError.Failed())) {
    5002           0 :         return nullptr;
    5003             :       }
    5004             :     }
    5005             : 
    5006             :     // If the document has the sandboxed origin flag set
    5007             :     // don't allow access to sessionStorage.
    5008           0 :     if (!mDoc) {
    5009           0 :       aError.Throw(NS_ERROR_FAILURE);
    5010           0 :       return nullptr;
    5011             :     }
    5012             : 
    5013           0 :     if (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
    5014           0 :       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
    5015           0 :       return nullptr;
    5016             :     }
    5017             : 
    5018             :     nsresult rv;
    5019             : 
    5020           0 :     nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(docShell, &rv);
    5021           0 :     if (NS_FAILED(rv)) {
    5022           0 :       aError.Throw(rv);
    5023           0 :       return nullptr;
    5024             :     }
    5025             : 
    5026           0 :     nsCOMPtr<nsIDOMStorage> storage;
    5027           0 :     aError = storageManager->CreateStorage(this, principal, documentURI,
    5028           0 :                                            IsPrivateBrowsing(),
    5029           0 :                                            getter_AddRefs(storage));
    5030           0 :     if (aError.Failed()) {
    5031           0 :       return nullptr;
    5032             :     }
    5033             : 
    5034           0 :     mSessionStorage = static_cast<Storage*>(storage.get());
    5035           0 :     MOZ_ASSERT(mSessionStorage);
    5036             : 
    5037           0 :     MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
    5038             :             ("nsGlobalWindowInner %p tried to get a new sessionStorage %p", this, mSessionStorage.get()));
    5039             : 
    5040           0 :     if (!mSessionStorage) {
    5041           0 :       aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
    5042           0 :       return nullptr;
    5043             :     }
    5044             :   }
    5045             : 
    5046           0 :   MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
    5047             :           ("nsGlobalWindowInner %p returns %p sessionStorage", this, mSessionStorage.get()));
    5048             : 
    5049           0 :   return mSessionStorage;
    5050             : }
    5051             : 
    5052             : Storage*
    5053           0 : nsGlobalWindowInner::GetLocalStorage(ErrorResult& aError)
    5054             : {
    5055           0 :   if (!Storage::StoragePrefIsEnabled()) {
    5056             :     return nullptr;
    5057             :   }
    5058             : 
    5059           0 :   if (!mLocalStorage) {
    5060           0 :     if (nsContentUtils::StorageAllowedForWindow(this) ==
    5061             :           nsContentUtils::StorageAccess::eDeny) {
    5062           0 :       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
    5063           0 :       return nullptr;
    5064             :     }
    5065             : 
    5066           0 :     nsIPrincipal *principal = GetPrincipal();
    5067           0 :     if (!principal) {
    5068             :       return nullptr;
    5069             :     }
    5070             : 
    5071             :     nsresult rv;
    5072             :     nsCOMPtr<nsIDOMStorageManager> storageManager =
    5073           0 :       do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
    5074           0 :     if (NS_FAILED(rv)) {
    5075           0 :       aError.Throw(rv);
    5076           0 :       return nullptr;
    5077             :     }
    5078             : 
    5079           0 :     nsString documentURI;
    5080           0 :     if (mDoc) {
    5081           0 :       aError = mDoc->GetDocumentURI(documentURI);
    5082           0 :       if (NS_WARN_IF(aError.Failed())) {
    5083             :         return nullptr;
    5084             :       }
    5085             :     }
    5086             : 
    5087           0 :     nsCOMPtr<nsIDOMStorage> storage;
    5088           0 :     aError = storageManager->CreateStorage(this, principal, documentURI,
    5089           0 :                                            IsPrivateBrowsing(),
    5090           0 :                                            getter_AddRefs(storage));
    5091           0 :     if (aError.Failed()) {
    5092           0 :       return nullptr;
    5093             :     }
    5094             : 
    5095           0 :     mLocalStorage = static_cast<Storage*>(storage.get());
    5096           0 :     MOZ_ASSERT(mLocalStorage);
    5097             :   }
    5098             : 
    5099           0 :   return mLocalStorage;
    5100             : }
    5101             : 
    5102             : IDBFactory*
    5103           0 : nsGlobalWindowInner::GetIndexedDB(ErrorResult& aError)
    5104             : {
    5105           0 :   if (!mIndexedDB) {
    5106             :     // This may keep mIndexedDB null without setting an error.
    5107           0 :     aError = IDBFactory::CreateForWindow(this,
    5108           0 :                                          getter_AddRefs(mIndexedDB));
    5109             :   }
    5110             : 
    5111           0 :   return mIndexedDB;
    5112             : }
    5113             : 
    5114             : void
    5115           0 : nsGlobalWindowInner::AddPendingPromise(mozilla::dom::Promise* aPromise)
    5116             : {
    5117           0 :   mPendingPromises.AppendElement(aPromise);
    5118           0 : }
    5119             : 
    5120             : void
    5121           0 : nsGlobalWindowInner::RemovePendingPromise(mozilla::dom::Promise* aPromise)
    5122             : {
    5123           0 :   DebugOnly<bool> foundIt = mPendingPromises.RemoveElement(aPromise);
    5124           0 :   MOZ_ASSERT(foundIt, "tried to remove a non-existent element from mPendingPromises");
    5125           0 : }
    5126             : 
    5127             : //*****************************************************************************
    5128             : // nsGlobalWindowInner::nsIInterfaceRequestor
    5129             : //*****************************************************************************
    5130             : 
    5131             : NS_IMETHODIMP
    5132          38 : nsGlobalWindowInner::GetInterface(const nsIID & aIID, void **aSink)
    5133             : {
    5134          38 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    5135           0 :   NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED);
    5136             : 
    5137          38 :   nsresult rv = outer->GetInterfaceInternal(aIID, aSink);
    5138           0 :   if (rv == NS_ERROR_NO_INTERFACE) {
    5139           0 :     return QueryInterface(aIID, aSink);
    5140             :   }
    5141             :   return rv;
    5142             : }
    5143             : 
    5144             : void
    5145          31 : nsGlobalWindowInner::GetInterface(JSContext* aCx, nsIJSID* aIID,
    5146             :                                   JS::MutableHandle<JS::Value> aRetval,
    5147             :                                   ErrorResult& aError)
    5148             : {
    5149          31 :   dom::GetInterface(aCx, this, aIID, aRetval, aError);
    5150           0 : }
    5151             : 
    5152             : already_AddRefed<CacheStorage>
    5153           0 : nsGlobalWindowInner::GetCaches(ErrorResult& aRv)
    5154             : {
    5155           0 :   if (!mCacheStorage) {
    5156             :     bool forceTrustedOrigin =
    5157           0 :       GetOuterWindow()->GetServiceWorkersTestingEnabled();
    5158             : 
    5159             :     nsContentUtils::StorageAccess access =
    5160           0 :       nsContentUtils::StorageAllowedForWindow(this);
    5161             : 
    5162             :     // We don't block the cache API when being told to only allow storage for the
    5163             :     // current session.
    5164           0 :     bool storageBlocked = access <= nsContentUtils::StorageAccess::ePrivateBrowsing;
    5165             : 
    5166           0 :     mCacheStorage = CacheStorage::CreateOnMainThread(cache::DEFAULT_NAMESPACE,
    5167             :                                                      this, GetPrincipal(),
    5168             :                                                      storageBlocked,
    5169           0 :                                                      forceTrustedOrigin, aRv);
    5170             :   }
    5171             : 
    5172           0 :   RefPtr<CacheStorage> ref = mCacheStorage;
    5173           0 :   return ref.forget();
    5174             : }
    5175             : 
    5176             : void
    5177           0 : nsGlobalWindowInner::FireOfflineStatusEventIfChanged()
    5178             : {
    5179           0 :   if (!IsCurrentInnerWindow())
    5180           0 :     return;
    5181             : 
    5182             :   // Don't fire an event if the status hasn't changed
    5183           0 :   if (mWasOffline == NS_IsOffline()) {
    5184             :     return;
    5185             :   }
    5186             : 
    5187           0 :   mWasOffline = !mWasOffline;
    5188             : 
    5189           0 :   nsAutoString name;
    5190           0 :   if (mWasOffline) {
    5191           0 :     name.AssignLiteral("offline");
    5192             :   } else {
    5193           0 :     name.AssignLiteral("online");
    5194             :   }
    5195           0 :   nsContentUtils::DispatchTrustedEvent(mDoc,
    5196             :                                        static_cast<EventTarget*>(this),
    5197             :                                        name,
    5198             :                                        false,
    5199           0 :                                        false);
    5200             : }
    5201             : 
    5202           0 : class NotifyIdleObserverRunnable : public Runnable
    5203             : {
    5204             : public:
    5205           0 :   NotifyIdleObserverRunnable(nsIIdleObserver* aIdleObserver,
    5206             :                              uint32_t aTimeInS,
    5207             :                              bool aCallOnidle,
    5208             :                              nsGlobalWindowInner* aIdleWindow)
    5209           0 :     : mozilla::Runnable("NotifyIdleObserverRunnable")
    5210             :     , mIdleObserver(aIdleObserver)
    5211             :     , mTimeInS(aTimeInS)
    5212             :     , mIdleWindow(aIdleWindow)
    5213           0 :     , mCallOnidle(aCallOnidle)
    5214           0 :   { }
    5215             : 
    5216           0 :   NS_IMETHOD Run() override
    5217             :   {
    5218           0 :     if (mIdleWindow->ContainsIdleObserver(mIdleObserver, mTimeInS)) {
    5219           0 :       return mCallOnidle ? mIdleObserver->Onidle() : mIdleObserver->Onactive();
    5220             :     }
    5221             :     return NS_OK;
    5222             :   }
    5223             : 
    5224             : private:
    5225             :   nsCOMPtr<nsIIdleObserver> mIdleObserver;
    5226             :   uint32_t mTimeInS;
    5227             :   RefPtr<nsGlobalWindowInner> mIdleWindow;
    5228             : 
    5229             :   // If false then call on active
    5230             :   bool mCallOnidle;
    5231             : };
    5232             : 
    5233             : void
    5234           0 : nsGlobalWindowInner::NotifyIdleObserver(IdleObserverHolder* aIdleObserverHolder,
    5235             :                                         bool aCallOnidle)
    5236             : {
    5237           0 :   MOZ_ASSERT(aIdleObserverHolder);
    5238           0 :   aIdleObserverHolder->mPrevNotificationIdle = aCallOnidle;
    5239             : 
    5240             :   nsCOMPtr<nsIRunnable> caller =
    5241             :     new NotifyIdleObserverRunnable(aIdleObserverHolder->mIdleObserver,
    5242             :                                    aIdleObserverHolder->mTimeInS,
    5243           0 :                                    aCallOnidle, this);
    5244           0 :   if (NS_FAILED(Dispatch(TaskCategory::Other, caller.forget()))) {
    5245           0 :     NS_WARNING("Failed to dispatch thread for idle observer notification.");
    5246             :   }
    5247           0 : }
    5248             : 
    5249             : bool
    5250           0 : nsGlobalWindowInner::ContainsIdleObserver(nsIIdleObserver* aIdleObserver, uint32_t aTimeInS)
    5251             : {
    5252           0 :   MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
    5253           0 :   bool found = false;
    5254           0 :   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
    5255           0 :   while (iter.HasMore()) {
    5256           0 :     IdleObserverHolder& idleObserver = iter.GetNext();
    5257           0 :     if (idleObserver.mIdleObserver == aIdleObserver &&
    5258           0 :         idleObserver.mTimeInS == aTimeInS) {
    5259             :       found = true;
    5260             :       break;
    5261             :     }
    5262             :   }
    5263           0 :   return found;
    5264             : }
    5265             : 
    5266             : void
    5267           0 : IdleActiveTimerCallback(nsITimer* aTimer, void* aClosure)
    5268             : {
    5269             :   RefPtr<nsGlobalWindowInner> idleWindow =
    5270           0 :     static_cast<nsGlobalWindowInner*>(aClosure);
    5271           0 :   MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
    5272           0 :   idleWindow->HandleIdleActiveEvent();
    5273           0 : }
    5274             : 
    5275             : void
    5276           0 : IdleObserverTimerCallback(nsITimer* aTimer, void* aClosure)
    5277             : {
    5278             :   RefPtr<nsGlobalWindowInner> idleWindow =
    5279           0 :     static_cast<nsGlobalWindowInner*>(aClosure);
    5280           0 :   MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
    5281           0 :   idleWindow->HandleIdleObserverCallback();
    5282           0 : }
    5283             : 
    5284             : void
    5285           0 : nsGlobalWindowInner::HandleIdleObserverCallback()
    5286             : {
    5287           0 :   MOZ_ASSERT(static_cast<uint32_t>(mIdleCallbackIndex) < mIdleObservers.Length(),
    5288             :                                   "Idle callback index exceeds array bounds!");
    5289           0 :   IdleObserverHolder& idleObserver = mIdleObservers.ElementAt(mIdleCallbackIndex);
    5290           0 :   NotifyIdleObserver(&idleObserver, true);
    5291           0 :   mIdleCallbackIndex++;
    5292           0 :   if (NS_FAILED(ScheduleNextIdleObserverCallback())) {
    5293           0 :     NS_WARNING("Failed to set next idle observer callback.");
    5294             :   }
    5295           0 : }
    5296             : 
    5297             : nsresult
    5298           0 : nsGlobalWindowInner::ScheduleNextIdleObserverCallback()
    5299             : {
    5300           0 :   MOZ_ASSERT(mIdleService, "No idle service!");
    5301             : 
    5302           0 :   if (mIdleCallbackIndex < 0 ||
    5303           0 :       static_cast<uint32_t>(mIdleCallbackIndex) >= mIdleObservers.Length()) {
    5304             :     return NS_OK;
    5305             :   }
    5306             : 
    5307             :   IdleObserverHolder& idleObserver =
    5308           0 :     mIdleObservers.ElementAt(mIdleCallbackIndex);
    5309             : 
    5310           0 :   uint32_t userIdleTimeMS = 0;
    5311           0 :   nsresult rv = mIdleService->GetIdleTime(&userIdleTimeMS);
    5312           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5313             : 
    5314           0 :   uint32_t callbackTimeMS = 0;
    5315           0 :   if (idleObserver.mTimeInS * 1000 + mIdleFuzzFactor > userIdleTimeMS) {
    5316           0 :     callbackTimeMS = idleObserver.mTimeInS * 1000 - userIdleTimeMS + mIdleFuzzFactor;
    5317             :   }
    5318             : 
    5319           0 :   mIdleTimer->Cancel();
    5320           0 :   rv = mIdleTimer->InitWithNamedFuncCallback(
    5321             :     IdleObserverTimerCallback,
    5322             :     this,
    5323             :     callbackTimeMS,
    5324             :     nsITimer::TYPE_ONE_SHOT,
    5325           0 :     "nsGlobalWindowInner::ScheduleNextIdleObserverCallback");
    5326           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5327             : 
    5328             :   return NS_OK;
    5329             : }
    5330             : 
    5331             : uint32_t
    5332           0 : nsGlobalWindowInner::GetFuzzTimeMS()
    5333             : {
    5334           0 :   if (gIdleObserversAPIFuzzTimeDisabled) {
    5335             :     return 0;
    5336             :   }
    5337             : 
    5338           0 :   uint32_t randNum = MAX_IDLE_FUZZ_TIME_MS;
    5339           0 :   size_t nbytes = PR_GetRandomNoise(&randNum, sizeof(randNum));
    5340           0 :   if (nbytes != sizeof(randNum)) {
    5341           0 :     NS_WARNING("PR_GetRandomNoise(...) Not implemented or no available noise!");
    5342           0 :     return MAX_IDLE_FUZZ_TIME_MS;
    5343             :   }
    5344             : 
    5345           0 :   if (randNum > MAX_IDLE_FUZZ_TIME_MS) {
    5346           0 :     randNum %= MAX_IDLE_FUZZ_TIME_MS;
    5347             :   }
    5348             : 
    5349           0 :   return randNum;
    5350             : }
    5351             : 
    5352             : nsresult
    5353           0 : nsGlobalWindowInner::ScheduleActiveTimerCallback()
    5354             : {
    5355           0 :   if (!mAddActiveEventFuzzTime) {
    5356           0 :     return HandleIdleActiveEvent();
    5357             :   }
    5358             : 
    5359           0 :   MOZ_ASSERT(mIdleTimer);
    5360           0 :   mIdleTimer->Cancel();
    5361             : 
    5362           0 :   uint32_t fuzzFactorInMS = GetFuzzTimeMS();
    5363           0 :   nsresult rv = mIdleTimer->InitWithNamedFuncCallback(
    5364             :     IdleActiveTimerCallback,
    5365             :     this,
    5366             :     fuzzFactorInMS,
    5367             :     nsITimer::TYPE_ONE_SHOT,
    5368           0 :     "nsGlobalWindowInner::ScheduleActiveTimerCallback");
    5369           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5370             :   return NS_OK;
    5371             : }
    5372             : 
    5373             : nsresult
    5374           0 : nsGlobalWindowInner::HandleIdleActiveEvent()
    5375             : {
    5376           0 :   if (mCurrentlyIdle) {
    5377           0 :     mIdleCallbackIndex = 0;
    5378           0 :     mIdleFuzzFactor = GetFuzzTimeMS();
    5379           0 :     nsresult rv = ScheduleNextIdleObserverCallback();
    5380           0 :     NS_ENSURE_SUCCESS(rv, rv);
    5381             :     return NS_OK;
    5382             :   }
    5383             : 
    5384           0 :   mIdleCallbackIndex = -1;
    5385           0 :   MOZ_ASSERT(mIdleTimer);
    5386           0 :   mIdleTimer->Cancel();
    5387           0 :   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
    5388           0 :   while (iter.HasMore()) {
    5389           0 :     IdleObserverHolder& idleObserver = iter.GetNext();
    5390           0 :     if (idleObserver.mPrevNotificationIdle) {
    5391           0 :       NotifyIdleObserver(&idleObserver, false);
    5392             :     }
    5393             :   }
    5394             : 
    5395           0 :   return NS_OK;
    5396             : }
    5397             : 
    5398             : nsGlobalWindowInner::SlowScriptResponse
    5399           0 : nsGlobalWindowInner::ShowSlowScriptDialog(const nsString& aAddonId)
    5400             : {
    5401             :   nsresult rv;
    5402           0 :   AutoJSContext cx;
    5403             : 
    5404           0 :   if (Preferences::GetBool("dom.always_stop_slow_scripts")) {
    5405             :     return KillSlowScript;
    5406             :   }
    5407             : 
    5408             :   // If it isn't safe to run script, then it isn't safe to bring up the prompt
    5409             :   // (since that spins the event loop). In that (rare) case, we just kill the
    5410             :   // script and report a warning.
    5411           0 :   if (!nsContentUtils::IsSafeToRunScript()) {
    5412           0 :     JS_ReportWarningASCII(cx, "A long running script was terminated");
    5413           0 :     return KillSlowScript;
    5414             :   }
    5415             : 
    5416             :   // If our document is not active, just kill the script: we've been unloaded
    5417           0 :   if (!HasActiveDocument()) {
    5418             :     return KillSlowScript;
    5419             :   }
    5420             : 
    5421             :   // Check if we should offer the option to debug
    5422           0 :   JS::AutoFilename filename;
    5423             :   unsigned lineno;
    5424             :   // Computing the line number can be very expensive (see bug 1330231 for
    5425             :   // example), and we don't use the line number anywhere except than in the
    5426             :   // parent process, so we avoid computing it elsewhere.  This gives us most of
    5427             :   // the wins we are interested in, since the source of the slowness here is
    5428             :   // minified scripts which is more common in Web content that is loaded in the
    5429             :   // content process.
    5430           0 :   unsigned* linenop = XRE_IsParentProcess() ? &lineno : nullptr;
    5431           0 :   bool hasFrame = JS::DescribeScriptedCaller(cx, &filename, linenop);
    5432             : 
    5433             :   // Record the slow script event if we haven't done so already for this inner window
    5434             :   // (which represents a particular page to the user).
    5435           0 :   if (!mHasHadSlowScript) {
    5436           0 :     Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1);
    5437             :   }
    5438           0 :   mHasHadSlowScript = true;
    5439             : 
    5440           0 :   if (XRE_IsContentProcess() &&
    5441             :       ProcessHangMonitor::Get()) {
    5442             :     ProcessHangMonitor::SlowScriptAction action;
    5443           0 :     RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
    5444           0 :     nsIDocShell* docShell = GetDocShell();
    5445           0 :     nsCOMPtr<nsITabChild> child = docShell ? docShell->GetTabChild() : nullptr;
    5446           0 :     action = monitor->NotifySlowScript(child,
    5447             :                                        filename.get(),
    5448           0 :                                        aAddonId);
    5449           0 :     if (action == ProcessHangMonitor::Terminate) {
    5450             :       return KillSlowScript;
    5451             :     }
    5452           0 :     if (action == ProcessHangMonitor::TerminateGlobal) {
    5453             :       return KillScriptGlobal;
    5454             :     }
    5455             : 
    5456           0 :     if (action == ProcessHangMonitor::StartDebugger) {
    5457             :       // Spin a nested event loop so that the debugger in the parent can fetch
    5458             :       // any information it needs. Once the debugger has started, return to the
    5459             :       // script.
    5460           0 :       RefPtr<nsGlobalWindowOuter> outer = GetOuterWindowInternal();
    5461           0 :       outer->EnterModalState();
    5462           0 :       SpinEventLoopUntil([&]() { return monitor->IsDebuggerStartupComplete(); });
    5463           0 :       outer->LeaveModalState();
    5464             :       return ContinueSlowScript;
    5465             :     }
    5466             : 
    5467             :     return ContinueSlowScriptAndKeepNotifying;
    5468             :   }
    5469             : 
    5470             :   // Reached only on non-e10s - once per slow script dialog.
    5471             :   // On e10s - we probe once at ProcessHangsMonitor.jsm
    5472           0 :   Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_NOTICE_COUNT, 1);
    5473             : 
    5474             :   // Get the nsIPrompt interface from the docshell
    5475           0 :   nsCOMPtr<nsIDocShell> ds = GetDocShell();
    5476           0 :   NS_ENSURE_TRUE(ds, KillSlowScript);
    5477           0 :   nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ds);
    5478           0 :   NS_ENSURE_TRUE(prompt, KillSlowScript);
    5479             : 
    5480             :   // Prioritize the SlowScriptDebug interface over JSD1.
    5481           0 :   nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
    5482             : 
    5483           0 :   if (hasFrame) {
    5484           0 :     const char *debugCID = "@mozilla.org/dom/slow-script-debug;1";
    5485           0 :     nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv);
    5486           0 :     if (NS_SUCCEEDED(rv)) {
    5487           0 :       debugService->GetActivationHandler(getter_AddRefs(debugCallback));
    5488             :     }
    5489             :   }
    5490             : 
    5491           0 :   bool failed = false;
    5492             :   auto getString = [&] (const char* name,
    5493           0 :                         nsContentUtils::PropertiesFile propFile = nsContentUtils::eDOM_PROPERTIES) {
    5494           0 :     nsAutoString result;
    5495           0 :     nsresult rv = nsContentUtils::GetLocalizedString(
    5496           0 :       propFile, name, result);
    5497             : 
    5498             :     // GetStringFromName can return NS_OK and still give nullptr string
    5499           0 :     failed = failed || NS_FAILED(rv) || result.IsEmpty();
    5500           0 :     return result;
    5501           0 :   };
    5502             : 
    5503           0 :   bool isAddonScript = !aAddonId.IsEmpty();
    5504           0 :   bool showDebugButton = debugCallback && !isAddonScript;
    5505             : 
    5506             :   // Get localizable strings
    5507             : 
    5508           0 :   nsAutoString title, checkboxMsg, debugButton, msg;
    5509           0 :   if (isAddonScript) {
    5510           0 :     title = getString("KillAddonScriptTitle");
    5511           0 :     checkboxMsg = getString("KillAddonScriptGlobalMessage");
    5512             : 
    5513           0 :     auto appName = getString("brandShortName", nsContentUtils::eBRAND_PROPERTIES);
    5514             : 
    5515           0 :     nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
    5516           0 :     nsString addonName;
    5517           0 :     if (!aps || NS_FAILED(aps->GetExtensionName(aAddonId, addonName))) {
    5518             :       addonName = aAddonId;
    5519             :     }
    5520             : 
    5521           0 :     const char16_t* params[] = {addonName.get(), appName.get()};
    5522           0 :     rv = nsContentUtils::FormatLocalizedString(
    5523             :         nsContentUtils::eDOM_PROPERTIES, "KillAddonScriptMessage",
    5524             :         params, msg);
    5525             : 
    5526           0 :     failed = failed || NS_FAILED(rv);
    5527             :   } else {
    5528           0 :     title = getString("KillScriptTitle");
    5529           0 :     checkboxMsg = getString("DontAskAgain");
    5530             : 
    5531           0 :     if (showDebugButton) {
    5532           0 :       debugButton = getString("DebugScriptButton");
    5533           0 :       msg = getString("KillScriptWithDebugMessage");
    5534             :     } else {
    5535           0 :       msg = getString("KillScriptMessage");
    5536             :     }
    5537             :   }
    5538             : 
    5539           0 :   auto stopButton = getString("StopScriptButton");
    5540           0 :   auto waitButton = getString("WaitForScriptButton");
    5541             : 
    5542           0 :   if (failed) {
    5543           0 :     NS_ERROR("Failed to get localized strings.");
    5544           0 :     return ContinueSlowScript;
    5545             :   }
    5546             : 
    5547             :   // Append file and line number information, if available
    5548           0 :   if (filename.get()) {
    5549           0 :     nsAutoString scriptLocation;
    5550             :     // We want to drop the middle part of too-long locations.  We'll
    5551             :     // define "too-long" as longer than 60 UTF-16 code units.  Just
    5552             :     // have to be a bit careful about unpaired surrogates.
    5553           0 :     NS_ConvertUTF8toUTF16 filenameUTF16(filename.get());
    5554           0 :     if (filenameUTF16.Length() > 60) {
    5555             :       // XXXbz Do we need to insert any bidi overrides here?
    5556           0 :       size_t cutStart = 30;
    5557           0 :       size_t cutLength = filenameUTF16.Length() - 60;
    5558           0 :       MOZ_ASSERT(cutLength > 0);
    5559           0 :       if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart])) {
    5560             :         // Don't truncate before the low surrogate, in case it's preceded by a
    5561             :         // high surrogate and forms a single Unicode character.  Instead, just
    5562             :         // include the low surrogate.
    5563           0 :         ++cutStart;
    5564           0 :         --cutLength;
    5565             :       }
    5566           0 :       if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart + cutLength])) {
    5567             :         // Likewise, don't drop a trailing low surrogate here.  We want to
    5568             :         // increase cutLength, since it might be 0 already so we can't very well
    5569             :         // decrease it.
    5570           0 :         ++cutLength;
    5571             :       }
    5572             : 
    5573             :       // Insert U+2026 HORIZONTAL ELLIPSIS
    5574           0 :       filenameUTF16.ReplaceLiteral(cutStart, cutLength, u"\x2026");
    5575             :     }
    5576           0 :     const char16_t *formatParams[] = { filenameUTF16.get() };
    5577           0 :     rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
    5578             :                                                "KillScriptLocation",
    5579             :                                                formatParams,
    5580             :                                                scriptLocation);
    5581             : 
    5582           0 :     if (NS_SUCCEEDED(rv)) {
    5583           0 :       msg.AppendLiteral("\n\n");
    5584           0 :       msg.Append(scriptLocation);
    5585           0 :       msg.Append(':');
    5586           0 :       msg.AppendInt(lineno);
    5587             :     }
    5588             :   }
    5589             : 
    5590             :   uint32_t buttonFlags = nsIPrompt::BUTTON_POS_1_DEFAULT +
    5591             :                          (nsIPrompt::BUTTON_TITLE_IS_STRING *
    5592           0 :                           (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));
    5593             : 
    5594             :   // Add a third button if necessary.
    5595           0 :   if (showDebugButton)
    5596           0 :     buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
    5597             : 
    5598           0 :   bool checkboxValue = false;
    5599           0 :   int32_t buttonPressed = 0; // In case the user exits dialog by clicking X.
    5600             :   {
    5601             :     // Null out the operation callback while we're re-entering JS here.
    5602           0 :     AutoDisableJSInterruptCallback disabler(cx);
    5603             : 
    5604             :     // Open the dialog.
    5605           0 :     rv = prompt->ConfirmEx(title.get(), msg.get(), buttonFlags,
    5606             :                            waitButton.get(), stopButton.get(),
    5607             :                            debugButton.get(), checkboxMsg.get(),
    5608           0 :                            &checkboxValue, &buttonPressed);
    5609             :   }
    5610             : 
    5611           0 :   if (buttonPressed == 0) {
    5612           0 :     if (checkboxValue && !isAddonScript && NS_SUCCEEDED(rv))
    5613             :       return AlwaysContinueSlowScript;
    5614           0 :     return ContinueSlowScript;
    5615             :   }
    5616             : 
    5617           0 :   if (buttonPressed == 2) {
    5618           0 :     MOZ_RELEASE_ASSERT(debugCallback);
    5619             : 
    5620           0 :     rv = debugCallback->HandleSlowScriptDebug(this);
    5621           0 :     return NS_SUCCEEDED(rv) ? ContinueSlowScript : KillSlowScript;
    5622             :   }
    5623             : 
    5624           0 :   JS_ClearPendingException(cx);
    5625             : 
    5626           0 :   if (checkboxValue && isAddonScript)
    5627             :     return KillScriptGlobal;
    5628           0 :   return KillSlowScript;
    5629             : }
    5630             : 
    5631             : uint32_t
    5632           0 : nsGlobalWindowInner::FindInsertionIndex(IdleObserverHolder* aIdleObserver)
    5633             : {
    5634           0 :   MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
    5635             : 
    5636           0 :   uint32_t i = 0;
    5637           0 :   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
    5638           0 :   while (iter.HasMore()) {
    5639           0 :     IdleObserverHolder& idleObserver = iter.GetNext();
    5640           0 :     if (idleObserver.mTimeInS > aIdleObserver->mTimeInS) {
    5641             :       break;
    5642             :     }
    5643           0 :     i++;
    5644           0 :     MOZ_ASSERT(i <= mIdleObservers.Length(), "Array index out of bounds error.");
    5645             :   }
    5646             : 
    5647           0 :   return i;
    5648             : }
    5649             : 
    5650             : nsresult
    5651           0 : nsGlobalWindowInner::RegisterIdleObserver(nsIIdleObserver* aIdleObserver)
    5652             : {
    5653             :   nsresult rv;
    5654           0 :   if (mIdleObservers.IsEmpty()) {
    5655           0 :     mIdleService = do_GetService("@mozilla.org/widget/idleservice;1", &rv);
    5656           0 :     NS_ENSURE_SUCCESS(rv, rv);
    5657             : 
    5658           0 :     rv = mIdleService->AddIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
    5659           0 :     NS_ENSURE_SUCCESS(rv, rv);
    5660             : 
    5661           0 :     if (!mIdleTimer) {
    5662           0 :       mIdleTimer = NS_NewTimer();
    5663           0 :       NS_ENSURE_TRUE(mIdleTimer, NS_ERROR_OUT_OF_MEMORY);
    5664             :     } else {
    5665           0 :       mIdleTimer->Cancel();
    5666             :     }
    5667             :   }
    5668             : 
    5669           0 :   MOZ_ASSERT(mIdleService);
    5670           0 :   MOZ_ASSERT(mIdleTimer);
    5671             : 
    5672           0 :   IdleObserverHolder tmpIdleObserver;
    5673           0 :   tmpIdleObserver.mIdleObserver = aIdleObserver;
    5674           0 :   rv = aIdleObserver->GetTime(&tmpIdleObserver.mTimeInS);
    5675           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5676           0 :   NS_ENSURE_ARG_MAX(tmpIdleObserver.mTimeInS, UINT32_MAX / 1000);
    5677           0 :   NS_ENSURE_ARG_MIN(tmpIdleObserver.mTimeInS, MIN_IDLE_NOTIFICATION_TIME_S);
    5678             : 
    5679           0 :   uint32_t insertAtIndex = FindInsertionIndex(&tmpIdleObserver);
    5680           0 :   if (insertAtIndex == mIdleObservers.Length()) {
    5681           0 :     mIdleObservers.AppendElement(tmpIdleObserver);
    5682             :   }
    5683             :   else {
    5684           0 :     mIdleObservers.InsertElementAt(insertAtIndex, tmpIdleObserver);
    5685             :   }
    5686             : 
    5687           0 :   bool userIsIdle = false;
    5688           0 :   rv = nsContentUtils::IsUserIdle(MIN_IDLE_NOTIFICATION_TIME_S, &userIsIdle);
    5689           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5690             : 
    5691             :   // Special case. First idle observer added to empty list while the user is idle.
    5692             :   // Haven't received 'idle' topic notification from slow idle service yet.
    5693             :   // Need to wait for the idle notification and then notify idle observers in the list.
    5694           0 :   if (userIsIdle && mIdleCallbackIndex == -1) {
    5695             :     return NS_OK;
    5696             :   }
    5697             : 
    5698           0 :   if (!mCurrentlyIdle) {
    5699             :     return NS_OK;
    5700             :   }
    5701             : 
    5702           0 :   MOZ_ASSERT(mIdleCallbackIndex >= 0);
    5703             : 
    5704           0 :   if (static_cast<int32_t>(insertAtIndex) < mIdleCallbackIndex) {
    5705           0 :     IdleObserverHolder& idleObserver = mIdleObservers.ElementAt(insertAtIndex);
    5706           0 :     NotifyIdleObserver(&idleObserver, true);
    5707           0 :     mIdleCallbackIndex++;
    5708           0 :     return NS_OK;
    5709             :   }
    5710             : 
    5711           0 :   if (static_cast<int32_t>(insertAtIndex) == mIdleCallbackIndex) {
    5712           0 :     mIdleTimer->Cancel();
    5713           0 :     rv = ScheduleNextIdleObserverCallback();
    5714           0 :     NS_ENSURE_SUCCESS(rv, rv);
    5715             :   }
    5716             :   return NS_OK;
    5717             : }
    5718             : 
    5719             : nsresult
    5720           0 : nsGlobalWindowInner::FindIndexOfElementToRemove(nsIIdleObserver* aIdleObserver,
    5721             :                                                 int32_t* aRemoveElementIndex)
    5722             : {
    5723           0 :   MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
    5724             : 
    5725           0 :   *aRemoveElementIndex = 0;
    5726           0 :   if (mIdleObservers.IsEmpty()) {
    5727             :     return NS_ERROR_FAILURE;
    5728             :   }
    5729             : 
    5730             :   uint32_t aIdleObserverTimeInS;
    5731           0 :   nsresult rv = aIdleObserver->GetTime(&aIdleObserverTimeInS);
    5732           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5733           0 :   NS_ENSURE_ARG_MIN(aIdleObserverTimeInS, MIN_IDLE_NOTIFICATION_TIME_S);
    5734             : 
    5735           0 :   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
    5736           0 :   while (iter.HasMore()) {
    5737           0 :     IdleObserverHolder& idleObserver = iter.GetNext();
    5738           0 :     if (idleObserver.mTimeInS == aIdleObserverTimeInS &&
    5739           0 :         idleObserver.mIdleObserver == aIdleObserver ) {
    5740             :       break;
    5741             :     }
    5742           0 :     (*aRemoveElementIndex)++;
    5743             :   }
    5744           0 :   return static_cast<uint32_t>(*aRemoveElementIndex) >= mIdleObservers.Length() ?
    5745           0 :     NS_ERROR_FAILURE : NS_OK;
    5746             : }
    5747             : 
    5748             : nsresult
    5749           0 : nsGlobalWindowInner::UnregisterIdleObserver(nsIIdleObserver* aIdleObserver)
    5750             : {
    5751             :   int32_t removeElementIndex;
    5752           0 :   nsresult rv = FindIndexOfElementToRemove(aIdleObserver, &removeElementIndex);
    5753           0 :   if (NS_FAILED(rv)) {
    5754           0 :     NS_WARNING("Idle observer not found in list of idle observers. No idle observer removed.");
    5755           0 :     return NS_OK;
    5756             :   }
    5757           0 :   mIdleObservers.RemoveElementAt(removeElementIndex);
    5758             : 
    5759           0 :   MOZ_ASSERT(mIdleTimer);
    5760           0 :   if (mIdleObservers.IsEmpty() && mIdleService) {
    5761           0 :     rv = mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
    5762           0 :     NS_ENSURE_SUCCESS(rv, rv);
    5763           0 :     mIdleService = nullptr;
    5764             : 
    5765           0 :     mIdleTimer->Cancel();
    5766           0 :     mIdleCallbackIndex = -1;
    5767           0 :     return NS_OK;
    5768             :   }
    5769             : 
    5770           0 :   if (!mCurrentlyIdle) {
    5771             :     return NS_OK;
    5772             :   }
    5773             : 
    5774           0 :   if (removeElementIndex < mIdleCallbackIndex) {
    5775           0 :     mIdleCallbackIndex--;
    5776           0 :     return NS_OK;
    5777             :   }
    5778             : 
    5779           0 :   if (removeElementIndex != mIdleCallbackIndex) {
    5780             :     return NS_OK;
    5781             :   }
    5782             : 
    5783           0 :   mIdleTimer->Cancel();
    5784             : 
    5785             :   // If the last element in the array had been notified then decrement
    5786             :   // mIdleCallbackIndex because an idle was removed from the list of
    5787             :   // idle observers.
    5788             :   // Example: add idle observer with time 1, 2, 3,
    5789             :   // Idle notifications for idle observers with time 1, 2, 3 are complete
    5790             :   // Remove idle observer with time 3 while the user is still idle.
    5791             :   // The user never transitioned to active state.
    5792             :   // Add an idle observer with idle time 4
    5793           0 :   if (static_cast<uint32_t>(mIdleCallbackIndex) == mIdleObservers.Length()) {
    5794           0 :     mIdleCallbackIndex--;
    5795             :   }
    5796           0 :   rv = ScheduleNextIdleObserverCallback();
    5797           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5798             : 
    5799             :   return NS_OK;
    5800             : }
    5801             : 
    5802             : nsresult
    5803           0 : nsGlobalWindowInner::Observe(nsISupports* aSubject, const char* aTopic,
    5804             :                              const char16_t* aData)
    5805             : {
    5806           0 :   if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
    5807           0 :     if (!IsFrozen()) {
    5808             :         // Fires an offline status event if the offline status has changed
    5809           0 :         FireOfflineStatusEventIfChanged();
    5810             :     }
    5811             :     return NS_OK;
    5812             :   }
    5813             : 
    5814           0 :   if (!nsCRT::strcmp(aTopic, MEMORY_PRESSURE_OBSERVER_TOPIC)) {
    5815           0 :     if (mPerformance) {
    5816           0 :       mPerformance->MemoryPressure();
    5817             :     }
    5818             :     return NS_OK;
    5819             :   }
    5820             : 
    5821           0 :   if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
    5822           0 :     mCurrentlyIdle = true;
    5823           0 :     if (IsFrozen()) {
    5824             :       // need to fire only one idle event while the window is frozen.
    5825           0 :       mNotifyIdleObserversIdleOnThaw = true;
    5826           0 :       mNotifyIdleObserversActiveOnThaw = false;
    5827           0 :     } else if (IsCurrentInnerWindow()) {
    5828           0 :       HandleIdleActiveEvent();
    5829             :     }
    5830             :     return NS_OK;
    5831             :   }
    5832             : 
    5833           0 :   if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_ACTIVE)) {
    5834           0 :     mCurrentlyIdle = false;
    5835           0 :     if (IsFrozen()) {
    5836           0 :       mNotifyIdleObserversActiveOnThaw = true;
    5837           0 :       mNotifyIdleObserversIdleOnThaw = false;
    5838           0 :     } else if (IsCurrentInnerWindow()) {
    5839           0 :       ScheduleActiveTimerCallback();
    5840             :     }
    5841             :     return NS_OK;
    5842             :   }
    5843             : 
    5844           0 :   if (!nsCRT::strcmp(aTopic, "offline-cache-update-added")) {
    5845           0 :     if (mApplicationCache)
    5846             :       return NS_OK;
    5847             : 
    5848             :     // Instantiate the application object now. It observes update belonging to
    5849             :     // this window's document and correctly updates the applicationCache object
    5850             :     // state.
    5851           0 :     nsCOMPtr<nsIDOMOfflineResourceList> applicationCache = GetApplicationCache();
    5852           0 :     nsCOMPtr<nsIObserver> observer = do_QueryInterface(applicationCache);
    5853           0 :     if (observer)
    5854           0 :       observer->Observe(aSubject, aTopic, aData);
    5855             : 
    5856             :     return NS_OK;
    5857             :   }
    5858             : 
    5859           0 :   if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
    5860           0 :     MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages"));
    5861             : 
    5862             :     // The user preferred languages have changed, we need to fire an event on
    5863             :     // Window object and invalidate the cache for navigator.languages. It is
    5864             :     // done for every change which can be a waste of cycles but those should be
    5865             :     // fairly rare.
    5866             :     // We MUST invalidate navigator.languages before sending the event in the
    5867             :     // very likely situation where an event handler will try to read its value.
    5868             : 
    5869           0 :     if (mNavigator) {
    5870           0 :       NavigatorBinding::ClearCachedLanguageValue(mNavigator);
    5871           0 :       NavigatorBinding::ClearCachedLanguagesValue(mNavigator);
    5872             :     }
    5873             : 
    5874             :     // The event has to be dispatched only to the current inner window.
    5875           0 :     if (!IsCurrentInnerWindow()) {
    5876             :       return NS_OK;
    5877             :     }
    5878             : 
    5879           0 :     RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
    5880           0 :     event->InitEvent(NS_LITERAL_STRING("languagechange"), false, false);
    5881           0 :     event->SetTrusted(true);
    5882             : 
    5883           0 :     ErrorResult rv;
    5884           0 :     DispatchEvent(*event, rv);
    5885           0 :     return rv.StealNSResult();
    5886             :   }
    5887             : 
    5888           0 :   NS_WARNING("unrecognized topic in nsGlobalWindowInner::Observe");
    5889           0 :   return NS_ERROR_FAILURE;
    5890             : }
    5891             : 
    5892             : void
    5893           0 : nsGlobalWindowInner::ObserveStorageNotification(StorageEvent* aEvent,
    5894             :                                                 const char16_t* aStorageType,
    5895             :                                                 bool aPrivateBrowsing)
    5896             : {
    5897           0 :   MOZ_ASSERT(aEvent);
    5898             : 
    5899             :   // The private browsing check must be done here again because this window
    5900             :   // could have changed its state before the notification check and now. This
    5901             :   // happens in case this window did have a docShell at that time.
    5902           0 :   if (aPrivateBrowsing != IsPrivateBrowsing()) {
    5903           0 :     return;
    5904             :   }
    5905             : 
    5906             :   // LocalStorage can only exist on an inner window, and we don't want to
    5907             :   // generate events on frozen or otherwise-navigated-away from windows.
    5908             :   // (Actually, this code used to try and buffer events for frozen windows,
    5909             :   // but it never worked, so we've removed it.  See bug 1285898.)
    5910           0 :   if (!IsCurrentInnerWindow() || IsFrozen()) {
    5911             :     return;
    5912             :   }
    5913             : 
    5914           0 :   nsIPrincipal *principal = GetPrincipal();
    5915           0 :   if (!principal) {
    5916             :     return;
    5917             :   }
    5918             : 
    5919           0 :   bool fireMozStorageChanged = false;
    5920           0 :   nsAutoString eventType;
    5921           0 :   eventType.AssignLiteral("storage");
    5922             : 
    5923           0 :   if (!NS_strcmp(aStorageType, u"sessionStorage")) {
    5924           0 :     nsCOMPtr<nsIDOMStorage> changingStorage = aEvent->GetStorageArea();
    5925           0 :     MOZ_ASSERT(changingStorage);
    5926             : 
    5927           0 :     bool check = false;
    5928             : 
    5929           0 :     nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(GetDocShell());
    5930           0 :     if (storageManager) {
    5931           0 :       nsresult rv = storageManager->CheckStorage(principal, changingStorage,
    5932           0 :                                                  &check);
    5933           0 :       if (NS_FAILED(rv)) {
    5934           0 :         return;
    5935             :       }
    5936             :     }
    5937             : 
    5938           0 :     if (!check) {
    5939             :       // This storage event is not coming from our storage or is coming
    5940             :       // from a different docshell, i.e. it is a clone, ignore this event.
    5941             :       return;
    5942             :     }
    5943             : 
    5944           0 :     MOZ_LOG(gDOMLeakPRLogInner, LogLevel::Debug,
    5945             :             ("nsGlobalWindowInner %p with sessionStorage %p passing event from %p",
    5946             :              this, mSessionStorage.get(), changingStorage.get()));
    5947             : 
    5948           0 :     fireMozStorageChanged = mSessionStorage == changingStorage;
    5949           0 :     if (fireMozStorageChanged) {
    5950           0 :       eventType.AssignLiteral("MozSessionStorageChanged");
    5951             :     }
    5952             :   }
    5953             : 
    5954             :   else {
    5955           0 :     MOZ_ASSERT(!NS_strcmp(aStorageType, u"localStorage"));
    5956             : 
    5957           0 :     MOZ_DIAGNOSTIC_ASSERT(StorageUtils::PrincipalsEqual(aEvent->GetPrincipal(),
    5958             :                                                         principal));
    5959             : 
    5960           0 :     fireMozStorageChanged = mLocalStorage == aEvent->GetStorageArea();
    5961             : 
    5962           0 :     if (fireMozStorageChanged) {
    5963           0 :       eventType.AssignLiteral("MozLocalStorageChanged");
    5964             :     }
    5965             :   }
    5966             : 
    5967             :   // Clone the storage event included in the observer notification. We want
    5968             :   // to dispatch clones rather than the original event.
    5969           0 :   IgnoredErrorResult error;
    5970             :   RefPtr<StorageEvent> clonedEvent =
    5971           0 :     CloneStorageEvent(eventType, aEvent, error);
    5972           0 :   if (error.Failed()) {
    5973           0 :     return;
    5974             :   }
    5975             : 
    5976           0 :   clonedEvent->SetTrusted(true);
    5977             : 
    5978           0 :   if (fireMozStorageChanged) {
    5979           0 :     WidgetEvent* internalEvent = clonedEvent->WidgetEventPtr();
    5980           0 :     internalEvent->mFlags.mOnlyChromeDispatch = true;
    5981             :   }
    5982             : 
    5983           0 :   DispatchEvent(*clonedEvent);
    5984             : }
    5985             : 
    5986             : already_AddRefed<StorageEvent>
    5987           0 : nsGlobalWindowInner::CloneStorageEvent(const nsAString& aType,
    5988             :                                        const RefPtr<StorageEvent>& aEvent,
    5989             :                                        ErrorResult& aRv)
    5990             : {
    5991           0 :   StorageEventInit dict;
    5992             : 
    5993           0 :   dict.mBubbles = aEvent->Bubbles();
    5994           0 :   dict.mCancelable = aEvent->Cancelable();
    5995           0 :   aEvent->GetKey(dict.mKey);
    5996           0 :   aEvent->GetOldValue(dict.mOldValue);
    5997           0 :   aEvent->GetNewValue(dict.mNewValue);
    5998           0 :   aEvent->GetUrl(dict.mUrl);
    5999             : 
    6000           0 :   RefPtr<Storage> storageArea = aEvent->GetStorageArea();
    6001             : 
    6002           0 :   RefPtr<Storage> storage;
    6003             : 
    6004             :   // If null, this is a localStorage event received by IPC.
    6005           0 :   if (!storageArea) {
    6006           0 :     storage = GetLocalStorage(aRv);
    6007           0 :     if (aRv.Failed() || !storage) {
    6008           0 :       return nullptr;
    6009             :     }
    6010             : 
    6011           0 :     MOZ_ASSERT(storage->Type() == Storage::eLocalStorage);
    6012             :     RefPtr<LocalStorage> localStorage =
    6013           0 :       static_cast<LocalStorage*>(storage.get());
    6014             : 
    6015             :     // We must apply the current change to the 'local' localStorage.
    6016           0 :     localStorage->ApplyEvent(aEvent);
    6017           0 :   } else if (storageArea->Type() == Storage::eSessionStorage) {
    6018           0 :     storage = GetSessionStorage(aRv);
    6019             :   } else {
    6020           0 :     MOZ_ASSERT(storageArea->Type() == Storage::eLocalStorage);
    6021           0 :     storage = GetLocalStorage(aRv);
    6022             :   }
    6023             : 
    6024           0 :   if (aRv.Failed() || !storage) {
    6025             :     return nullptr;
    6026             :   }
    6027             : 
    6028           0 :   MOZ_ASSERT(storage);
    6029           0 :   MOZ_ASSERT_IF(storageArea, storage->IsForkOf(storageArea));
    6030             : 
    6031           0 :   dict.mStorageArea = storage;
    6032             : 
    6033           0 :   RefPtr<StorageEvent> event = StorageEvent::Constructor(this, aType, dict);
    6034           0 :   return event.forget();
    6035             : }
    6036             : 
    6037             : void
    6038           0 : nsGlobalWindowInner::Suspend()
    6039             : {
    6040           0 :   MOZ_ASSERT(NS_IsMainThread());
    6041             : 
    6042             :   // We can only safely suspend windows that are the current inner window.  If
    6043             :   // its not the current inner, then we are in one of two different cases.
    6044             :   // Either we are in the bfcache or we are doomed window that is going away.
    6045             :   // When a window becomes inactive we purposely avoid placing already suspended
    6046             :   // windows into the bfcache.  It only expects windows suspended due to the
    6047             :   // Freeze() method which occurs while the window is still the current inner.
    6048             :   // So we must not call Suspend() on bfcache windows at this point or this
    6049             :   // invariant will be broken.  If the window is doomed there is no point in
    6050             :   // suspending it since it will soon be gone.
    6051           0 :   if (!IsCurrentInnerWindow()) {
    6052           0 :     return;
    6053             :   }
    6054             : 
    6055             :   // All children are also suspended.  This ensure mSuspendDepth is
    6056             :   // set properly and the timers are properly canceled for each child.
    6057           0 :   CallOnChildren(&nsGlobalWindowInner::Suspend);
    6058             : 
    6059           0 :   mSuspendDepth += 1;
    6060           0 :   if (mSuspendDepth != 1) {
    6061             :     return;
    6062             :   }
    6063             : 
    6064           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
    6065           0 :   if (ac) {
    6066           0 :     for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
    6067           0 :       ac->RemoveWindowListener(mEnabledSensors[i], this);
    6068             :   }
    6069           0 :   DisableGamepadUpdates();
    6070           0 :   DisableVRUpdates();
    6071             : 
    6072           0 :   SuspendWorkersForWindow(this);
    6073             : 
    6074           0 :   SuspendIdleRequests();
    6075             : 
    6076           0 :   mTimeoutManager->Suspend();
    6077             : 
    6078             :   // Suspend all of the AudioContexts for this window
    6079           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    6080           0 :     ErrorResult dummy;
    6081           0 :     RefPtr<Promise> d = mAudioContexts[i]->Suspend(dummy);
    6082             :   }
    6083             : }
    6084             : 
    6085             : void
    6086           0 : nsGlobalWindowInner::Resume()
    6087             : {
    6088           0 :   MOZ_ASSERT(NS_IsMainThread());
    6089             : 
    6090             :   // We can only safely resume a window if its the current inner window.  If
    6091             :   // its not the current inner, then we are in one of two different cases.
    6092             :   // Either we are in the bfcache or we are doomed window that is going away.
    6093             :   // If a window is suspended when it becomes inactive we purposely do not
    6094             :   // put it in the bfcache, so Resume should never be needed in that case.
    6095             :   // If the window is doomed then there is no point in resuming it.
    6096           0 :   if (!IsCurrentInnerWindow()) {
    6097           0 :     return;
    6098             :   }
    6099             : 
    6100             :   // Resume all children.  This restores timers recursively canceled
    6101             :   // in Suspend() and ensures all children have the correct mSuspendDepth.
    6102           0 :   CallOnChildren(&nsGlobalWindowInner::Resume);
    6103             : 
    6104           0 :   MOZ_ASSERT(mSuspendDepth != 0);
    6105           0 :   mSuspendDepth -= 1;
    6106           0 :   if (mSuspendDepth != 0) {
    6107             :     return;
    6108             :   }
    6109             : 
    6110             :   // We should not be able to resume a frozen window.  It must be Thaw()'d first.
    6111           0 :   MOZ_ASSERT(mFreezeDepth == 0);
    6112             : 
    6113           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
    6114           0 :   if (ac) {
    6115           0 :     for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
    6116           0 :       ac->AddWindowListener(mEnabledSensors[i], this);
    6117             :   }
    6118           0 :   EnableGamepadUpdates();
    6119           0 :   EnableVRUpdates();
    6120             : 
    6121             :   // Resume all of the AudioContexts for this window
    6122           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    6123           0 :     ErrorResult dummy;
    6124           0 :     RefPtr<Promise> d = mAudioContexts[i]->Resume(dummy);
    6125             :   }
    6126             : 
    6127           0 :   mTimeoutManager->Resume();
    6128             : 
    6129           0 :   ResumeIdleRequests();
    6130             : 
    6131             :   // Resume all of the workers for this window.  We must do this
    6132             :   // after timeouts since workers may have queued events that can trigger
    6133             :   // a setTimeout().
    6134           0 :   ResumeWorkersForWindow(this);
    6135             : }
    6136             : 
    6137             : bool
    6138          14 : nsGlobalWindowInner::IsSuspended() const
    6139             : {
    6140          14 :   MOZ_ASSERT(NS_IsMainThread());
    6141           0 :   return mSuspendDepth != 0;
    6142             : }
    6143             : 
    6144             : void
    6145           0 : nsGlobalWindowInner::Freeze()
    6146             : {
    6147           0 :   MOZ_ASSERT(NS_IsMainThread());
    6148           0 :   Suspend();
    6149           0 :   FreezeInternal();
    6150           0 : }
    6151             : 
    6152             : void
    6153           0 : nsGlobalWindowInner::FreezeInternal()
    6154             : {
    6155           0 :   MOZ_ASSERT(NS_IsMainThread());
    6156           0 :   MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow());
    6157           0 :   MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
    6158             : 
    6159           0 :   CallOnChildren(&nsGlobalWindowInner::FreezeInternal);
    6160             : 
    6161           0 :   mFreezeDepth += 1;
    6162           0 :   MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
    6163           0 :   if (mFreezeDepth != 1) {
    6164             :     return;
    6165             :   }
    6166             : 
    6167           0 :   FreezeWorkersForWindow(this);
    6168             : 
    6169           0 :   mTimeoutManager->Freeze();
    6170           0 :   if (mClientSource) {
    6171           0 :     mClientSource->Freeze();
    6172             :   }
    6173             : 
    6174           0 :   NotifyDOMWindowFrozen(this);
    6175             : }
    6176             : 
    6177             : void
    6178           0 : nsGlobalWindowInner::Thaw()
    6179             : {
    6180           0 :   MOZ_ASSERT(NS_IsMainThread());
    6181           0 :   ThawInternal();
    6182           0 :   Resume();
    6183           0 : }
    6184             : 
    6185             : void
    6186           0 : nsGlobalWindowInner::ThawInternal()
    6187             : {
    6188           0 :   MOZ_ASSERT(NS_IsMainThread());
    6189           0 :   MOZ_DIAGNOSTIC_ASSERT(IsCurrentInnerWindow());
    6190           0 :   MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
    6191             : 
    6192           0 :   CallOnChildren(&nsGlobalWindowInner::ThawInternal);
    6193             : 
    6194           0 :   MOZ_ASSERT(mFreezeDepth != 0);
    6195           0 :   mFreezeDepth -= 1;
    6196           0 :   MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
    6197           0 :   if (mFreezeDepth != 0) {
    6198             :     return;
    6199             :   }
    6200             : 
    6201           0 :   if (mClientSource) {
    6202           0 :     mClientSource->Thaw();
    6203             :   }
    6204           0 :   mTimeoutManager->Thaw();
    6205             : 
    6206           0 :   ThawWorkersForWindow(this);
    6207             : 
    6208           0 :   NotifyDOMWindowThawed(this);
    6209             : }
    6210             : 
    6211             : bool
    6212          29 : nsGlobalWindowInner::IsFrozen() const
    6213             : {
    6214          29 :   MOZ_ASSERT(NS_IsMainThread());
    6215           0 :   bool frozen = mFreezeDepth != 0;
    6216           0 :   MOZ_ASSERT_IF(frozen, IsSuspended());
    6217           0 :   return frozen;
    6218             : }
    6219             : 
    6220             : void
    6221          14 : nsGlobalWindowInner::SyncStateFromParentWindow()
    6222             : {
    6223             :   // This method should only be called on an inner window that has been
    6224             :   // assigned to an outer window already.
    6225          14 :   MOZ_ASSERT(IsCurrentInnerWindow());
    6226           0 :   nsPIDOMWindowOuter* outer = GetOuterWindow();
    6227           0 :   MOZ_ASSERT(outer);
    6228             : 
    6229             :   // Attempt to find our parent windows.
    6230          28 :   nsCOMPtr<Element> frame = outer->GetFrameElementInternal();
    6231           0 :   nsPIDOMWindowOuter* parentOuter = frame ? frame->OwnerDoc()->GetWindow()
    6232           0 :                                           : nullptr;
    6233             :   nsGlobalWindowInner* parentInner =
    6234          14 :     parentOuter ? nsGlobalWindowInner::Cast(parentOuter->GetCurrentInnerWindow())
    6235           0 :                 : nullptr;
    6236             : 
    6237             :   // If our outer is in a modal state, but our parent is not in a modal
    6238             :   // state, then we must apply the suspend directly.  If our parent is
    6239             :   // in a modal state then we should get the suspend automatically
    6240             :   // via the parentSuspendDepth application below.
    6241          14 :   if ((!parentInner || !parentInner->IsInModalState()) && IsInModalState()) {
    6242           0 :     Suspend();
    6243             :   }
    6244             : 
    6245          14 :   uint32_t parentFreezeDepth = parentInner ? parentInner->mFreezeDepth : 0;
    6246           0 :   uint32_t parentSuspendDepth = parentInner ? parentInner->mSuspendDepth : 0;
    6247             : 
    6248             :   // Since every Freeze() calls Suspend(), the suspend count must
    6249             :   // be equal or greater to the freeze count.
    6250          14 :   MOZ_ASSERT(parentFreezeDepth <= parentSuspendDepth);
    6251             : 
    6252             :   // First apply the Freeze() calls.
    6253          14 :   for (uint32_t i = 0; i < parentFreezeDepth; ++i) {
    6254           0 :     Freeze();
    6255             :   }
    6256             : 
    6257             :   // Now apply only the number of Suspend() calls to reach the target
    6258             :   // suspend count after applying the Freeze() calls.
    6259          14 :   for (uint32_t i = 0; i < (parentSuspendDepth - parentFreezeDepth); ++i) {
    6260           0 :     Suspend();
    6261             :   }
    6262          14 : }
    6263             : 
    6264             : template<typename Method, typename... Args>
    6265             : nsGlobalWindowInner::CallState
    6266           0 : nsGlobalWindowInner::CallOnChildren(Method aMethod, Args& ...aArgs)
    6267             : {
    6268           0 :   MOZ_ASSERT(NS_IsMainThread());
    6269           0 :   MOZ_ASSERT(IsCurrentInnerWindow());
    6270             : 
    6271           0 :   CallState state = CallState::Continue;
    6272             : 
    6273           0 :   nsCOMPtr<nsIDocShell> docShell = GetDocShell();
    6274           0 :   if (!docShell) {
    6275             :     return state;
    6276             :   }
    6277             : 
    6278           0 :   int32_t childCount = 0;
    6279           0 :   docShell->GetChildCount(&childCount);
    6280             : 
    6281             :   // Take a copy of the current children so that modifications to
    6282             :   // the child list don't affect to the iteration.
    6283           0 :   AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> children;
    6284           0 :   for (int32_t i = 0; i < childCount; ++i) {
    6285           0 :     nsCOMPtr<nsIDocShellTreeItem> childShell;
    6286           0 :     docShell->GetChildAt(i, getter_AddRefs(childShell));
    6287           0 :     if (childShell) {
    6288           0 :       children.AppendElement(childShell);
    6289             :     }
    6290             :   }
    6291             : 
    6292           0 :   for (nsCOMPtr<nsIDocShellTreeItem> childShell : children) {
    6293           0 :     nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow();
    6294           0 :     if (!pWin) {
    6295           0 :       continue;
    6296             :     }
    6297             : 
    6298           0 :     auto* win = nsGlobalWindowOuter::Cast(pWin);
    6299           0 :     nsGlobalWindowInner* inner = win->GetCurrentInnerWindowInternal();
    6300             : 
    6301             :     // This is a bit hackish. Only freeze/suspend windows which are truly our
    6302             :     // subwindows.
    6303           0 :     nsCOMPtr<Element> frame = pWin->GetFrameElementInternal();
    6304           0 :     if (!mDoc || !frame || mDoc != frame->OwnerDoc() || !inner) {
    6305           0 :       continue;
    6306             :     }
    6307             : 
    6308             :     // Call the child method using our helper CallChild() template method.
    6309             :     // This allows us to handle both void returning methods and methods
    6310             :     // that return CallState explicitly.  For void returning methods we
    6311             :     // assume CallState::Continue.
    6312             :     typedef decltype((inner->*aMethod)(aArgs...)) returnType;
    6313           0 :     state = CallChild<returnType>(inner, aMethod, aArgs...);
    6314             : 
    6315           0 :     if (state == CallState::Stop) {
    6316           0 :       return state;
    6317             :     }
    6318             :   }
    6319             : 
    6320           0 :   return state;
    6321             : }
    6322             : 
    6323             : Maybe<ClientInfo>
    6324          99 : nsGlobalWindowInner::GetClientInfo() const
    6325             : {
    6326          99 :   MOZ_ASSERT(NS_IsMainThread());
    6327           0 :   Maybe<ClientInfo> clientInfo;
    6328           0 :   if (mClientSource) {
    6329           0 :     clientInfo.emplace(mClientSource->Info());
    6330             :   }
    6331          99 :   return clientInfo;
    6332             : }
    6333             : 
    6334             : Maybe<ClientState>
    6335           0 : nsGlobalWindowInner::GetClientState() const
    6336             : {
    6337           0 :   MOZ_ASSERT(NS_IsMainThread());
    6338           0 :   Maybe<ClientState> clientState;
    6339           0 :   if (mClientSource) {
    6340           0 :     ClientState state;
    6341           0 :     nsresult rv = mClientSource->SnapshotState(&state);
    6342           0 :     if (NS_SUCCEEDED(rv)) {
    6343           0 :       clientState.emplace(state);
    6344             :     }
    6345             :   }
    6346           0 :   return clientState;
    6347             : }
    6348             : 
    6349             : Maybe<ServiceWorkerDescriptor>
    6350         104 : nsGlobalWindowInner::GetController() const
    6351             : {
    6352         104 :   MOZ_ASSERT(NS_IsMainThread());
    6353           0 :   Maybe<ServiceWorkerDescriptor> controller;
    6354           0 :   if (mClientSource) {
    6355           0 :     controller = mClientSource->GetController();
    6356             :   }
    6357         104 :   return controller;
    6358             : }
    6359             : 
    6360             : RefPtr<ServiceWorker>
    6361           0 : nsGlobalWindowInner::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor)
    6362             : {
    6363           0 :   MOZ_ASSERT(NS_IsMainThread());
    6364           0 :   RefPtr<ServiceWorker> ref;
    6365           0 :   ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget, bool* aDoneOut) {
    6366           0 :     RefPtr<ServiceWorker> sw = do_QueryObject(aTarget);
    6367           0 :     if (!sw || !sw->Descriptor().Matches(aDescriptor)) {
    6368           0 :       return;
    6369             :     }
    6370             : 
    6371           0 :     ref = sw.forget();
    6372           0 :     *aDoneOut = true;
    6373           0 :   });
    6374             : 
    6375           0 :   if (!ref) {
    6376           0 :     ref = ServiceWorker::Create(this, aDescriptor);
    6377             :   }
    6378             : 
    6379           0 :   return ref.forget();
    6380             : }
    6381             : 
    6382             : RefPtr<ServiceWorkerRegistration>
    6383           0 : nsGlobalWindowInner::GetOrCreateServiceWorkerRegistration(const ServiceWorkerRegistrationDescriptor& aDescriptor)
    6384             : {
    6385           0 :   MOZ_ASSERT(NS_IsMainThread());
    6386           0 :   RefPtr<ServiceWorkerRegistration> ref;
    6387           0 :   ForEachEventTargetObject([&] (DOMEventTargetHelper* aTarget, bool* aDoneOut) {
    6388           0 :     RefPtr<ServiceWorkerRegistration> swr = do_QueryObject(aTarget);
    6389           0 :     if (!swr || !swr->MatchesDescriptor(aDescriptor)) {
    6390           0 :       return;
    6391             :     }
    6392             : 
    6393           0 :     ref = swr.forget();
    6394           0 :     *aDoneOut = true;
    6395           0 :   });
    6396             : 
    6397           0 :   if (!ref) {
    6398           0 :     ref = ServiceWorkerRegistration::CreateForMainThread(this, aDescriptor);
    6399             :   }
    6400             : 
    6401           0 :   return ref.forget();
    6402             : }
    6403             : 
    6404             : nsresult
    6405           0 : nsGlobalWindowInner::FireDelayedDOMEvents()
    6406             : {
    6407           0 :   if (mApplicationCache) {
    6408           0 :     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->FirePendingEvents();
    6409             :   }
    6410             : 
    6411             :   // Fires an offline status event if the offline status has changed
    6412           0 :   FireOfflineStatusEventIfChanged();
    6413             : 
    6414           0 :   if (mNotifyIdleObserversIdleOnThaw) {
    6415           0 :     mNotifyIdleObserversIdleOnThaw = false;
    6416           0 :     HandleIdleActiveEvent();
    6417             :   }
    6418             : 
    6419           0 :   if (mNotifyIdleObserversActiveOnThaw) {
    6420           0 :     mNotifyIdleObserversActiveOnThaw = false;
    6421           0 :     ScheduleActiveTimerCallback();
    6422             :   }
    6423             : 
    6424           0 :   nsCOMPtr<nsIDocShell> docShell = GetDocShell();
    6425           0 :   if (docShell) {
    6426           0 :     int32_t childCount = 0;
    6427           0 :     docShell->GetChildCount(&childCount);
    6428             : 
    6429             :     // Take a copy of the current children so that modifications to
    6430             :     // the child list don't affect to the iteration.
    6431           0 :     AutoTArray<nsCOMPtr<nsIDocShellTreeItem>, 8> children;
    6432           0 :     for (int32_t i = 0; i < childCount; ++i) {
    6433           0 :       nsCOMPtr<nsIDocShellTreeItem> childShell;
    6434           0 :       docShell->GetChildAt(i, getter_AddRefs(childShell));
    6435           0 :       if (childShell) {
    6436           0 :         children.AppendElement(childShell);
    6437             :       }
    6438             :     }
    6439             : 
    6440           0 :     for (nsCOMPtr<nsIDocShellTreeItem> childShell : children) {
    6441           0 :       if (nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow()) {
    6442           0 :         auto* win = nsGlobalWindowOuter::Cast(pWin);
    6443           0 :         win->FireDelayedDOMEvents();
    6444             :       }
    6445             :     }
    6446             :   }
    6447             : 
    6448           0 :   return NS_OK;
    6449             : }
    6450             : 
    6451             : //*****************************************************************************
    6452             : // nsGlobalWindowInner: Window Control Functions
    6453             : //*****************************************************************************
    6454             : 
    6455             : nsPIDOMWindowOuter*
    6456           3 : nsGlobalWindowInner::GetParentInternal()
    6457             : {
    6458           3 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    6459           0 :   if (!outer) {
    6460             :     // No outer window available!
    6461             :     return nullptr;
    6462             :   }
    6463           3 :   return outer->GetParentInternal();
    6464             : }
    6465             : 
    6466             : //*****************************************************************************
    6467             : // nsGlobalWindowInner: Timeout Functions
    6468             : //*****************************************************************************
    6469             : 
    6470             : nsGlobalWindowInner*
    6471           0 : nsGlobalWindowInner::InnerForSetTimeoutOrInterval(ErrorResult& aError)
    6472             : {
    6473           0 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    6474           0 :   nsGlobalWindowInner* currentInner = outer ? outer->GetCurrentInnerWindowInternal() : this;
    6475             : 
    6476             :   // If forwardTo is not the window with an active document then we want the
    6477             :   // call to setTimeout/Interval to be a noop, so return null but don't set an
    6478             :   // error.
    6479           0 :   return HasActiveDocument() ? currentInner : nullptr;
    6480             : }
    6481             : 
    6482             : int32_t
    6483           0 : nsGlobalWindowInner::SetTimeout(JSContext* aCx, Function& aFunction,
    6484             :                                 int32_t aTimeout,
    6485             :                                 const Sequence<JS::Value>& aArguments,
    6486             :                                 ErrorResult& aError)
    6487             : {
    6488             :   return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, false,
    6489           0 :                               aError);
    6490             : }
    6491             : 
    6492             : int32_t
    6493           0 : nsGlobalWindowInner::SetTimeout(JSContext* aCx, const nsAString& aHandler,
    6494             :                                 int32_t aTimeout,
    6495             :                                 const Sequence<JS::Value>& /* unused */,
    6496             :                                 ErrorResult& aError)
    6497             : {
    6498           0 :   return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError);
    6499             : }
    6500             : 
    6501             : int32_t
    6502           0 : nsGlobalWindowInner::SetInterval(JSContext* aCx, Function& aFunction,
    6503             :                                  const int32_t aTimeout,
    6504             :                                  const Sequence<JS::Value>& aArguments,
    6505             :                                  ErrorResult& aError)
    6506             : {
    6507             :   return SetTimeoutOrInterval(
    6508           0 :     aCx, aFunction, aTimeout, aArguments, true, aError);
    6509             : }
    6510             : 
    6511             : int32_t
    6512           0 : nsGlobalWindowInner::SetInterval(JSContext* aCx, const nsAString& aHandler,
    6513             :                                  const int32_t aTimeout,
    6514             :                                  const Sequence<JS::Value>& /* unused */,
    6515             :                                  ErrorResult& aError)
    6516             : {
    6517           0 :   return SetTimeoutOrInterval(aCx, aHandler, aTimeout, true, aError);
    6518             : }
    6519             : 
    6520             : int32_t
    6521           0 : nsGlobalWindowInner::SetTimeoutOrInterval(JSContext *aCx, Function& aFunction,
    6522             :                                           int32_t aTimeout,
    6523             :                                           const Sequence<JS::Value>& aArguments,
    6524             :                                           bool aIsInterval, ErrorResult& aError)
    6525             : {
    6526           0 :   nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError);
    6527           0 :   if (!inner) {
    6528             :     return -1;
    6529             :   }
    6530             : 
    6531           0 :   if (inner != this) {
    6532           0 :     return inner->SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments,
    6533           0 :                                        aIsInterval, aError);
    6534             :   }
    6535             : 
    6536             :   nsCOMPtr<nsIScriptTimeoutHandler> handler =
    6537           0 :     NS_CreateJSTimeoutHandler(aCx, this, aFunction, aArguments, aError);
    6538           0 :   if (!handler) {
    6539             :     return 0;
    6540             :   }
    6541             : 
    6542             :   int32_t result;
    6543           0 :   aError = mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
    6544             :                                       Timeout::Reason::eTimeoutOrInterval,
    6545           0 :                                       &result);
    6546           0 :   return result;
    6547             : }
    6548             : 
    6549             : int32_t
    6550           0 : nsGlobalWindowInner::SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler,
    6551             :                                           int32_t aTimeout, bool aIsInterval,
    6552             :                                           ErrorResult& aError)
    6553             : {
    6554           0 :   nsGlobalWindowInner* inner = InnerForSetTimeoutOrInterval(aError);
    6555           0 :   if (!inner) {
    6556             :     return -1;
    6557             :   }
    6558             : 
    6559           0 :   if (inner != this) {
    6560           0 :     return inner->SetTimeoutOrInterval(aCx, aHandler, aTimeout, aIsInterval,
    6561           0 :                                        aError);
    6562             :   }
    6563             : 
    6564             :   nsCOMPtr<nsIScriptTimeoutHandler> handler =
    6565           0 :     NS_CreateJSTimeoutHandler(aCx, this, aHandler, aError);
    6566           0 :   if (!handler) {
    6567             :     return 0;
    6568             :   }
    6569             : 
    6570             :   int32_t result;
    6571           0 :   aError = mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
    6572             :                                       Timeout::Reason::eTimeoutOrInterval,
    6573           0 :                                       &result);
    6574           0 :   return result;
    6575             : }
    6576             : 
    6577             : bool
    6578           0 : nsGlobalWindowInner::RunTimeoutHandler(Timeout* aTimeout,
    6579             :                                        nsIScriptContext* aScx)
    6580             : {
    6581             :   // Hold on to the timeout in case mExpr or mFunObj releases its
    6582             :   // doc.
    6583           0 :   RefPtr<Timeout> timeout = aTimeout;
    6584           0 :   Timeout* last_running_timeout = mTimeoutManager->BeginRunningTimeout(timeout);
    6585           0 :   timeout->mRunning = true;
    6586             : 
    6587             :   // Push this timeout's popup control state, which should only be
    6588             :   // eabled the first time a timeout fires that was created while
    6589             :   // popups were enabled and with a delay less than
    6590             :   // "dom.disable_open_click_delay".
    6591           0 :   nsAutoPopupStatePusher popupStatePusher(timeout->mPopupState);
    6592             : 
    6593             :   // Clear the timeout's popup state, if any, to prevent interval
    6594             :   // timeouts from repeatedly opening poups.
    6595           0 :   timeout->mPopupState = openAbused;
    6596             : 
    6597           0 :   bool trackNestingLevel = !timeout->mIsInterval;
    6598             :   uint32_t nestingLevel;
    6599           0 :   if (trackNestingLevel) {
    6600           0 :     nestingLevel = TimeoutManager::GetNestingLevel();
    6601           0 :     TimeoutManager::SetNestingLevel(timeout->mNestingLevel);
    6602             :   }
    6603             : 
    6604             :   const char *reason;
    6605           0 :   if (timeout->mIsInterval) {
    6606             :     reason = "setInterval handler";
    6607             :   } else {
    6608           0 :     reason = "setTimeout handler";
    6609             :   }
    6610             : 
    6611           0 :   bool abortIntervalHandler = false;
    6612           0 :   nsCOMPtr<nsIScriptTimeoutHandler> handler(do_QueryInterface(timeout->mScriptHandler));
    6613           0 :   if (handler) {
    6614           0 :     RefPtr<Function> callback = handler->GetCallback();
    6615             : 
    6616           0 :     if (!callback) {
    6617             :       // Evaluate the timeout expression.
    6618           0 :       const nsAString& script = handler->GetHandlerText();
    6619             : 
    6620           0 :       const char* filename = nullptr;
    6621           0 :       uint32_t lineNo = 0, dummyColumn = 0;
    6622           0 :       handler->GetLocation(&filename, &lineNo, &dummyColumn);
    6623             : 
    6624             :       // New script entry point required, due to the "Create a script" sub-step of
    6625             :       // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps
    6626           0 :       nsAutoMicroTask mt;
    6627           0 :       AutoEntryScript aes(this, reason, true);
    6628           0 :       JS::CompileOptions options(aes.cx());
    6629           0 :       options.setFileAndLine(filename, lineNo);
    6630           0 :       options.setNoScriptRval(true);
    6631           0 :       JS::Rooted<JSObject*> global(aes.cx(), FastGetGlobalJSObject());
    6632           0 :       nsresult rv = NS_OK;
    6633             :       {
    6634           0 :         nsJSUtils::ExecutionContext exec(aes.cx(), global);
    6635           0 :         rv = exec.CompileAndExec(options, script);
    6636             :       }
    6637             : 
    6638           0 :       if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) {
    6639           0 :         abortIntervalHandler = true;
    6640             :       }
    6641             :     } else {
    6642             :       // Hold strong ref to ourselves while we call the callback.
    6643           0 :       nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow*>(this));
    6644           0 :       ErrorResult rv;
    6645           0 :       JS::Rooted<JS::Value> ignoredVal(RootingCx());
    6646           0 :       callback->Call(me, handler->GetArgs(), &ignoredVal, rv, reason);
    6647           0 :       if (rv.IsUncatchableException()) {
    6648           0 :         abortIntervalHandler = true;
    6649             :       }
    6650             : 
    6651           0 :       rv.SuppressException();
    6652             :     }
    6653             :   } else {
    6654           0 :     nsCOMPtr<nsITimeoutHandler> basicHandler(timeout->mScriptHandler);
    6655           0 :     nsCOMPtr<nsISupports> kungFuDeathGrip(static_cast<nsIDOMWindow*>(this));
    6656             :     mozilla::Unused << kungFuDeathGrip;
    6657           0 :     basicHandler->Call();
    6658             :   }
    6659             : 
    6660             :   // If we received an uncatchable exception, do not schedule the timeout again.
    6661             :   // This allows the slow script dialog to break easy DoS attacks like
    6662             :   // setInterval(function() { while(1); }, 100);
    6663           0 :   if (abortIntervalHandler) {
    6664             :     // If it wasn't an interval timer to begin with, this does nothing.  If it
    6665             :     // was, we'll treat it as a timeout that we just ran and discard it when
    6666             :     // we return.
    6667           0 :     timeout->mIsInterval = false;
    6668             :    }
    6669             : 
    6670             :   // We ignore any failures from calling EvaluateString() on the context or
    6671             :   // Call() on a Function here since we're in a loop
    6672             :   // where we're likely to be running timeouts whose OS timers
    6673             :   // didn't fire in time and we don't want to not fire those timers
    6674             :   // now just because execution of one timer failed. We can't
    6675             :   // propagate the error to anyone who cares about it from this
    6676             :   // point anyway, and the script context should have already reported
    6677             :   // the script error in the usual way - so we just drop it.
    6678             : 
    6679           0 :   if (trackNestingLevel) {
    6680             :     TimeoutManager::SetNestingLevel(nestingLevel);
    6681             :   }
    6682             : 
    6683           0 :   mTimeoutManager->EndRunningTimeout(last_running_timeout);
    6684           0 :   timeout->mRunning = false;
    6685             : 
    6686           0 :   return timeout->mCleared;
    6687             : }
    6688             : 
    6689             : //*****************************************************************************
    6690             : // nsGlobalWindowInner: Helper Functions
    6691             : //*****************************************************************************
    6692             : 
    6693             : already_AddRefed<nsIDocShellTreeOwner>
    6694           3 : nsGlobalWindowInner::GetTreeOwner()
    6695             : {
    6696           6 :   FORWARD_TO_OUTER(GetTreeOwner, (), nullptr);
    6697             : }
    6698             : 
    6699             : already_AddRefed<nsIWebBrowserChrome>
    6700           3 : nsGlobalWindowInner::GetWebBrowserChrome()
    6701             : {
    6702           6 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
    6703             : 
    6704           9 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(treeOwner);
    6705           0 :   return browserChrome.forget();
    6706             : }
    6707             : 
    6708             : nsIScrollableFrame *
    6709           0 : nsGlobalWindowInner::GetScrollFrame()
    6710             : {
    6711           0 :   FORWARD_TO_OUTER(GetScrollFrame, (), nullptr);
    6712             : }
    6713             : 
    6714             : bool
    6715           0 : nsGlobalWindowInner::IsPrivateBrowsing()
    6716             : {
    6717           0 :   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(GetDocShell());
    6718           0 :   return loadContext && loadContext->UsePrivateBrowsing();
    6719             : }
    6720             : 
    6721             : void
    6722           0 : nsGlobalWindowInner::FlushPendingNotifications(FlushType aType)
    6723             : {
    6724           0 :   if (mDoc) {
    6725           0 :     mDoc->FlushPendingNotifications(aType);
    6726             :   }
    6727           0 : }
    6728             : 
    6729             : void
    6730           0 : nsGlobalWindowInner::EnableDeviceSensor(uint32_t aType)
    6731             : {
    6732           0 :   bool alreadyEnabled = false;
    6733           0 :   for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
    6734           0 :     if (mEnabledSensors[i] == aType) {
    6735             :       alreadyEnabled = true;
    6736             :       break;
    6737             :     }
    6738             :   }
    6739             : 
    6740           0 :   mEnabledSensors.AppendElement(aType);
    6741             : 
    6742           0 :   if (alreadyEnabled) {
    6743           0 :     return;
    6744             :   }
    6745             : 
    6746           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
    6747           0 :   if (ac) {
    6748           0 :     ac->AddWindowListener(aType, this);
    6749             :   }
    6750             : }
    6751             : 
    6752             : void
    6753           0 : nsGlobalWindowInner::DisableDeviceSensor(uint32_t aType)
    6754             : {
    6755           0 :   int32_t doomedElement = -1;
    6756           0 :   int32_t listenerCount = 0;
    6757           0 :   for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
    6758           0 :     if (mEnabledSensors[i] == aType) {
    6759           0 :       doomedElement = i;
    6760           0 :       listenerCount++;
    6761             :     }
    6762             :   }
    6763             : 
    6764           0 :   if (doomedElement == -1) {
    6765           0 :     return;
    6766             :   }
    6767             : 
    6768           0 :   mEnabledSensors.RemoveElementAt(doomedElement);
    6769             : 
    6770           0 :   if (listenerCount > 1) {
    6771             :     return;
    6772             :   }
    6773             : 
    6774           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
    6775           0 :   if (ac) {
    6776           0 :     ac->RemoveWindowListener(aType, this);
    6777             :   }
    6778             : }
    6779             : 
    6780             : #if defined(MOZ_WIDGET_ANDROID)
    6781             : void
    6782             : nsGlobalWindowInner::EnableOrientationChangeListener()
    6783             : {
    6784             :   // XXX: mDocShell is never set on the inner window?
    6785             :   nsIDocShell* docShell = nullptr;
    6786             :   if (!nsContentUtils::ShouldResistFingerprinting(docShell) &&
    6787             :       !mOrientationChangeObserver) {
    6788             :     mOrientationChangeObserver =
    6789             :       MakeUnique<WindowOrientationObserver>(this);
    6790             :   }
    6791             : }
    6792             : 
    6793             : void
    6794             : nsGlobalWindowInner::DisableOrientationChangeListener()
    6795             : {
    6796             :   mOrientationChangeObserver = nullptr;
    6797             : }
    6798             : #endif
    6799             : 
    6800             : void
    6801           0 : nsGlobalWindowInner::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
    6802             : {
    6803           0 :   mHasGamepad = aHasGamepad;
    6804           0 :   if (aHasGamepad) {
    6805           0 :     EnableGamepadUpdates();
    6806             :   }
    6807           0 : }
    6808             : 
    6809             : 
    6810             : void
    6811          53 : nsGlobalWindowInner::EventListenerAdded(nsAtom* aType)
    6812             : {
    6813         106 :   if (aType == nsGkAtoms::onvrdisplayactivate ||
    6814           0 :       aType == nsGkAtoms::onvrdisplayconnect ||
    6815           0 :       aType == nsGkAtoms::onvrdisplaydeactivate ||
    6816           0 :       aType == nsGkAtoms::onvrdisplaydisconnect ||
    6817           0 :       aType == nsGkAtoms::onvrdisplaypresentchange) {
    6818           0 :     NotifyVREventListenerAdded();
    6819             :   }
    6820             : 
    6821          53 :   if (aType == nsGkAtoms::onvrdisplayactivate) {
    6822           0 :     mHasVRDisplayActivateEvents = true;
    6823             :   }
    6824             : 
    6825         106 :   if (aType == nsGkAtoms::onbeforeunload &&
    6826           0 :       mTabChild &&
    6827           0 :       (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
    6828           0 :     mBeforeUnloadListenerCount++;
    6829           0 :     MOZ_ASSERT(mBeforeUnloadListenerCount > 0);
    6830           0 :     mTabChild->BeforeUnloadAdded();
    6831             :   }
    6832             : 
    6833             :   // We need to initialize localStorage in order to receive notifications.
    6834          53 :   if (aType == nsGkAtoms::onstorage) {
    6835           0 :     ErrorResult rv;
    6836           0 :     GetLocalStorage(rv);
    6837           0 :     rv.SuppressException();
    6838             :   }
    6839          53 : }
    6840             : 
    6841             : void
    6842           3 : nsGlobalWindowInner::EventListenerRemoved(nsAtom* aType)
    6843             : {
    6844           6 :   if (aType == nsGkAtoms::onbeforeunload &&
    6845           0 :       mTabChild &&
    6846           0 :       (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
    6847           0 :     mBeforeUnloadListenerCount--;
    6848           0 :     MOZ_ASSERT(mBeforeUnloadListenerCount >= 0);
    6849           0 :     mTabChild->BeforeUnloadRemoved();
    6850             :   }
    6851           3 : }
    6852             : 
    6853             : void
    6854           0 : nsGlobalWindowInner::NotifyVREventListenerAdded()
    6855             : {
    6856           0 :   mHasVREvents = true;
    6857           0 :   EnableVRUpdates();
    6858           0 : }
    6859             : 
    6860             : bool
    6861           0 : nsGlobalWindowInner::HasUsedVR() const
    6862             : {
    6863             :   // Returns true only if any WebVR API call or related event
    6864             :   // has been used
    6865           0 :   return mHasVREvents;
    6866             : }
    6867             : 
    6868             : bool
    6869           0 : nsGlobalWindowInner::IsVRContentDetected() const
    6870             : {
    6871             :   // Returns true only if the content will respond to
    6872             :   // the VRDisplayActivate event.
    6873           0 :   return mHasVRDisplayActivateEvents;
    6874             : }
    6875             : 
    6876             : bool
    6877           0 : nsGlobalWindowInner::IsVRContentPresenting() const
    6878             : {
    6879           0 :   for (const auto& display : mVRDisplays) {
    6880           0 :     if (display->IsAnyPresenting(gfx::kVRGroupAll)) {
    6881           0 :       return true;
    6882             :     }
    6883             :   }
    6884           0 :   return false;
    6885             : }
    6886             : 
    6887             : void
    6888           0 : nsGlobalWindowInner::AddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const
    6889             : {
    6890           0 :   aWindowSizes.mDOMOtherSize += aWindowSizes.mState.mMallocSizeOf(this);
    6891           0 :   aWindowSizes.mDOMOtherSize +=
    6892           0 :     nsIGlobalObject::ShallowSizeOfExcludingThis(aWindowSizes.mState.mMallocSizeOf);
    6893             : 
    6894           0 :   EventListenerManager* elm = GetExistingListenerManager();
    6895           0 :   if (elm) {
    6896           0 :     aWindowSizes.mDOMOtherSize +=
    6897           0 :       elm->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
    6898           0 :     aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
    6899             :   }
    6900           0 :   if (mDoc) {
    6901             :     // Multiple global windows can share a document. So only measure the
    6902             :     // document if it (a) doesn't have a global window, or (b) it's the
    6903             :     // primary document for the window.
    6904           0 :     if (!mDoc->GetInnerWindow() ||
    6905           0 :         mDoc->GetInnerWindow() == this) {
    6906           0 :       mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
    6907             :     }
    6908             :   }
    6909             : 
    6910           0 :   if (mNavigator) {
    6911           0 :     aWindowSizes.mDOMOtherSize +=
    6912           0 :       mNavigator->SizeOfIncludingThis(aWindowSizes.mState.mMallocSizeOf);
    6913             :   }
    6914             : 
    6915           0 :   ForEachEventTargetObject([&] (DOMEventTargetHelper* et, bool* aDoneOut) {
    6916           0 :     if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
    6917           0 :       aWindowSizes.mDOMEventTargetsSize +=
    6918           0 :         iSizeOf->SizeOfEventTargetIncludingThis(
    6919           0 :           aWindowSizes.mState.mMallocSizeOf);
    6920             :     }
    6921           0 :     if (EventListenerManager* elm = et->GetExistingListenerManager()) {
    6922           0 :       aWindowSizes.mDOMEventListenersCount += elm->ListenerCount();
    6923             :     }
    6924           0 :     ++aWindowSizes.mDOMEventTargetsCount;
    6925           0 :   });
    6926             : 
    6927           0 :   if (mPerformance) {
    6928           0 :     aWindowSizes.mDOMPerformanceUserEntries =
    6929           0 :       mPerformance->SizeOfUserEntries(aWindowSizes.mState.mMallocSizeOf);
    6930           0 :     aWindowSizes.mDOMPerformanceResourceEntries =
    6931           0 :       mPerformance->SizeOfResourceEntries(aWindowSizes.mState.mMallocSizeOf);
    6932             :   }
    6933             : 
    6934           0 :   aWindowSizes.mDOMOtherSize +=
    6935           0 :     mPendingPromises.ShallowSizeOfExcludingThis(aWindowSizes.mState.mMallocSizeOf);
    6936           0 : }
    6937             : 
    6938             : void
    6939           0 : nsGlobalWindowInner::AddGamepad(uint32_t aIndex, Gamepad* aGamepad)
    6940             : {
    6941             :   // Create the index we will present to content based on which indices are
    6942             :   // already taken, as required by the spec.
    6943             :   // https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index
    6944           0 :   int index = 0;
    6945           0 :   while(mGamepadIndexSet.Contains(index)) {
    6946           0 :     ++index;
    6947             :   }
    6948           0 :   mGamepadIndexSet.Put(index);
    6949           0 :   aGamepad->SetIndex(index);
    6950           0 :   mGamepads.Put(aIndex, aGamepad);
    6951           0 : }
    6952             : 
    6953             : void
    6954           0 : nsGlobalWindowInner::RemoveGamepad(uint32_t aIndex)
    6955             : {
    6956           0 :   RefPtr<Gamepad> gamepad;
    6957           0 :   if (!mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
    6958           0 :     return;
    6959             :   }
    6960             :   // Free up the index we were using so it can be reused
    6961           0 :   mGamepadIndexSet.Remove(gamepad->Index());
    6962           0 :   mGamepads.Remove(aIndex);
    6963             : }
    6964             : 
    6965             : void
    6966           0 : nsGlobalWindowInner::GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads)
    6967             : {
    6968           0 :   aGamepads.Clear();
    6969             : 
    6970             :   // navigator.getGamepads() always returns an empty array when
    6971             :   // privacy.resistFingerprinting is true.
    6972           0 :   if (nsContentUtils::ShouldResistFingerprinting()) {
    6973             :     return;
    6974             :   }
    6975             : 
    6976             :   // mGamepads.Count() may not be sufficient, but it's not harmful.
    6977           0 :   aGamepads.SetCapacity(mGamepads.Count());
    6978           0 :   for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
    6979           0 :     Gamepad* gamepad = iter.UserData();
    6980           0 :     aGamepads.EnsureLengthAtLeast(gamepad->Index() + 1);
    6981           0 :     aGamepads[gamepad->Index()] = gamepad;
    6982             :   }
    6983             : }
    6984             : 
    6985             : already_AddRefed<Gamepad>
    6986           0 : nsGlobalWindowInner::GetGamepad(uint32_t aIndex)
    6987             : {
    6988           0 :   RefPtr<Gamepad> gamepad;
    6989             : 
    6990           0 :   if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
    6991             :     return gamepad.forget();
    6992             :   }
    6993             : 
    6994             :   return nullptr;
    6995             : }
    6996             : 
    6997             : void
    6998           0 : nsGlobalWindowInner::SetHasSeenGamepadInput(bool aHasSeen)
    6999             : {
    7000           0 :   mHasSeenGamepadInput = aHasSeen;
    7001           0 : }
    7002             : 
    7003             : bool
    7004           0 : nsGlobalWindowInner::HasSeenGamepadInput()
    7005             : {
    7006           0 :   return mHasSeenGamepadInput;
    7007             : }
    7008             : 
    7009             : void
    7010           0 : nsGlobalWindowInner::SyncGamepadState()
    7011             : {
    7012           0 :   if (mHasSeenGamepadInput) {
    7013           0 :     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
    7014           0 :     for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
    7015           0 :       gamepadManager->SyncGamepadState(iter.Key(), iter.UserData());
    7016             :     }
    7017             :   }
    7018           0 : }
    7019             : 
    7020             : void
    7021           0 : nsGlobalWindowInner::StopGamepadHaptics()
    7022             : {
    7023           0 :   if (mHasSeenGamepadInput) {
    7024           0 :     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
    7025           0 :     gamepadManager->StopHaptics();
    7026             :   }
    7027           0 : }
    7028             : 
    7029             : bool
    7030           0 : nsGlobalWindowInner::UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices)
    7031             : {
    7032           0 :   VRDisplay::UpdateVRDisplays(mVRDisplays, this);
    7033           0 :   aDevices = mVRDisplays;
    7034           0 :   return true;
    7035             : }
    7036             : 
    7037             : void
    7038           0 : nsGlobalWindowInner::NotifyActiveVRDisplaysChanged()
    7039             : {
    7040           0 :   if (mNavigator) {
    7041           0 :     mNavigator->NotifyActiveVRDisplaysChanged();
    7042             :   }
    7043           0 : }
    7044             : 
    7045             : void
    7046           0 : nsGlobalWindowInner::DispatchVRDisplayActivate(uint32_t aDisplayID,
    7047             :                                                mozilla::dom::VRDisplayEventReason aReason)
    7048             : {
    7049             :   // Ensure that our list of displays is up to date
    7050           0 :   VRDisplay::UpdateVRDisplays(mVRDisplays, this);
    7051             : 
    7052             :   // Search for the display identified with aDisplayID and fire the
    7053             :   // event if found.
    7054           0 :   for (const auto& display : mVRDisplays) {
    7055           0 :     if (display->DisplayId() == aDisplayID) {
    7056           0 :       if (aReason != VRDisplayEventReason::Navigation &&
    7057           0 :           display->IsAnyPresenting(gfx::kVRGroupContent)) {
    7058             :         // We only want to trigger this event if nobody is presenting to the
    7059             :         // display already or when a page is loaded by navigating away
    7060             :         // from a page with an active VR Presentation.
    7061           0 :         continue;
    7062             :       }
    7063             : 
    7064           0 :       VRDisplayEventInit init;
    7065           0 :       init.mBubbles = false;
    7066           0 :       init.mCancelable = false;
    7067           0 :       init.mDisplay = display;
    7068           0 :       init.mReason.Construct(aReason);
    7069             : 
    7070             :       RefPtr<VRDisplayEvent> event =
    7071           0 :         VRDisplayEvent::Constructor(this,
    7072           0 :                                     NS_LITERAL_STRING("vrdisplayactivate"),
    7073           0 :                                     init);
    7074             :       // vrdisplayactivate is a trusted event, allowing VRDisplay.requestPresent
    7075             :       // to be used in response to link traversal, user request (chrome UX), and
    7076             :       // HMD mounting detection sensors.
    7077           0 :       event->SetTrusted(true);
    7078             :       // VRDisplay.requestPresent normally requires a user gesture; however, an
    7079             :       // exception is made to allow it to be called in response to vrdisplayactivate
    7080             :       // during VR link traversal.
    7081           0 :       display->StartHandlingVRNavigationEvent();
    7082           0 :       DispatchEvent(*event);
    7083           0 :       display->StopHandlingVRNavigationEvent();
    7084             :       // Once we dispatch the event, we must not access any members as an event
    7085             :       // listener can do anything, including closing windows.
    7086             :       return;
    7087             :     }
    7088             :   }
    7089             : }
    7090             : 
    7091             : void
    7092           0 : nsGlobalWindowInner::DispatchVRDisplayDeactivate(uint32_t aDisplayID,
    7093             :                                                  mozilla::dom::VRDisplayEventReason aReason)
    7094             : {
    7095             :   // Ensure that our list of displays is up to date
    7096           0 :   VRDisplay::UpdateVRDisplays(mVRDisplays, this);
    7097             : 
    7098             :   // Search for the display identified with aDisplayID and fire the
    7099             :   // event if found.
    7100           0 :   for (const auto& display : mVRDisplays) {
    7101           0 :     if (display->DisplayId() == aDisplayID && display->IsPresenting()) {
    7102             :       // We only want to trigger this event to content that is presenting to
    7103             :       // the display already.
    7104             : 
    7105           0 :       VRDisplayEventInit init;
    7106           0 :       init.mBubbles = false;
    7107           0 :       init.mCancelable = false;
    7108           0 :       init.mDisplay = display;
    7109           0 :       init.mReason.Construct(aReason);
    7110             : 
    7111             :       RefPtr<VRDisplayEvent> event =
    7112           0 :         VRDisplayEvent::Constructor(this,
    7113           0 :                                     NS_LITERAL_STRING("vrdisplaydeactivate"),
    7114           0 :                                     init);
    7115           0 :       event->SetTrusted(true);
    7116           0 :       DispatchEvent(*event);
    7117             :       // Once we dispatch the event, we must not access any members as an event
    7118             :       // listener can do anything, including closing windows.
    7119             :       return;
    7120             :     }
    7121             :   }
    7122             : }
    7123             : 
    7124             : void
    7125           0 : nsGlobalWindowInner::DispatchVRDisplayConnect(uint32_t aDisplayID)
    7126             : {
    7127             :   // Ensure that our list of displays is up to date
    7128           0 :   VRDisplay::UpdateVRDisplays(mVRDisplays, this);
    7129             : 
    7130             :   // Search for the display identified with aDisplayID and fire the
    7131             :   // event if found.
    7132           0 :   for (const auto& display : mVRDisplays) {
    7133           0 :     if (display->DisplayId() == aDisplayID) {
    7134             :       // Fire event even if not presenting to the display.
    7135           0 :       VRDisplayEventInit init;
    7136           0 :       init.mBubbles = false;
    7137           0 :       init.mCancelable = false;
    7138           0 :       init.mDisplay = display;
    7139             :       // VRDisplayEvent.reason is not set for vrdisplayconnect
    7140             : 
    7141             :       RefPtr<VRDisplayEvent> event =
    7142           0 :         VRDisplayEvent::Constructor(this,
    7143           0 :                                     NS_LITERAL_STRING("vrdisplayconnect"),
    7144           0 :                                     init);
    7145           0 :       event->SetTrusted(true);
    7146           0 :       DispatchEvent(*event);
    7147             :       // Once we dispatch the event, we must not access any members as an event
    7148             :       // listener can do anything, including closing windows.
    7149             :       return;
    7150             :     }
    7151             :   }
    7152             : }
    7153             : 
    7154             : void
    7155           0 : nsGlobalWindowInner::DispatchVRDisplayDisconnect(uint32_t aDisplayID)
    7156             : {
    7157             :   // Ensure that our list of displays is up to date
    7158           0 :   VRDisplay::UpdateVRDisplays(mVRDisplays, this);
    7159             : 
    7160             :   // Search for the display identified with aDisplayID and fire the
    7161             :   // event if found.
    7162           0 :   for (const auto& display : mVRDisplays) {
    7163           0 :     if (display->DisplayId() == aDisplayID) {
    7164             :       // Fire event even if not presenting to the display.
    7165           0 :       VRDisplayEventInit init;
    7166           0 :       init.mBubbles = false;
    7167           0 :       init.mCancelable = false;
    7168           0 :       init.mDisplay = display;
    7169             :       // VRDisplayEvent.reason is not set for vrdisplaydisconnect
    7170             : 
    7171             :       RefPtr<VRDisplayEvent> event =
    7172           0 :         VRDisplayEvent::Constructor(this,
    7173           0 :                                     NS_LITERAL_STRING("vrdisplaydisconnect"),
    7174           0 :                                     init);
    7175           0 :       event->SetTrusted(true);
    7176           0 :       DispatchEvent(*event);
    7177             :       // Once we dispatch the event, we must not access any members as an event
    7178             :       // listener can do anything, including closing windows.
    7179             :       return;
    7180             :     }
    7181             :   }
    7182             : }
    7183             : 
    7184             : void
    7185           0 : nsGlobalWindowInner::DispatchVRDisplayPresentChange(uint32_t aDisplayID)
    7186             : {
    7187             :   // Ensure that our list of displays is up to date
    7188           0 :   VRDisplay::UpdateVRDisplays(mVRDisplays, this);
    7189             : 
    7190             :   // Search for the display identified with aDisplayID and fire the
    7191             :   // event if found.
    7192           0 :   for (const auto& display : mVRDisplays) {
    7193           0 :     if (display->DisplayId() == aDisplayID) {
    7194             :       // Fire event even if not presenting to the display.
    7195           0 :       VRDisplayEventInit init;
    7196           0 :       init.mBubbles = false;
    7197           0 :       init.mCancelable = false;
    7198           0 :       init.mDisplay = display;
    7199             :       // VRDisplayEvent.reason is not set for vrdisplaypresentchange
    7200             :       RefPtr<VRDisplayEvent> event =
    7201           0 :         VRDisplayEvent::Constructor(this,
    7202           0 :                                     NS_LITERAL_STRING("vrdisplaypresentchange"),
    7203           0 :                                     init);
    7204           0 :       event->SetTrusted(true);
    7205           0 :       DispatchEvent(*event);
    7206             :       // Once we dispatch the event, we must not access any members as an event
    7207             :       // listener can do anything, including closing windows.
    7208             :       return;
    7209             :     }
    7210             :   }
    7211             : }
    7212             : 
    7213             : enum WindowState {
    7214             :   // These constants need to match the constants in Window.webidl
    7215             :   STATE_MAXIMIZED = 1,
    7216             :   STATE_MINIMIZED = 2,
    7217             :   STATE_NORMAL = 3,
    7218             :   STATE_FULLSCREEN = 4
    7219             : };
    7220             : 
    7221             : uint16_t
    7222           3 : nsGlobalWindowInner::WindowState()
    7223             : {
    7224           6 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
    7225             : 
    7226           3 :   int32_t mode = widget ? widget->SizeMode() : 0;
    7227             : 
    7228           3 :   switch (mode) {
    7229             :     case nsSizeMode_Minimized:
    7230             :       return STATE_MINIMIZED;
    7231             :     case nsSizeMode_Maximized:
    7232           3 :       return STATE_MAXIMIZED;
    7233             :     case nsSizeMode_Fullscreen:
    7234           0 :       return STATE_FULLSCREEN;
    7235             :     case nsSizeMode_Normal:
    7236           0 :       return STATE_NORMAL;
    7237             :     default:
    7238           0 :       NS_WARNING("Illegal window state for this chrome window");
    7239             :       break;
    7240             :   }
    7241             : 
    7242           0 :   return STATE_NORMAL;
    7243             : }
    7244             : 
    7245             : bool
    7246           1 : nsGlobalWindowInner::IsFullyOccluded()
    7247             : {
    7248           2 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
    7249           0 :   return widget && widget->IsFullyOccluded();
    7250             : }
    7251             : 
    7252             : void
    7253           0 : nsGlobalWindowInner::Maximize()
    7254             : {
    7255           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
    7256             : 
    7257           0 :   if (widget) {
    7258           0 :     widget->SetSizeMode(nsSizeMode_Maximized);
    7259             :   }
    7260           0 : }
    7261             : 
    7262             : void
    7263           0 : nsGlobalWindowInner::Minimize()
    7264             : {
    7265           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
    7266             : 
    7267           0 :   if (widget) {
    7268           0 :     widget->SetSizeMode(nsSizeMode_Minimized);
    7269             :   }
    7270           0 : }
    7271             : 
    7272             : void
    7273           0 : nsGlobalWindowInner::Restore()
    7274             : {
    7275           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
    7276             : 
    7277           0 :   if (widget) {
    7278           0 :     widget->SetSizeMode(nsSizeMode_Normal);
    7279             :   }
    7280           0 : }
    7281             : 
    7282             : void
    7283           0 : nsGlobalWindowInner::GetAttention(ErrorResult& aResult)
    7284             : {
    7285           0 :   return GetAttentionWithCycleCount(-1, aResult);
    7286             : }
    7287             : 
    7288             : void
    7289           0 : nsGlobalWindowInner::GetAttentionWithCycleCount(int32_t aCycleCount,
    7290             :                                                 ErrorResult& aError)
    7291             : {
    7292           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
    7293             : 
    7294           0 :   if (widget) {
    7295           0 :     aError = widget->GetAttention(aCycleCount);
    7296             :   }
    7297           0 : }
    7298             : 
    7299             : void
    7300           0 : nsGlobalWindowInner::BeginWindowMove(Event& aMouseDownEvent,
    7301             :                                      ErrorResult& aError)
    7302             : {
    7303           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
    7304             : 
    7305           0 :   if (!widget) {
    7306           0 :     return;
    7307             :   }
    7308             : 
    7309             :   WidgetMouseEvent* mouseEvent =
    7310           0 :     aMouseDownEvent.WidgetEventPtr()->AsMouseEvent();
    7311           0 :   if (!mouseEvent || mouseEvent->mClass != eMouseEventClass) {
    7312           0 :     aError.Throw(NS_ERROR_FAILURE);
    7313           0 :     return;
    7314             :   }
    7315             : 
    7316           0 :   aError = widget->BeginMoveDrag(mouseEvent);
    7317             : }
    7318             : 
    7319             : already_AddRefed<Promise>
    7320           0 : nsGlobalWindowInner::PromiseDocumentFlushed(PromiseDocumentFlushedCallback& aCallback,
    7321             :                                             ErrorResult& aError)
    7322             : {
    7323           0 :   MOZ_RELEASE_ASSERT(IsChromeWindow());
    7324             : 
    7325           0 :   if (!IsCurrentInnerWindow()) {
    7326           0 :     aError.Throw(NS_ERROR_FAILURE);
    7327             :     return nullptr;
    7328             :   }
    7329             : 
    7330           0 :   if (mIteratingDocumentFlushedResolvers) {
    7331           0 :     aError.Throw(NS_ERROR_FAILURE);
    7332             :     return nullptr;
    7333             :   }
    7334             : 
    7335           0 :   if (!mDoc) {
    7336           0 :     aError.Throw(NS_ERROR_FAILURE);
    7337             :     return nullptr;
    7338             :   }
    7339             : 
    7340           0 :   nsIPresShell* shell = mDoc->GetShell();
    7341           0 :   if (!shell) {
    7342           0 :     aError.Throw(NS_ERROR_FAILURE);
    7343             :     return nullptr;
    7344             :   }
    7345             : 
    7346             :   // We need to associate the lifetime of the Promise to the lifetime
    7347             :   // of the caller's global. That way, if the window we're observing
    7348             :   // refresh driver ticks on goes away before our observer is fired,
    7349             :   // we can still resolve the Promise.
    7350           0 :   nsIGlobalObject* global = GetIncumbentGlobal();
    7351           0 :   if (!global) {
    7352           0 :     aError.Throw(NS_ERROR_FAILURE);
    7353             :     return nullptr;
    7354             :   }
    7355             : 
    7356           0 :   RefPtr<Promise> resultPromise = Promise::Create(global, aError);
    7357           0 :   if (aError.Failed()) {
    7358             :     return nullptr;
    7359             :   }
    7360             : 
    7361             :   UniquePtr<PromiseDocumentFlushedResolver> flushResolver(
    7362           0 :     new PromiseDocumentFlushedResolver(resultPromise, aCallback));
    7363             : 
    7364           0 :   if (!shell->NeedStyleFlush() && !shell->NeedLayoutFlush()) {
    7365           0 :     flushResolver->Call();
    7366             :     return resultPromise.forget();
    7367             :   }
    7368             : 
    7369           0 :   if (!mObservingDidRefresh) {
    7370           0 :     bool success = shell->AddPostRefreshObserver(this);
    7371           0 :     if (!success) {
    7372           0 :       aError.Throw(NS_ERROR_FAILURE);
    7373             :       return nullptr;
    7374             :     }
    7375           0 :     mObservingDidRefresh = true;
    7376             :   }
    7377             : 
    7378           0 :   mDocumentFlushedResolvers.AppendElement(std::move(flushResolver));
    7379             :   return resultPromise.forget();
    7380             : }
    7381             : 
    7382             : template<bool call>
    7383             : void
    7384           7 : nsGlobalWindowInner::CallOrCancelDocumentFlushedResolvers()
    7385             : {
    7386           7 :   MOZ_ASSERT(!mIteratingDocumentFlushedResolvers);
    7387             : 
    7388             :   while (true) {
    7389             :     {
    7390             :       // To coalesce MicroTask checkpoints inside callback call, enclose the
    7391             :       // inner loop with nsAutoMicroTask, and perform a MicroTask checkpoint
    7392             :       // after the loop.
    7393          14 :       nsAutoMicroTask mt;
    7394             : 
    7395           7 :       mIteratingDocumentFlushedResolvers = true;
    7396           0 :       for (const auto& documentFlushedResolver : mDocumentFlushedResolvers) {
    7397             :         if (call) {
    7398           0 :           documentFlushedResolver->Call();
    7399             :         } else {
    7400           0 :           documentFlushedResolver->Cancel();
    7401             :         }
    7402             :       }
    7403           7 :       mDocumentFlushedResolvers.Clear();
    7404           0 :       mIteratingDocumentFlushedResolvers = false;
    7405             :     }
    7406             : 
    7407             :     // Leaving nsAutoMicroTask above will perform MicroTask checkpoint, and
    7408             :     // Promise callbacks there may create mDocumentFlushedResolvers items.
    7409             : 
    7410             :     // If there's no new item, there's nothing to do here.
    7411          14 :     if (!mDocumentFlushedResolvers.Length()) {
    7412             :       break;
    7413             :     }
    7414             : 
    7415             :     // If there are new items, the observer is not added for them when calling
    7416             :     // PromiseDocumentFlushed.  Add here and leave.
    7417             :     // FIXME: Handle this case inside PromiseDocumentFlushed (bug 1442824).
    7418           0 :     if (mDoc) {
    7419           0 :       nsIPresShell* shell = mDoc->GetShell();
    7420           0 :       if (shell) {
    7421           0 :         (void) shell->AddPostRefreshObserver(this);
    7422           0 :         break;
    7423             :       }
    7424             :     }
    7425             : 
    7426             :     // If we fail adding observer, keep looping to resolve or reject all
    7427             :     // promises.  This case happens while destroying window.
    7428             :     // This violates the constraint that the promiseDocumentFlushed callback
    7429             :     // only ever run when no flush needed, but it's necessary to resolve
    7430             :     // Promise returned by that.
    7431             :   }
    7432           7 : }
    7433             : 
    7434             : void
    7435           0 : nsGlobalWindowInner::CallDocumentFlushedResolvers()
    7436             : {
    7437           7 :   CallOrCancelDocumentFlushedResolvers<true>();
    7438           0 : }
    7439             : 
    7440             : void
    7441           0 : nsGlobalWindowInner::CancelDocumentFlushedResolvers()
    7442             : {
    7443           0 :   CallOrCancelDocumentFlushedResolvers<false>();
    7444           0 : }
    7445             : 
    7446             : void
    7447           0 : nsGlobalWindowInner::DidRefresh()
    7448             : {
    7449           0 :   auto rejectionGuard = MakeScopeExit([&] {
    7450           0 :     CancelDocumentFlushedResolvers();
    7451           0 :     mObservingDidRefresh = false;
    7452           0 :   });
    7453             : 
    7454           0 :   MOZ_ASSERT(mDoc);
    7455             : 
    7456           0 :   nsIPresShell* shell = mDoc->GetShell();
    7457           0 :   MOZ_ASSERT(shell);
    7458             : 
    7459           0 :   if (shell->NeedStyleFlush() || shell->NeedLayoutFlush()) {
    7460             :     // By the time our observer fired, something has already invalidated
    7461             :     // style or layout - or perhaps we're still in the middle of a flush that
    7462             :     // was interrupted. In either case, we'll wait until the next refresh driver
    7463             :     // tick instead and try again.
    7464           0 :     rejectionGuard.release();
    7465           0 :     return;
    7466             :   }
    7467             : 
    7468           0 :   bool success = shell->RemovePostRefreshObserver(this);
    7469           0 :   if (!success) {
    7470             :     return;
    7471             :   }
    7472             : 
    7473           0 :   rejectionGuard.release();
    7474             : 
    7475           0 :   CallDocumentFlushedResolvers();
    7476           0 :   mObservingDidRefresh = false;
    7477             : }
    7478             : 
    7479             : already_AddRefed<nsWindowRoot>
    7480           0 : nsGlobalWindowInner::GetWindowRoot(mozilla::ErrorResult& aError)
    7481             : {
    7482           0 :   FORWARD_TO_OUTER_OR_THROW(GetWindowRootOuter, (), aError, nullptr);
    7483             : }
    7484             : 
    7485             : void
    7486           0 : nsGlobalWindowInner::SetCursor(const nsAString& aCursor, ErrorResult& aError)
    7487             : {
    7488           0 :   FORWARD_TO_OUTER_OR_THROW(SetCursorOuter, (aCursor, aError), aError, );
    7489             : }
    7490             : 
    7491             : NS_IMETHODIMP
    7492           1 : nsGlobalWindowInner::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow)
    7493             : {
    7494           1 :   MOZ_RELEASE_ASSERT(IsChromeWindow());
    7495             : 
    7496           2 :   ErrorResult rv;
    7497           0 :   NS_IF_ADDREF(*aBrowserWindow = GetBrowserDOMWindow(rv));
    7498           0 :   return rv.StealNSResult();
    7499             : }
    7500             : 
    7501             : nsIBrowserDOMWindow*
    7502           1 : nsGlobalWindowInner::GetBrowserDOMWindow(ErrorResult& aError)
    7503             : {
    7504           1 :   FORWARD_TO_OUTER_OR_THROW(GetBrowserDOMWindowOuter, (), aError, nullptr);
    7505             : }
    7506             : 
    7507             : void
    7508           1 : nsGlobalWindowInner::SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserWindow,
    7509             :                                     ErrorResult& aError)
    7510             : {
    7511           1 :   FORWARD_TO_OUTER_OR_THROW(SetBrowserDOMWindowOuter, (aBrowserWindow), aError, );
    7512             : }
    7513             : 
    7514             : void
    7515           0 : nsGlobalWindowInner::NotifyDefaultButtonLoaded(Element& aDefaultButton,
    7516             :                                                ErrorResult& aError)
    7517             : {
    7518             : #ifdef MOZ_XUL
    7519             :   // Don't snap to a disabled button.
    7520             :   nsCOMPtr<nsIDOMXULControlElement> xulControl =
    7521           0 :                                       do_QueryInterface(&aDefaultButton);
    7522           0 :   if (!xulControl) {
    7523           0 :     aError.Throw(NS_ERROR_FAILURE);
    7524           0 :     return;
    7525             :   }
    7526             :   bool disabled;
    7527           0 :   aError = xulControl->GetDisabled(&disabled);
    7528           0 :   if (aError.Failed() || disabled) {
    7529             :     return;
    7530             :   }
    7531             : 
    7532             :   // Get the button rect in screen coordinates.
    7533           0 :   nsIFrame *frame = aDefaultButton.GetPrimaryFrame();
    7534           0 :   if (!frame) {
    7535           0 :     aError.Throw(NS_ERROR_FAILURE);
    7536           0 :     return;
    7537             :   }
    7538             :   LayoutDeviceIntRect buttonRect =
    7539             :     LayoutDeviceIntRect::FromAppUnitsToNearest(
    7540           0 :       frame->GetScreenRectInAppUnits(),
    7541           0 :       frame->PresContext()->AppUnitsPerDevPixel());
    7542             : 
    7543             :   // Get the widget rect in screen coordinates.
    7544           0 :   nsIWidget *widget = GetNearestWidget();
    7545           0 :   if (!widget) {
    7546           0 :     aError.Throw(NS_ERROR_FAILURE);
    7547           0 :     return;
    7548             :   }
    7549           0 :   LayoutDeviceIntRect widgetRect = widget->GetScreenBounds();
    7550             : 
    7551             :   // Convert the buttonRect coordinates from screen to the widget.
    7552           0 :   buttonRect -= widgetRect.TopLeft();
    7553           0 :   nsresult rv = widget->OnDefaultButtonLoaded(buttonRect);
    7554           0 :   if (NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED) {
    7555           0 :     aError.Throw(rv);
    7556             :   }
    7557             : #else
    7558             :   aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
    7559             : #endif
    7560             : }
    7561             : 
    7562             : ChromeMessageBroadcaster*
    7563          26 : nsGlobalWindowInner::MessageManager()
    7564             : {
    7565          26 :   MOZ_ASSERT(IsChromeWindow());
    7566           0 :   if (!mChromeFields.mMessageManager) {
    7567             :     RefPtr<ChromeMessageBroadcaster> globalMM =
    7568           9 :       nsFrameMessageManager::GetGlobalMessageManager();
    7569           0 :     mChromeFields.mMessageManager = new ChromeMessageBroadcaster(globalMM);
    7570             :   }
    7571          52 :   return mChromeFields.mMessageManager;
    7572             : }
    7573             : 
    7574             : ChromeMessageBroadcaster*
    7575           8 : nsGlobalWindowInner::GetGroupMessageManager(const nsAString& aGroup)
    7576             : {
    7577           8 :   MOZ_ASSERT(IsChromeWindow());
    7578             : 
    7579             :   RefPtr<ChromeMessageBroadcaster> messageManager =
    7580          16 :     mChromeFields.mGroupMessageManagers.LookupForAdd(aGroup).OrInsert(
    7581           0 :       [this] () {
    7582           0 :         return new ChromeMessageBroadcaster(MessageManager());
    7583           0 :       });
    7584           0 :   return messageManager;
    7585             : }
    7586             : 
    7587             : void
    7588          14 : nsGlobalWindowInner::InitWasOffline()
    7589             : {
    7590          14 :   mWasOffline = NS_IsOffline();
    7591           0 : }
    7592             : 
    7593             : #if defined(MOZ_WIDGET_ANDROID)
    7594             : int16_t
    7595             : nsGlobalWindowInner::Orientation(CallerType aCallerType) const
    7596             : {
    7597             :   return nsContentUtils::ResistFingerprinting(aCallerType) ?
    7598             :            0 : WindowOrientationObserver::OrientationAngle();
    7599             : }
    7600             : #endif
    7601             : 
    7602             : already_AddRefed<Console>
    7603           0 : nsGlobalWindowInner::GetConsole(JSContext* aCx, ErrorResult& aRv)
    7604             : {
    7605           0 :   if (!mConsole) {
    7606           0 :     mConsole = Console::Create(aCx, this, aRv);
    7607           0 :     if (NS_WARN_IF(aRv.Failed())) {
    7608             :       return nullptr;
    7609             :     }
    7610             :   }
    7611             : 
    7612           0 :   RefPtr<Console> console = mConsole;
    7613           0 :   return console.forget();
    7614             : }
    7615             : 
    7616             : bool
    7617           0 : nsGlobalWindowInner::IsSecureContext() const
    7618             : {
    7619           0 :   JS::Realm* realm = js::GetNonCCWObjectRealm(GetWrapperPreserveColor());
    7620           0 :   return JS::GetIsSecureContext(realm);
    7621             : }
    7622             : 
    7623             : already_AddRefed<External>
    7624           0 : nsGlobalWindowInner::GetExternal(ErrorResult& aRv)
    7625             : {
    7626             : #ifdef HAVE_SIDEBAR
    7627           0 :   if (!mExternal) {
    7628           0 :     JS::Rooted<JSObject*> jsImplObj(RootingCx());
    7629           0 :     ConstructJSImplementation("@mozilla.org/sidebar;1", this, &jsImplObj, aRv);
    7630           0 :     if (aRv.Failed()) {
    7631           0 :       return nullptr;
    7632             :     }
    7633           0 :     mExternal = new External(jsImplObj, this);
    7634             :   }
    7635             : 
    7636           0 :   RefPtr<External> external = static_cast<External*>(mExternal.get());
    7637           0 :   return external.forget();
    7638             : #else
    7639             :   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    7640             :   return nullptr;
    7641             : #endif
    7642             : }
    7643             : 
    7644             : void
    7645           0 : nsGlobalWindowInner::GetSidebar(OwningExternalOrWindowProxy& aResult,
    7646             :                                 ErrorResult& aRv)
    7647             : {
    7648             : #ifdef HAVE_SIDEBAR
    7649             :   // First check for a named frame named "sidebar"
    7650           0 :   nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetChildWindow(NS_LITERAL_STRING("sidebar"));
    7651           0 :   if (domWindow) {
    7652           0 :     aResult.SetAsWindowProxy() = domWindow.forget();
    7653           0 :     return;
    7654             :   }
    7655             : 
    7656           0 :   RefPtr<External> external = GetExternal(aRv);
    7657           0 :   if (external) {
    7658           0 :     aResult.SetAsExternal() = external;
    7659             :   }
    7660             : #else
    7661             :   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    7662             : #endif
    7663             : }
    7664             : 
    7665             : void
    7666          15 : nsGlobalWindowInner::ClearDocumentDependentSlots(JSContext* aCx)
    7667             : {
    7668             :   // If JSAPI OOMs here, there is basically nothing we can do to recover safely.
    7669          30 :   if (!WindowBinding::ClearCachedDocumentValue(aCx, this) ||
    7670           0 :       !WindowBinding::ClearCachedPerformanceValue(aCx, this)) {
    7671           0 :     MOZ_CRASH("Unhandlable OOM while clearing document dependent slots.");
    7672             :   }
    7673          15 : }
    7674             : 
    7675             : /* static */
    7676             : JSObject*
    7677          14 : nsGlobalWindowInner::CreateNamedPropertiesObject(JSContext *aCx,
    7678             :                                                  JS::Handle<JSObject*> aProto)
    7679             : {
    7680          14 :   return WindowNamedPropertiesHandler::Create(aCx, aProto);
    7681             : }
    7682             : 
    7683             : void
    7684           0 : nsGlobalWindowInner::RedefineProperty(JSContext* aCx, const char* aPropName,
    7685             :                                       JS::Handle<JS::Value> aValue,
    7686             :                                       ErrorResult& aError)
    7687             : {
    7688           0 :   JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
    7689           0 :   if (!thisObj) {
    7690           0 :     aError.Throw(NS_ERROR_UNEXPECTED);
    7691           0 :     return;
    7692             :   }
    7693             : 
    7694           0 :   if (!JS_WrapObject(aCx, &thisObj) ||
    7695           0 :       !JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE)) {
    7696           0 :     aError.Throw(NS_ERROR_FAILURE);
    7697             :   }
    7698             : }
    7699             : 
    7700             : void
    7701           0 : nsGlobalWindowInner::GetReplaceableWindowCoord(JSContext* aCx,
    7702             :                                                nsGlobalWindowInner::WindowCoordGetter aGetter,
    7703             :                                                JS::MutableHandle<JS::Value> aRetval,
    7704             :                                                CallerType aCallerType,
    7705             :                                                ErrorResult& aError)
    7706             : {
    7707           0 :   int32_t coord = (this->*aGetter)(aCallerType, aError);
    7708           0 :   if (!aError.Failed() &&
    7709           0 :       !ToJSValue(aCx, coord, aRetval)) {
    7710           0 :     aError.Throw(NS_ERROR_FAILURE);
    7711             :   }
    7712           0 : }
    7713             : 
    7714             : void
    7715           0 : nsGlobalWindowInner::SetReplaceableWindowCoord(JSContext* aCx,
    7716             :                                                nsGlobalWindowInner::WindowCoordSetter aSetter,
    7717             :                                                JS::Handle<JS::Value> aValue,
    7718             :                                                const char* aPropName,
    7719             :                                                CallerType aCallerType,
    7720             :                                                ErrorResult& aError)
    7721             : {
    7722             :   /*
    7723             :    * If caller is not chrome and the user has not explicitly exempted the site,
    7724             :    * just treat this the way we would an IDL replaceable property.
    7725             :    */
    7726           0 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    7727           0 :   if (!outer ||
    7728           0 :       !outer->CanMoveResizeWindows(aCallerType) ||
    7729           0 :       outer->IsFrame()) {
    7730           0 :     RedefineProperty(aCx, aPropName, aValue, aError);
    7731           0 :     return;
    7732             :   }
    7733             : 
    7734             :   int32_t value;
    7735           0 :   if (!ValueToPrimitive<int32_t, eDefault>(aCx, aValue, &value)) {
    7736           0 :     aError.Throw(NS_ERROR_UNEXPECTED);
    7737           0 :     return;
    7738             :   }
    7739             : 
    7740           0 :   if (nsContentUtils::ShouldResistFingerprinting(GetDocShell())) {
    7741           0 :     bool innerWidthSpecified = false;
    7742           0 :     bool innerHeightSpecified = false;
    7743           0 :     bool outerWidthSpecified = false;
    7744           0 :     bool outerHeightSpecified = false;
    7745             : 
    7746           0 :     if (strcmp(aPropName, "innerWidth") == 0) {
    7747             :       innerWidthSpecified = true;
    7748           0 :     } else if (strcmp(aPropName, "innerHeight") == 0) {
    7749             :       innerHeightSpecified = true;
    7750           0 :     } else if (strcmp(aPropName, "outerWidth") == 0) {
    7751             :       outerWidthSpecified = true;
    7752           0 :     } else if (strcmp(aPropName, "outerHeight") == 0) {
    7753           0 :       outerHeightSpecified = true;
    7754             :     }
    7755             : 
    7756           0 :     if (innerWidthSpecified || innerHeightSpecified ||
    7757           0 :         outerWidthSpecified || outerHeightSpecified)
    7758             :     {
    7759           0 :       nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = outer->GetTreeOwnerWindow();
    7760           0 :       nsCOMPtr<nsIScreen> screen;
    7761             :       nsCOMPtr<nsIScreenManager> screenMgr(
    7762           0 :         do_GetService("@mozilla.org/gfx/screenmanager;1"));
    7763           0 :       int32_t winLeft   = 0;
    7764           0 :       int32_t winTop    = 0;
    7765           0 :       int32_t winWidth  = 0;
    7766           0 :       int32_t winHeight = 0;
    7767           0 :       double scale = 1.0;
    7768             : 
    7769             : 
    7770           0 :       if (treeOwnerAsWin && screenMgr) {
    7771             :         // Acquire current window size.
    7772           0 :         treeOwnerAsWin->GetUnscaledDevicePixelsPerCSSPixel(&scale);
    7773           0 :         treeOwnerAsWin->GetPositionAndSize(&winLeft, &winTop, &winWidth, &winHeight);
    7774           0 :         winLeft = NSToIntRound(winHeight / scale);
    7775           0 :         winTop = NSToIntRound(winWidth / scale);
    7776           0 :         winWidth = NSToIntRound(winWidth / scale);
    7777           0 :         winHeight = NSToIntRound(winHeight / scale);
    7778             : 
    7779             :         // Acquire content window size.
    7780           0 :         CSSIntSize contentSize;
    7781           0 :         outer->GetInnerSize(contentSize);
    7782             : 
    7783           0 :         screenMgr->ScreenForRect(winLeft, winTop, winWidth, winHeight,
    7784           0 :                                  getter_AddRefs(screen));
    7785             : 
    7786           0 :         if (screen) {
    7787           0 :           int32_t* targetContentWidth  = nullptr;
    7788           0 :           int32_t* targetContentHeight = nullptr;
    7789           0 :           int32_t screenWidth  = 0;
    7790           0 :           int32_t screenHeight = 0;
    7791           0 :           int32_t chromeWidth  = 0;
    7792           0 :           int32_t chromeHeight = 0;
    7793           0 :           int32_t inputWidth   = 0;
    7794           0 :           int32_t inputHeight  = 0;
    7795           0 :           int32_t unused = 0;
    7796             : 
    7797             :           // Get screen dimensions (in device pixels)
    7798           0 :           screen->GetAvailRect(&unused, &unused, &screenWidth,
    7799           0 :                                &screenHeight);
    7800             :           // Convert them to CSS pixels
    7801           0 :           screenWidth = NSToIntRound(screenWidth / scale);
    7802           0 :           screenHeight = NSToIntRound(screenHeight / scale);
    7803             : 
    7804             :           // Calculate the chrome UI size.
    7805           0 :           chromeWidth = winWidth - contentSize.width;
    7806           0 :           chromeHeight = winHeight - contentSize.height;
    7807             : 
    7808           0 :           if (innerWidthSpecified || outerWidthSpecified) {
    7809           0 :             inputWidth = value;
    7810           0 :             targetContentWidth = &value;
    7811           0 :             targetContentHeight = &unused;
    7812           0 :           } else if (innerHeightSpecified || outerHeightSpecified) {
    7813           0 :             inputHeight = value;
    7814           0 :             targetContentWidth = &unused;
    7815           0 :             targetContentHeight = &value;
    7816             :           }
    7817             : 
    7818           0 :           nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
    7819             :             chromeWidth,
    7820             :             chromeHeight,
    7821             :             screenWidth,
    7822             :             screenHeight,
    7823             :             inputWidth,
    7824             :             inputHeight,
    7825             :             outerWidthSpecified,
    7826             :             outerHeightSpecified,
    7827             :             targetContentWidth,
    7828             :             targetContentHeight
    7829           0 :           );
    7830             :         }
    7831             :       }
    7832             :     }
    7833             :   }
    7834             : 
    7835           0 :   (this->*aSetter)(value, aCallerType, aError);
    7836             : }
    7837             : 
    7838             : void
    7839          14 : nsGlobalWindowInner::FireOnNewGlobalObject()
    7840             : {
    7841             :   // AutoEntryScript required to invoke debugger hook, which is a
    7842             :   // Gecko-specific concept at present.
    7843          28 :   AutoEntryScript aes(this, "nsGlobalWindowInner report new global");
    7844           0 :   JS::Rooted<JSObject*> global(aes.cx(), GetWrapper());
    7845           0 :   JS_FireOnNewGlobalObject(aes.cx(), global);
    7846           0 : }
    7847             : 
    7848             : #ifdef _WINDOWS_
    7849             : #error "Never include windows.h in this file!"
    7850             : #endif
    7851             : 
    7852             : already_AddRefed<Promise>
    7853           0 : nsGlobalWindowInner::CreateImageBitmap(JSContext* aCx,
    7854             :                                        const ImageBitmapSource& aImage,
    7855             :                                        ErrorResult& aRv)
    7856             : {
    7857           0 :   if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
    7858           0 :     aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    7859             :     return nullptr;
    7860             :   }
    7861             : 
    7862           0 :   return ImageBitmap::Create(this, aImage, Nothing(), aRv);
    7863             : }
    7864             : 
    7865             : already_AddRefed<Promise>
    7866           0 : nsGlobalWindowInner::CreateImageBitmap(JSContext* aCx,
    7867             :                                        const ImageBitmapSource& aImage,
    7868             :                                        int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
    7869             :                                        ErrorResult& aRv)
    7870             : {
    7871           0 :   if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
    7872           0 :     aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
    7873             :     return nullptr;
    7874             :   }
    7875             : 
    7876           0 :   return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
    7877             : }
    7878             : 
    7879             : already_AddRefed<mozilla::dom::Promise>
    7880           0 : nsGlobalWindowInner::CreateImageBitmap(JSContext* aCx,
    7881             :                                        const ImageBitmapSource& aImage,
    7882             :                                        int32_t aOffset, int32_t aLength,
    7883             :                                        ImageBitmapFormat aFormat,
    7884             :                                        const Sequence<ChannelPixelLayout>& aLayout,
    7885             :                                        ErrorResult& aRv)
    7886             : {
    7887           0 :   if (!DOMPrefs::ImageBitmapExtensionsEnabled()) {
    7888           0 :     aRv.Throw(NS_ERROR_TYPE_ERR);
    7889             :     return nullptr;
    7890             :   }
    7891           0 :   if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
    7892             :     return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
    7893           0 :                                aRv);
    7894             :   }
    7895           0 :   aRv.Throw(NS_ERROR_TYPE_ERR);
    7896             :   return nullptr;
    7897             : }
    7898             : 
    7899             : mozilla::dom::TabGroup*
    7900          15 : nsGlobalWindowInner::TabGroupInner()
    7901             : {
    7902             :   // If we don't have a TabGroup yet, try to get it from the outer window and
    7903             :   // cache it.
    7904          30 :   if (!mTabGroup) {
    7905           0 :     nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    7906             :     // This will never be called without either an outer window, or a cached tab group.
    7907             :     // This is because of the following:
    7908             :     // * This method is only called on inner windows
    7909             :     // * This method is called as a document is attached to it's script global
    7910             :     //   by the document
    7911             :     // * Inner windows are created in nsGlobalWindowInner::SetNewDocument, which
    7912             :     //   immediately sets a document, which will call this method, causing
    7913             :     //   the TabGroup to be cached.
    7914          14 :     MOZ_RELEASE_ASSERT(outer, "Inner window without outer window has no cached tab group!");
    7915           0 :     mTabGroup = outer->TabGroup();
    7916             :   }
    7917          30 :   MOZ_ASSERT(mTabGroup);
    7918             : 
    7919             : #ifdef DEBUG
    7920          15 :   nsGlobalWindowOuter* outer = GetOuterWindowInternal();
    7921           0 :   MOZ_ASSERT_IF(outer, outer->TabGroup() == mTabGroup);
    7922             : #endif
    7923             : 
    7924          30 :   return mTabGroup;
    7925             : }
    7926             : 
    7927             : nsresult
    7928           9 : nsGlobalWindowInner::Dispatch(TaskCategory aCategory,
    7929             :                               already_AddRefed<nsIRunnable>&& aRunnable)
    7930             : {
    7931           9 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
    7932           0 :   if (GetDocGroup()) {
    7933           0 :     return GetDocGroup()->Dispatch(aCategory, std::move(aRunnable));
    7934             :   }
    7935           0 :   return DispatcherTrait::Dispatch(aCategory, std::move(aRunnable));
    7936             : }
    7937             : 
    7938             : nsISerialEventTarget*
    7939          15 : nsGlobalWindowInner::EventTargetFor(TaskCategory aCategory) const
    7940             : {
    7941          15 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
    7942           0 :   if (GetDocGroup()) {
    7943           0 :     return GetDocGroup()->EventTargetFor(aCategory);
    7944             :   }
    7945           0 :   return DispatcherTrait::EventTargetFor(aCategory);
    7946             : }
    7947             : 
    7948             : AbstractThread*
    7949           0 : nsGlobalWindowInner::AbstractMainThreadFor(TaskCategory aCategory)
    7950             : {
    7951           0 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
    7952           0 :   if (GetDocGroup()) {
    7953           0 :     return GetDocGroup()->AbstractMainThreadFor(aCategory);
    7954             :   }
    7955           0 :   return DispatcherTrait::AbstractMainThreadFor(aCategory);
    7956             : }
    7957             : 
    7958             : Worklet*
    7959           0 : nsGlobalWindowInner::GetAudioWorklet(ErrorResult& aRv)
    7960             : {
    7961           0 :   if (!mAudioWorklet) {
    7962           0 :     nsIPrincipal* principal = GetPrincipal();
    7963           0 :     if (!principal) {
    7964           0 :       aRv.Throw(NS_ERROR_FAILURE);
    7965           0 :       return nullptr;
    7966             :     }
    7967             : 
    7968           0 :     mAudioWorklet = new Worklet(this, principal, Worklet::eAudioWorklet);
    7969             :   }
    7970             : 
    7971           0 :   return mAudioWorklet;
    7972             : }
    7973             : 
    7974             : Worklet*
    7975           0 : nsGlobalWindowInner::GetPaintWorklet(ErrorResult& aRv)
    7976             : {
    7977           0 :   if (!mPaintWorklet) {
    7978           0 :     nsIPrincipal* principal = GetPrincipal();
    7979           0 :     if (!principal) {
    7980           0 :       aRv.Throw(NS_ERROR_FAILURE);
    7981           0 :       return nullptr;
    7982             :     }
    7983             : 
    7984           0 :     mPaintWorklet = new Worklet(this, principal, Worklet::ePaintWorklet);
    7985             :   }
    7986             : 
    7987           0 :   return mPaintWorklet;
    7988             : }
    7989             : 
    7990             : void
    7991           0 : nsGlobalWindowInner::GetRegionalPrefsLocales(nsTArray<nsString>& aLocales)
    7992             : {
    7993           0 :   AutoTArray<nsCString, 10> rpLocales;
    7994           0 :   mozilla::intl::LocaleService::GetInstance()->GetRegionalPrefsLocales(rpLocales);
    7995             : 
    7996           0 :   for (const auto& loc : rpLocales) {
    7997           0 :     aLocales.AppendElement(NS_ConvertUTF8toUTF16(loc));
    7998             :   }
    7999           0 : }
    8000             : 
    8001             : IntlUtils*
    8002           0 : nsGlobalWindowInner::GetIntlUtils(ErrorResult& aError)
    8003             : {
    8004           0 :   if (!mIntlUtils) {
    8005           0 :     mIntlUtils = new IntlUtils(this);
    8006             :   }
    8007             : 
    8008           0 :   return mIntlUtils;
    8009             : }
    8010             : 
    8011             : mozilla::dom::TabGroup*
    8012          15 : nsPIDOMWindowInner::TabGroup()
    8013             : {
    8014          15 :   return nsGlobalWindowInner::Cast(this)->TabGroupInner();
    8015             : }
    8016             : 
    8017             : /* static */ already_AddRefed<nsGlobalWindowInner>
    8018          14 : nsGlobalWindowInner::Create(nsGlobalWindowOuter *aOuterWindow, bool aIsChrome)
    8019             : {
    8020          28 :   RefPtr<nsGlobalWindowInner> window = new nsGlobalWindowInner(aOuterWindow);
    8021           0 :   if (aIsChrome) {
    8022           0 :     window->mIsChrome = true;
    8023           0 :     window->mCleanMessageManager = true;
    8024             :   }
    8025             : 
    8026          14 :   window->InitWasOffline();
    8027           0 :   return window.forget();
    8028             : }
    8029             : 
    8030             : nsIURI*
    8031           0 : nsPIDOMWindowInner::GetDocumentURI() const
    8032             : {
    8033           0 :   return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
    8034             : }
    8035             : 
    8036             : nsIURI*
    8037           0 : nsPIDOMWindowInner::GetDocBaseURI() const
    8038             : {
    8039           0 :   return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get();
    8040             : }
    8041             : 
    8042             : void
    8043          14 : nsPIDOMWindowInner::MaybeCreateDoc()
    8044             : {
    8045             :   // XXX: Forward to outer?
    8046          28 :   MOZ_ASSERT(!mDoc);
    8047           0 :   if (nsIDocShell* docShell = GetDocShell()) {
    8048             :     // Note that |document| here is the same thing as our mDoc, but we
    8049             :     // don't have to explicitly set the member variable because the docshell
    8050             :     // has already called SetNewDocument().
    8051          14 :     nsCOMPtr<nsIDocument> document = docShell->GetDocument();
    8052             :     Unused << document;
    8053             :   }
    8054          14 : }
    8055             : 
    8056             : mozilla::dom::DocGroup*
    8057          71 : nsPIDOMWindowInner::GetDocGroup() const
    8058             : {
    8059          71 :   nsIDocument* doc = GetExtantDoc();
    8060           0 :   if (doc) {
    8061           0 :     return doc->GetDocGroup();
    8062             :   }
    8063             :   return nullptr;
    8064             : }
    8065             : 
    8066             : nsIGlobalObject*
    8067          19 : nsPIDOMWindowInner::AsGlobal()
    8068             : {
    8069          19 :   return nsGlobalWindowInner::Cast(this);
    8070             : }
    8071             : 
    8072             : const nsIGlobalObject*
    8073           0 : nsPIDOMWindowInner::AsGlobal() const
    8074             : {
    8075           0 :   return nsGlobalWindowInner::Cast(this);
    8076             : }
    8077             : 
    8078             : // XXX: Can we define this in a header instead of here?
    8079             : namespace mozilla {
    8080             : namespace dom {
    8081             : extern uint64_t
    8082             : NextWindowID();
    8083             : } // namespace dom
    8084             : } // namespace mozilla
    8085             : 
    8086          14 : nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter *aOuterWindow)
    8087             : : mMutationBits(0), mActivePeerConnections(0), mIsDocumentLoaded(false),
    8088             :   mIsHandlingResizeEvent(false),
    8089             :   mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
    8090             :   mMayHaveSelectionChangeEventListener(false),
    8091             :   mMayHaveMouseEnterLeaveEventListener(false),
    8092             :   mMayHavePointerEnterLeaveEventListener(false),
    8093             :   mAudioCaptured(false),
    8094             :   mOuterWindow(aOuterWindow),
    8095             :   // Make sure no actual window ends up with mWindowID == 0
    8096          14 :   mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
    8097             :   mMarkedCCGeneration(0),
    8098             :   mHasTriedToCacheTopInnerWindow(false),
    8099             :   mNumOfIndexedDBDatabases(0),
    8100         210 :   mNumOfOpenWebSockets(0)
    8101             : {
    8102          14 :   MOZ_ASSERT(aOuterWindow);
    8103           0 : }
    8104             : 
    8105           0 : nsPIDOMWindowInner::~nsPIDOMWindowInner() {}
    8106             : 
    8107             : #undef FORWARD_TO_OUTER
    8108             : #undef FORWARD_TO_OUTER_OR_THROW
    8109             : #undef FORWARD_TO_OUTER_VOID

Generated by: LCOV version 1.13-14-ga5dd952