LCOV - code coverage report
Current view: top level - dom/base - nsGlobalWindow.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1924 6708 28.7 %
Date: 2017-07-14 16:53:18 Functions: 266 785 33.9 %
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/LocalStorage.h"
      21             : #include "mozilla/dom/Storage.h"
      22             : #include "mozilla/dom/IdleRequest.h"
      23             : #include "mozilla/dom/Performance.h"
      24             : #include "mozilla/dom/StorageEvent.h"
      25             : #include "mozilla/dom/StorageEventBinding.h"
      26             : #include "mozilla/dom/StorageNotifierService.h"
      27             : #include "mozilla/dom/Timeout.h"
      28             : #include "mozilla/dom/TimeoutHandler.h"
      29             : #include "mozilla/dom/TimeoutManager.h"
      30             : #include "mozilla/IntegerPrintfMacros.h"
      31             : #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
      32             : #include "mozilla/dom/WindowOrientationObserver.h"
      33             : #endif
      34             : #include "nsDOMOfflineResourceList.h"
      35             : #include "nsError.h"
      36             : #include "nsIIdleService.h"
      37             : #include "nsISizeOfEventTarget.h"
      38             : #include "nsDOMJSUtils.h"
      39             : #include "nsArrayUtils.h"
      40             : #include "nsIDOMWindowCollection.h"
      41             : #include "nsDOMWindowList.h"
      42             : #include "mozilla/dom/WakeLock.h"
      43             : #include "mozilla/dom/power/PowerManagerService.h"
      44             : #include "nsIDocShellTreeOwner.h"
      45             : #include "nsIInterfaceRequestorUtils.h"
      46             : #include "nsIPermissionManager.h"
      47             : #include "nsIScriptContext.h"
      48             : #include "nsIScriptTimeoutHandler.h"
      49             : #include "nsITimeoutHandler.h"
      50             : #include "nsIController.h"
      51             : #include "nsScriptNameSpaceManager.h"
      52             : #include "nsISlowScriptDebug.h"
      53             : #include "nsWindowMemoryReporter.h"
      54             : #include "WindowNamedPropertiesHandler.h"
      55             : #include "nsFrameSelection.h"
      56             : #include "nsNetUtil.h"
      57             : #include "nsVariant.h"
      58             : #include "nsPrintfCString.h"
      59             : #include "mozilla/intl/LocaleService.h"
      60             : 
      61             : // Helper Classes
      62             : #include "nsJSUtils.h"
      63             : #include "jsapi.h"              // for JSAutoRequest
      64             : #include "jswrapper.h"
      65             : #include "nsCharSeparatedTokenizer.h"
      66             : #include "nsReadableUtils.h"
      67             : #include "nsDOMClassInfo.h"
      68             : #include "nsJSEnvironment.h"
      69             : #include "mozilla/dom/ScriptSettings.h"
      70             : #include "mozilla/Preferences.h"
      71             : #include "mozilla/Likely.h"
      72             : #include "mozilla/Sprintf.h"
      73             : #include "mozilla/Unused.h"
      74             : 
      75             : // Other Classes
      76             : #include "mozilla/dom/BarProps.h"
      77             : #include "nsContentCID.h"
      78             : #include "nsLayoutStatics.h"
      79             : #include "nsCCUncollectableMarker.h"
      80             : #include "mozilla/dom/workers/Workers.h"
      81             : #include "mozilla/dom/ToJSValue.h"
      82             : #include "nsJSPrincipals.h"
      83             : #include "mozilla/Attributes.h"
      84             : #include "mozilla/Debug.h"
      85             : #include "mozilla/EventListenerManager.h"
      86             : #include "mozilla/EventStates.h"
      87             : #include "mozilla/MouseEvents.h"
      88             : #include "mozilla/ProcessHangMonitor.h"
      89             : #include "mozilla/ThrottledEventQueue.h"
      90             : #include "AudioChannelService.h"
      91             : #include "nsAboutProtocolUtils.h"
      92             : #include "nsCharTraits.h" // NS_IS_HIGH/LOW_SURROGATE
      93             : #include "PostMessageEvent.h"
      94             : #include "mozilla/dom/DocGroup.h"
      95             : #include "mozilla/dom/TabGroup.h"
      96             : 
      97             : // Interfaces Needed
      98             : #include "nsIFrame.h"
      99             : #include "nsCanvasFrame.h"
     100             : #include "nsIWidget.h"
     101             : #include "nsIWidgetListener.h"
     102             : #include "nsIBaseWindow.h"
     103             : #include "nsIDeviceSensors.h"
     104             : #include "nsIContent.h"
     105             : #include "nsIDocShell.h"
     106             : #include "nsIDocCharset.h"
     107             : #include "nsIDocument.h"
     108             : #include "Crypto.h"
     109             : #include "nsIDOMDocument.h"
     110             : #include "nsIDOMElement.h"
     111             : #include "nsIDOMEvent.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 "nsISelection.h"
     123             : #include "nsIPrompt.h"
     124             : #include "nsIPromptService.h"
     125             : #include "nsIPromptFactory.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 "nsComputedDOMStyle.h"
     132             : #include "nsDOMCID.h"
     133             : #include "nsDOMWindowUtils.h"
     134             : #include "nsIWindowWatcher.h"
     135             : #include "nsPIWindowWatcher.h"
     136             : #include "nsIContentViewer.h"
     137             : #include "nsIScriptError.h"
     138             : #include "nsIControllers.h"
     139             : #include "nsIControllerContext.h"
     140             : #include "nsGlobalWindowCommands.h"
     141             : #include "nsQueryObject.h"
     142             : #include "nsContentUtils.h"
     143             : #include "nsCSSProps.h"
     144             : #include "nsIDOMFileList.h"
     145             : #include "nsIURIFixup.h"
     146             : #ifndef DEBUG
     147             : #include "nsIAppStartup.h"
     148             : #include "nsToolkitCompsCID.h"
     149             : #endif
     150             : #include "nsCDefaultURIFixup.h"
     151             : #include "mozilla/EventDispatcher.h"
     152             : #include "mozilla/EventStateManager.h"
     153             : #include "nsIObserverService.h"
     154             : #include "nsFocusManager.h"
     155             : #include "nsIXULWindow.h"
     156             : #include "nsITimedChannel.h"
     157             : #include "nsServiceManagerUtils.h"
     158             : #ifdef MOZ_XUL
     159             : #include "nsIDOMXULControlElement.h"
     160             : #include "nsMenuPopupFrame.h"
     161             : #endif
     162             : #include "mozilla/dom/CustomEvent.h"
     163             : #include "nsIJARChannel.h"
     164             : #include "nsIScreenManager.h"
     165             : #include "nsIEffectiveTLDService.h"
     166             : 
     167             : #include "xpcprivate.h"
     168             : 
     169             : #ifdef NS_PRINTING
     170             : #include "nsIPrintSettings.h"
     171             : #include "nsIPrintSettingsService.h"
     172             : #include "nsIWebBrowserPrint.h"
     173             : #endif
     174             : 
     175             : #include "nsWindowRoot.h"
     176             : #include "nsNetCID.h"
     177             : #include "nsIArray.h"
     178             : 
     179             : // XXX An unfortunate dependency exists here (two XUL files).
     180             : #include "nsIDOMXULDocument.h"
     181             : #include "nsIDOMXULCommandDispatcher.h"
     182             : 
     183             : #include "nsBindingManager.h"
     184             : #include "nsXBLService.h"
     185             : 
     186             : // used for popup blocking, needs to be converted to something
     187             : // belonging to the back-end like nsIContentPolicy
     188             : #include "nsIPopupWindowManager.h"
     189             : 
     190             : #include "nsIDragService.h"
     191             : #include "mozilla/dom/Element.h"
     192             : #include "mozilla/dom/Selection.h"
     193             : #include "nsFrameLoader.h"
     194             : #include "nsISupportsPrimitives.h"
     195             : #include "nsXPCOMCID.h"
     196             : #include "mozilla/Logging.h"
     197             : #include "prenv.h"
     198             : 
     199             : #include "mozilla/dom/IDBFactory.h"
     200             : #include "mozilla/dom/MessageChannel.h"
     201             : #include "mozilla/dom/Promise.h"
     202             : 
     203             : #include "mozilla/dom/Gamepad.h"
     204             : #include "mozilla/dom/GamepadManager.h"
     205             : 
     206             : #include "gfxVR.h"
     207             : #include "mozilla/dom/VRDisplay.h"
     208             : #include "mozilla/dom/VRDisplayEvent.h"
     209             : #include "mozilla/dom/VRDisplayEventBinding.h"
     210             : #include "mozilla/dom/VREventObserver.h"
     211             : 
     212             : #include "nsRefreshDriver.h"
     213             : #include "Layers.h"
     214             : 
     215             : #include "mozilla/AddonPathService.h"
     216             : #include "mozilla/BasePrincipal.h"
     217             : #include "mozilla/Services.h"
     218             : #include "mozilla/Telemetry.h"
     219             : #include "mozilla/dom/Location.h"
     220             : #include "nsHTMLDocument.h"
     221             : #include "nsWrapperCacheInlines.h"
     222             : #include "mozilla/DOMEventTargetHelper.h"
     223             : #include "prrng.h"
     224             : #include "nsSandboxFlags.h"
     225             : #include "TimeChangeObserver.h"
     226             : #include "mozilla/dom/AudioContext.h"
     227             : #include "mozilla/dom/BrowserElementDictionariesBinding.h"
     228             : #include "mozilla/dom/cache/CacheStorage.h"
     229             : #include "mozilla/dom/Console.h"
     230             : #include "mozilla/dom/Fetch.h"
     231             : #include "mozilla/dom/FunctionBinding.h"
     232             : #include "mozilla/dom/HashChangeEvent.h"
     233             : #ifdef ENABLE_INTL_API
     234             : #include "mozilla/dom/IntlUtils.h"
     235             : #endif
     236             : #include "mozilla/dom/MozSelfSupportBinding.h"
     237             : #include "mozilla/dom/PopStateEvent.h"
     238             : #include "mozilla/dom/PopupBlockedEvent.h"
     239             : #include "mozilla/dom/PrimitiveConversions.h"
     240             : #include "mozilla/dom/WindowBinding.h"
     241             : #include "nsITabChild.h"
     242             : #include "mozilla/dom/MediaQueryList.h"
     243             : #include "mozilla/dom/ScriptSettings.h"
     244             : #include "mozilla/dom/NavigatorBinding.h"
     245             : #include "mozilla/dom/ImageBitmap.h"
     246             : #include "mozilla/dom/ImageBitmapBinding.h"
     247             : #include "mozilla/dom/ServiceWorkerRegistration.h"
     248             : #include "mozilla/dom/U2F.h"
     249             : #include "mozilla/dom/WebIDLGlobalNameHash.h"
     250             : #include "mozilla/dom/Worklet.h"
     251             : #ifdef HAVE_SIDEBAR
     252             : #include "mozilla/dom/ExternalBinding.h"
     253             : #endif
     254             : 
     255             : #ifdef MOZ_WEBSPEECH
     256             : #include "mozilla/dom/SpeechSynthesis.h"
     257             : #endif
     258             : 
     259             : #ifdef MOZ_B2G
     260             : #include "nsPISocketTransportService.h"
     261             : #endif
     262             : 
     263             : // Apple system headers seem to have a check() macro.  <sigh>
     264             : #ifdef check
     265             : class nsIScriptTimeoutHandler;
     266             : #undef check
     267             : #endif // check
     268             : #include "AccessCheck.h"
     269             : 
     270             : #ifdef ANDROID
     271             : #include <android/log.h>
     272             : #endif
     273             : 
     274             : #ifdef XP_WIN
     275             : #include <process.h>
     276             : #define getpid _getpid
     277             : #else
     278             : #include <unistd.h> // for getpid()
     279             : #endif
     280             : 
     281             : static const char kStorageEnabled[] = "dom.storage.enabled";
     282             : 
     283             : using namespace mozilla;
     284             : using namespace mozilla::dom;
     285             : using namespace mozilla::dom::ipc;
     286             : using mozilla::BasePrincipal;
     287             : using mozilla::OriginAttributes;
     288             : using mozilla::TimeStamp;
     289             : using mozilla::TimeDuration;
     290             : using mozilla::dom::cache::CacheStorage;
     291             : 
     292             : static LazyLogModule gDOMLeakPRLog("DOMLeak");
     293             : 
     294             : nsGlobalWindow::WindowByIdTable *nsGlobalWindow::sWindowsById = nullptr;
     295             : bool nsGlobalWindow::sWarnedAboutWindowInternal = false;
     296             : bool nsGlobalWindow::sIdleObserversAPIFuzzTimeDisabled = false;
     297             : 
     298             : static int32_t              gRefCnt                    = 0;
     299             : static int32_t              gOpenPopupSpamCount        = 0;
     300             : static PopupControlState    gPopupControlState         = openAbused;
     301             : static bool                 gMouseDown                 = false;
     302             : static bool                 gDragServiceDisabled       = false;
     303             : static FILE                *gDumpFile                  = nullptr;
     304             : static uint32_t             gSerialCounter             = 0;
     305             : 
     306             : #ifdef DEBUG_jst
     307             : int32_t gTimeoutCnt                                    = 0;
     308             : #endif
     309             : 
     310             : #if defined(DEBUG_bryner) || defined(DEBUG_chb)
     311             : #define DEBUG_PAGE_CACHE
     312             : #endif
     313             : 
     314             : #define DOM_TOUCH_LISTENER_ADDED "dom-touch-listener-added"
     315             : 
     316             : // The interval at which we execute idle callbacks
     317             : static uint32_t gThrottledIdlePeriodLength;
     318             : 
     319             : #define DEFAULT_THROTTLED_IDLE_PERIOD_LENGTH 10000
     320             : 
     321             : #define FORWARD_TO_OUTER(method, args, err_rval)                              \
     322             :   PR_BEGIN_MACRO                                                              \
     323             :   if (IsInnerWindow()) {                                                      \
     324             :     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     325             :     if (!AsInner()->HasActiveDocument()) {                                    \
     326             :       NS_WARNING(outer ?                                                      \
     327             :                  "Inner window does not have active document." :              \
     328             :                  "No outer window available!");                               \
     329             :       return err_rval;                                                        \
     330             :     }                                                                         \
     331             :     return outer->method args;                                                \
     332             :   }                                                                           \
     333             :   PR_END_MACRO
     334             : 
     335             : #define FORWARD_TO_OUTER_OR_THROW(method, args, errorresult, err_rval)        \
     336             :   PR_BEGIN_MACRO                                                              \
     337             :   MOZ_RELEASE_ASSERT(IsInnerWindow());                                        \
     338             :   nsGlobalWindow *outer = GetOuterWindowInternal();                           \
     339             :   if (MOZ_LIKELY(AsInner()->HasActiveDocument())) {                           \
     340             :     return outer->method args;                                                \
     341             :   }                                                                           \
     342             :   if (!outer) {                                                               \
     343             :     NS_WARNING("No outer window available!");                                 \
     344             :     errorresult.Throw(NS_ERROR_NOT_INITIALIZED);                              \
     345             :   } else {                                                                    \
     346             :     errorresult.Throw(NS_ERROR_XPC_SECURITY_MANAGER_VETO);                    \
     347             :   }                                                                           \
     348             :   return err_rval;                                                            \
     349             :   PR_END_MACRO
     350             : 
     351             : #define FORWARD_TO_OUTER_VOID(method, args)                                   \
     352             :   PR_BEGIN_MACRO                                                              \
     353             :   if (IsInnerWindow()) {                                                      \
     354             :     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     355             :     if (!AsInner()->HasActiveDocument()) {                                    \
     356             :       NS_WARNING(outer ?                                                      \
     357             :                  "Inner window does not have active document." :              \
     358             :                  "No outer window available!");                               \
     359             :       return;                                                                 \
     360             :     }                                                                         \
     361             :     outer->method args;                                                       \
     362             :     return;                                                                   \
     363             :   }                                                                           \
     364             :   PR_END_MACRO
     365             : 
     366             : #define FORWARD_TO_OUTER_CHROME(method, args, err_rval)                       \
     367             :   PR_BEGIN_MACRO                                                              \
     368             :   if (IsInnerWindow()) {                                                      \
     369             :     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     370             :     if (!AsInner()->HasActiveDocument()) {                                    \
     371             :       NS_WARNING(outer ?                                                      \
     372             :                  "Inner window does not have active document." :              \
     373             :                  "No outer window available!");                               \
     374             :       return err_rval;                                                        \
     375             :     }                                                                         \
     376             :     return ((nsGlobalChromeWindow *)outer)->method args;                      \
     377             :   }                                                                           \
     378             :   PR_END_MACRO
     379             : 
     380             : #define FORWARD_TO_INNER_CHROME(method, args, err_rval)                       \
     381             :   PR_BEGIN_MACRO                                                              \
     382             :   if (IsOuterWindow()) {                                                      \
     383             :     if (!mInnerWindow) {                                                      \
     384             :       NS_WARNING("No inner window available!");                               \
     385             :       return err_rval;                                                        \
     386             :     }                                                                         \
     387             :     return ((nsGlobalChromeWindow *)nsGlobalWindow::Cast(mInnerWindow))->method args; \
     388             :   }                                                                           \
     389             :   PR_END_MACRO
     390             : 
     391             : #define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval)         \
     392             :   PR_BEGIN_MACRO                                                              \
     393             :   if (IsInnerWindow()) {                                                      \
     394             :     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     395             :     if (!AsInner()->HasActiveDocument()) {                                    \
     396             :       NS_WARNING(outer ?                                                      \
     397             :                  "Inner window does not have active document." :              \
     398             :                  "No outer window available!");                               \
     399             :       return err_rval;                                                        \
     400             :     }                                                                         \
     401             :     return ((nsGlobalModalWindow *)outer)->method args;                       \
     402             :   }                                                                           \
     403             :   PR_END_MACRO
     404             : 
     405             : #define FORWARD_TO_INNER(method, args, err_rval)                              \
     406             :   PR_BEGIN_MACRO                                                              \
     407             :   if (IsOuterWindow()) {                                                      \
     408             :     if (!mInnerWindow) {                                                      \
     409             :       NS_WARNING("No inner window available!");                               \
     410             :       return err_rval;                                                        \
     411             :     }                                                                         \
     412             :     return GetCurrentInnerWindowInternal()->method args;                      \
     413             :   }                                                                           \
     414             :   PR_END_MACRO
     415             : 
     416             : #define FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(method, args, err_rval)         \
     417             :   PR_BEGIN_MACRO                                                              \
     418             :   if (IsOuterWindow()) {                                                      \
     419             :     if (!mInnerWindow) {                                                      \
     420             :       NS_WARNING("No inner window available!");                               \
     421             :       return err_rval;                                                        \
     422             :     }                                                                         \
     423             :     return ((nsGlobalModalWindow*)GetCurrentInnerWindowInternal())->method args; \
     424             :   }                                                                           \
     425             :   PR_END_MACRO
     426             : 
     427             : #define FORWARD_TO_INNER_VOID(method, args)                                   \
     428             :   PR_BEGIN_MACRO                                                              \
     429             :   if (IsOuterWindow()) {                                                      \
     430             :     if (!mInnerWindow) {                                                      \
     431             :       NS_WARNING("No inner window available!");                               \
     432             :       return;                                                                 \
     433             :     }                                                                         \
     434             :     GetCurrentInnerWindowInternal()->method args;                             \
     435             :     return;                                                                   \
     436             :   }                                                                           \
     437             :   PR_END_MACRO
     438             : 
     439             : // Same as FORWARD_TO_INNER, but this will create a fresh inner if an
     440             : // inner doesn't already exists.
     441             : #define FORWARD_TO_INNER_CREATE(method, args, err_rval)                       \
     442             :   PR_BEGIN_MACRO                                                              \
     443             :   if (IsOuterWindow()) {                                                      \
     444             :     if (!mInnerWindow) {                                                      \
     445             :       if (mIsClosed) {                                                        \
     446             :         return err_rval;                                                      \
     447             :       }                                                                       \
     448             :       nsCOMPtr<nsIDocument> kungFuDeathGrip = GetDoc();                       \
     449             :       ::mozilla::Unused << kungFuDeathGrip;                                   \
     450             :       if (!mInnerWindow) {                                                    \
     451             :         return err_rval;                                                      \
     452             :       }                                                                       \
     453             :     }                                                                         \
     454             :     return GetCurrentInnerWindowInternal()->method args;                      \
     455             :   }                                                                           \
     456             :   PR_END_MACRO
     457             : 
     458             : // CIDs
     459             : static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
     460             : 
     461             : #define NETWORK_UPLOAD_EVENT_NAME     NS_LITERAL_STRING("moznetworkupload")
     462             : #define NETWORK_DOWNLOAD_EVENT_NAME   NS_LITERAL_STRING("moznetworkdownload")
     463             : 
     464             : /**
     465             :  * An indirect observer object that means we don't have to implement nsIObserver
     466             :  * on nsGlobalWindow, where any script could see it.
     467             :  */
     468             : class nsGlobalWindowObserver final : public nsIObserver
     469             :                                    , public nsIInterfaceRequestor
     470             :                                    , public StorageNotificationObserver
     471             : {
     472             : public:
     473           7 :   explicit nsGlobalWindowObserver(nsGlobalWindow* aWindow) : mWindow(aWindow) {}
     474             :   NS_DECL_ISUPPORTS
     475           0 :   NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) override
     476             :   {
     477           0 :     if (!mWindow)
     478           0 :       return NS_OK;
     479           0 :     return mWindow->Observe(aSubject, aTopic, aData);
     480             :   }
     481           1 :   void Forget() { mWindow = nullptr; }
     482           0 :   NS_IMETHOD GetInterface(const nsIID& aIID, void** aResult) override
     483             :   {
     484           0 :     if (mWindow && aIID.Equals(NS_GET_IID(nsIDOMWindow)) && mWindow) {
     485           0 :       return mWindow->QueryInterface(aIID, aResult);
     486             :     }
     487           0 :     return NS_NOINTERFACE;
     488             :   }
     489             : 
     490             :   void
     491           0 :   ObserveStorageNotification(StorageEvent* aEvent,
     492             :                              const char16_t* aStorageType,
     493             :                              bool aPrivateBrowsing) override
     494             :   {
     495           0 :     if (mWindow) {
     496           0 :       mWindow->ObserveStorageNotification(aEvent, aStorageType,
     497           0 :                                           aPrivateBrowsing);
     498             :     }
     499           0 :   }
     500             : 
     501             :   virtual nsIEventTarget*
     502           0 :   GetEventTarget() const override
     503             :   {
     504           0 :     return mWindow ? mWindow->EventTargetFor(TaskCategory::Other) : nullptr;
     505             :   }
     506             : 
     507             : private:
     508             :   ~nsGlobalWindowObserver() = default;
     509             : 
     510             :   // This reference is non-owning and safe because it's cleared by
     511             :   // nsGlobalWindow::CleanUp().
     512             :   nsGlobalWindow* MOZ_NON_OWNING_REF mWindow;
     513             : };
     514             : 
     515          94 : NS_IMPL_ISUPPORTS(nsGlobalWindowObserver, nsIObserver, nsIInterfaceRequestor)
     516             : 
     517             : static already_AddRefed<nsIVariant>
     518           0 : CreateVoidVariant()
     519             : {
     520           0 :   RefPtr<nsVariantCC> writable = new nsVariantCC();
     521           0 :   writable->SetAsVoid();
     522           0 :   return writable.forget();
     523             : }
     524             : 
     525             : nsresult
     526           0 : DialogValueHolder::Get(nsIPrincipal* aSubject, nsIVariant** aResult)
     527             : {
     528           0 :   nsCOMPtr<nsIVariant> result;
     529           0 :   if (aSubject->SubsumesConsideringDomain(mOrigin)) {
     530           0 :     result = mValue;
     531             :   } else {
     532           0 :     result = CreateVoidVariant();
     533             :   }
     534           0 :   result.forget(aResult);
     535           0 :   return NS_OK;
     536             : }
     537             : 
     538             : void
     539           0 : DialogValueHolder::Get(JSContext* aCx, JS::Handle<JSObject*> aScope,
     540             :                        nsIPrincipal* aSubject,
     541             :                        JS::MutableHandle<JS::Value> aResult,
     542             :                        mozilla::ErrorResult& aError)
     543             : {
     544           0 :   if (aSubject->Subsumes(mOrigin)) {
     545           0 :     aError = nsContentUtils::XPConnect()->VariantToJS(aCx, aScope,
     546           0 :                                                       mValue, aResult);
     547             :   } else {
     548           0 :     aResult.setUndefined();
     549             :   }
     550           0 : }
     551             : 
     552             : class IdleRequestExecutor;
     553             : 
     554             : class IdleRequestExecutorTimeoutHandler final : public TimeoutHandler
     555             : {
     556             : public:
     557           1 :   explicit IdleRequestExecutorTimeoutHandler(IdleRequestExecutor* aExecutor)
     558           1 :     : mExecutor(aExecutor)
     559             :   {
     560           1 :   }
     561             : 
     562             :   NS_DECL_ISUPPORTS_INHERITED
     563           1 :   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestExecutorTimeoutHandler,
     564             :                                            TimeoutHandler)
     565             : 
     566             :   nsresult Call() override;
     567             : 
     568             : private:
     569           0 :   ~IdleRequestExecutorTimeoutHandler() override {}
     570             :   RefPtr<IdleRequestExecutor> mExecutor;
     571             : };
     572             : 
     573           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler, mExecutor)
     574             : 
     575           2 : NS_IMPL_ADDREF_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler)
     576           1 : NS_IMPL_RELEASE_INHERITED(IdleRequestExecutorTimeoutHandler, TimeoutHandler)
     577             : 
     578           2 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutorTimeoutHandler)
     579           1 : NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
     580             : 
     581             : 
     582             : class IdleRequestExecutor final : public nsIRunnable
     583             :                                 , public nsICancelableRunnable
     584             :                                 , public nsINamed
     585             :                                 , public nsIIdleRunnable
     586             : {
     587             : public:
     588           1 :   explicit IdleRequestExecutor(nsGlobalWindow* aWindow)
     589           1 :     : mDispatched(false)
     590             :     , mDeadline(TimeStamp::Now())
     591           1 :     , mWindow(aWindow)
     592             :   {
     593           1 :     MOZ_DIAGNOSTIC_ASSERT(mWindow);
     594           1 :     MOZ_DIAGNOSTIC_ASSERT(mWindow->IsInnerWindow());
     595             : 
     596           1 :     mIdlePeriodLimit = { mDeadline, mWindow->LastIdleRequestHandle() };
     597           1 :     mDelayedExecutorDispatcher = new IdleRequestExecutorTimeoutHandler(this);
     598           1 :   }
     599             : 
     600             :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     601           7 :   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(IdleRequestExecutor, nsIRunnable)
     602             : 
     603             :   NS_DECL_NSIRUNNABLE
     604             :   NS_DECL_NSINAMED
     605             :   nsresult Cancel() override;
     606             :   void SetDeadline(TimeStamp aDeadline) override;
     607             : 
     608           1 :   bool IsCancelled() const { return !mWindow || mWindow->AsInner()->InnerObjectsFreed(); }
     609             :   // Checks if aRequest shouldn't execute in the current idle period
     610             :   // since it has been queued from a chained call to
     611             :   // requestIdleCallback from within a running idle callback.
     612           0 :   bool IneligibleForCurrentIdlePeriod(IdleRequest* aRequest) const
     613             :   {
     614           0 :     return aRequest->Handle() >= mIdlePeriodLimit.mLastRequestIdInIdlePeriod &&
     615           0 :            TimeStamp::Now() <= mIdlePeriodLimit.mEndOfIdlePeriod;
     616             :   }
     617             : 
     618             :   void MaybeUpdateIdlePeriodLimit();
     619             : 
     620             :   // Maybe dispatch the IdleRequestExecutor. MabyeDispatch will
     621             :   // schedule a delayed dispatch if the associated window is in the
     622             :   // background or if given a time to wait until dispatching.
     623             :   void MaybeDispatch(TimeStamp aDelayUntil = TimeStamp());
     624             :   void ScheduleDispatch();
     625             : private:
     626           1 :   struct IdlePeriodLimit
     627             :   {
     628             :     TimeStamp mEndOfIdlePeriod;
     629             :     uint32_t mLastRequestIdInIdlePeriod;
     630             :   };
     631             : 
     632             :   void DelayedDispatch(uint32_t aDelay);
     633             : 
     634           0 :   ~IdleRequestExecutor() override {}
     635             : 
     636             :   bool mDispatched;
     637             :   TimeStamp mDeadline;
     638             :   IdlePeriodLimit mIdlePeriodLimit;
     639             :   RefPtr<nsGlobalWindow> mWindow;
     640             :   // The timeout handler responsible for dispatching this executor in
     641             :   // the case of immediate dispatch to the idle queue isn't
     642             :   // desirable. This is used if we've dispatched all idle callbacks
     643             :   // that are allowed to run in the current idle period, or if the
     644             :   // associated window is currently in the background.
     645             :   nsCOMPtr<nsITimeoutHandler> mDelayedExecutorDispatcher;
     646             :   // If not Nothing() then this value is the handle to the currently
     647             :   // scheduled delayed executor dispatcher. This is needed to be able
     648             :   // to cancel the timeout handler in case of the executor being
     649             :   // cancelled.
     650             :   Maybe<int32_t> mDelayedExecutorHandle;
     651             : };
     652             : 
     653             : NS_IMPL_CYCLE_COLLECTION_CLASS(IdleRequestExecutor)
     654             : 
     655           4 : NS_IMPL_CYCLE_COLLECTING_ADDREF(IdleRequestExecutor)
     656           1 : NS_IMPL_CYCLE_COLLECTING_RELEASE(IdleRequestExecutor)
     657             : 
     658           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IdleRequestExecutor)
     659           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
     660           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDelayedExecutorDispatcher)
     661           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     662             : 
     663           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IdleRequestExecutor)
     664           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
     665           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDelayedExecutorDispatcher)
     666           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     667             : 
     668           2 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestExecutor)
     669           1 :   NS_INTERFACE_MAP_ENTRY(nsIRunnable)
     670           0 :   NS_INTERFACE_MAP_ENTRY(nsICancelableRunnable)
     671           0 :   NS_INTERFACE_MAP_ENTRY(nsINamed)
     672           0 :   NS_INTERFACE_MAP_ENTRY(nsIIdleRunnable)
     673           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIRunnable)
     674           0 : NS_INTERFACE_MAP_END
     675             : 
     676             : NS_IMETHODIMP
     677           0 : IdleRequestExecutor::GetName(nsACString& aName)
     678             : {
     679           0 :     aName.AssignASCII("IdleRequestExecutor");
     680           0 :     return NS_OK;
     681             : }
     682             : 
     683             : NS_IMETHODIMP
     684           0 : IdleRequestExecutor::SetName(const char* aName)
     685             : {
     686           0 :   return NS_ERROR_NOT_IMPLEMENTED;
     687             : }
     688             : 
     689             : NS_IMETHODIMP
     690           0 : IdleRequestExecutor::Run()
     691             : {
     692           0 :   MOZ_ASSERT(NS_IsMainThread());
     693             : 
     694           0 :   mDispatched = false;
     695           0 :   if (mWindow) {
     696           0 :     return mWindow->ExecuteIdleRequest(mDeadline);
     697             :   }
     698             : 
     699           0 :   return NS_OK;
     700             : }
     701             : 
     702             : nsresult
     703           0 : IdleRequestExecutor::Cancel()
     704             : {
     705           0 :   MOZ_ASSERT(NS_IsMainThread());
     706             : 
     707           0 :   if (mDelayedExecutorHandle && mWindow) {
     708           0 :     mWindow->AsInner()->TimeoutManager().ClearTimeout(
     709             :       mDelayedExecutorHandle.value(),
     710           0 :       Timeout::Reason::eIdleCallbackTimeout);
     711             :   }
     712             : 
     713           0 :   mWindow = nullptr;
     714           0 :   return NS_OK;
     715             : }
     716             : 
     717             : void
     718           0 : IdleRequestExecutor::SetDeadline(TimeStamp aDeadline)
     719             : {
     720           0 :   MOZ_ASSERT(NS_IsMainThread());
     721             : 
     722           0 :   if (!mWindow) {
     723           0 :     return;
     724             :   }
     725             : 
     726           0 :   mDeadline = aDeadline;
     727             : }
     728             : 
     729             : void
     730           0 : IdleRequestExecutor::MaybeUpdateIdlePeriodLimit()
     731             : {
     732           0 :   if (TimeStamp::Now() > mIdlePeriodLimit.mEndOfIdlePeriod) {
     733           0 :     mIdlePeriodLimit = { mDeadline, mWindow->LastIdleRequestHandle() };
     734             :   }
     735           0 : }
     736             : 
     737             : void
     738           3 : IdleRequestExecutor::MaybeDispatch(TimeStamp aDelayUntil)
     739             : {
     740             :   // If we've already dispatched the executor we don't want to do it
     741             :   // again. Also, if we've called IdleRequestExecutor::Cancel mWindow
     742             :   // will be null, which indicates that we shouldn't dispatch this
     743             :   // executor either.
     744           3 :   if (mDispatched || IsCancelled()) {
     745           5 :     return;
     746             :   }
     747             : 
     748           1 :   mDispatched = true;
     749             : 
     750           1 :   nsPIDOMWindowOuter* outer = mWindow->GetOuterWindow();
     751           1 :   if (outer && outer->AsOuter()->IsBackground()) {
     752             :     // Set a timeout handler with a timeout of 0 ms to throttle idle
     753             :     // callback requests coming from a backround window using
     754             :     // background timeout throttling.
     755           0 :     DelayedDispatch(0);
     756           0 :     return;
     757             :   }
     758             : 
     759           1 :   TimeStamp now = TimeStamp::Now();
     760           1 :   if (!aDelayUntil || aDelayUntil < now) {
     761           1 :     ScheduleDispatch();
     762           1 :     return;
     763             :   }
     764             : 
     765           0 :   TimeDuration delay = aDelayUntil - now;
     766           0 :   DelayedDispatch(static_cast<uint32_t>(delay.ToMilliseconds()));
     767             : }
     768             : 
     769             : void
     770           1 : IdleRequestExecutor::ScheduleDispatch()
     771             : {
     772           1 :   MOZ_ASSERT(mWindow);
     773           1 :   mDelayedExecutorHandle = Nothing();
     774           2 :   RefPtr<IdleRequestExecutor> request = this;
     775           1 :   NS_IdleDispatchToCurrentThread(request.forget());
     776           1 : }
     777             : 
     778             : void
     779           0 : IdleRequestExecutor::DelayedDispatch(uint32_t aDelay)
     780             : {
     781           0 :   MOZ_ASSERT(mWindow);
     782           0 :   MOZ_ASSERT(mDelayedExecutorHandle.isNothing());
     783             :   int32_t handle;
     784           0 :   mWindow->AsInner()->TimeoutManager().SetTimeout(
     785           0 :     mDelayedExecutorDispatcher, aDelay, false, Timeout::Reason::eIdleCallbackTimeout, &handle);
     786           0 :   mDelayedExecutorHandle = Some(handle);
     787           0 : }
     788             : 
     789             : nsresult
     790           0 : IdleRequestExecutorTimeoutHandler::Call()
     791             : {
     792           0 :   if (!mExecutor->IsCancelled()) {
     793           0 :     mExecutor->ScheduleDispatch();
     794             :   }
     795           0 :   return NS_OK;
     796             : }
     797             : 
     798             : void
     799           3 : nsGlobalWindow::ScheduleIdleRequestDispatch()
     800             : {
     801           3 :   AssertIsOnMainThread();
     802             : 
     803           3 :   if (!mIdleRequestExecutor) {
     804           1 :     mIdleRequestExecutor = new IdleRequestExecutor(this);
     805             :   }
     806             : 
     807           3 :   mIdleRequestExecutor->MaybeDispatch();
     808           3 : }
     809             : 
     810             : void
     811           0 : nsGlobalWindow::SuspendIdleRequests()
     812             : {
     813           0 :   if (mIdleRequestExecutor) {
     814           0 :     mIdleRequestExecutor->Cancel();
     815           0 :     mIdleRequestExecutor = nullptr;
     816             :   }
     817           0 : }
     818             : 
     819             : void
     820           0 : nsGlobalWindow::ResumeIdleRequests()
     821             : {
     822           0 :   MOZ_ASSERT(!mIdleRequestExecutor);
     823             : 
     824           0 :   ScheduleIdleRequestDispatch();
     825           0 : }
     826             : 
     827             : void
     828           3 : nsGlobalWindow::InsertIdleCallback(IdleRequest* aRequest)
     829             : {
     830           3 :   AssertIsOnMainThread();
     831           3 :   mIdleRequestCallbacks.insertBack(aRequest);
     832           3 :   aRequest->AddRef();
     833           3 : }
     834             : 
     835             : void
     836           1 : nsGlobalWindow::RemoveIdleCallback(mozilla::dom::IdleRequest* aRequest)
     837             : {
     838           1 :   AssertIsOnMainThread();
     839             : 
     840           1 :   if (aRequest->HasTimeout()) {
     841           1 :     mTimeoutManager->ClearTimeout(aRequest->GetTimeoutHandle(),
     842           1 :                                   Timeout::Reason::eIdleCallbackTimeout);
     843             :   }
     844             : 
     845           1 :   aRequest->removeFrom(mIdleRequestCallbacks);
     846           1 :   aRequest->Release();
     847           1 : }
     848             : 
     849             : nsresult
     850           1 : nsGlobalWindow::RunIdleRequest(IdleRequest* aRequest,
     851             :                                DOMHighResTimeStamp aDeadline,
     852             :                                bool aDidTimeout)
     853             : {
     854           1 :   AssertIsOnMainThread();
     855           2 :   RefPtr<IdleRequest> request(aRequest);
     856           1 :   RemoveIdleCallback(request);
     857           2 :   return request->IdleRun(AsInner(), aDeadline, aDidTimeout);
     858             : }
     859             : 
     860             : nsresult
     861           0 : nsGlobalWindow::ExecuteIdleRequest(TimeStamp aDeadline)
     862             : {
     863           0 :   AssertIsOnMainThread();
     864           0 :   RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
     865             : 
     866           0 :   if (!request) {
     867             :     // There are no more idle requests, so stop scheduling idle
     868             :     // request callbacks.
     869           0 :     return NS_OK;
     870             :   }
     871             : 
     872             :   // If the request that we're trying to execute has been queued
     873             :   // during the current idle period, then dispatch it again at the end
     874             :   // of the idle period.
     875           0 :   if (mIdleRequestExecutor->IneligibleForCurrentIdlePeriod(request)) {
     876           0 :     mIdleRequestExecutor->MaybeDispatch(aDeadline);
     877           0 :     return NS_OK;
     878             :   }
     879             : 
     880           0 :   DOMHighResTimeStamp deadline = 0.0;
     881             : 
     882           0 :   if (Performance* perf = GetPerformance()) {
     883           0 :     deadline = perf->GetDOMTiming()->TimeStampToDOMHighRes(aDeadline);
     884             :   }
     885             : 
     886           0 :   mIdleRequestExecutor->MaybeUpdateIdlePeriodLimit();
     887           0 :   nsresult result = RunIdleRequest(request, deadline, false);
     888             : 
     889             :   // Running the idle callback could've suspended the window, in which
     890             :   // case mIdleRequestExecutor will be null.
     891           0 :   if (mIdleRequestExecutor) {
     892           0 :     mIdleRequestExecutor->MaybeDispatch();
     893             :   }
     894           0 :   return result;
     895             : }
     896             : 
     897             : class IdleRequestTimeoutHandler final : public TimeoutHandler
     898             : {
     899             : public:
     900           2 :   IdleRequestTimeoutHandler(JSContext* aCx,
     901             :                             IdleRequest* aIdleRequest,
     902             :                             nsPIDOMWindowInner* aWindow)
     903           2 :     : TimeoutHandler(aCx)
     904             :     , mIdleRequest(aIdleRequest)
     905           2 :     , mWindow(aWindow)
     906             :   {
     907           2 :   }
     908             : 
     909             :   NS_DECL_ISUPPORTS_INHERITED
     910           2 :   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IdleRequestTimeoutHandler,
     911             :                                            TimeoutHandler)
     912             : 
     913           1 :   nsresult Call() override
     914             :   {
     915           1 :     return nsGlobalWindow::Cast(mWindow)->RunIdleRequest(mIdleRequest, 0.0, true);
     916             :   }
     917             : 
     918             : private:
     919           0 :   ~IdleRequestTimeoutHandler() override {}
     920             : 
     921             :   RefPtr<IdleRequest> mIdleRequest;
     922             :   nsCOMPtr<nsPIDOMWindowInner> mWindow;
     923             : };
     924             : 
     925           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(IdleRequestTimeoutHandler,
     926             :                                    TimeoutHandler,
     927             :                                    mIdleRequest,
     928             :                                    mWindow)
     929             : 
     930           9 : NS_IMPL_ADDREF_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler)
     931           7 : NS_IMPL_RELEASE_INHERITED(IdleRequestTimeoutHandler, TimeoutHandler)
     932             : 
     933           7 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IdleRequestTimeoutHandler)
     934           5 : NS_INTERFACE_MAP_END_INHERITING(TimeoutHandler)
     935             : 
     936             : uint32_t
     937           3 : nsGlobalWindow::RequestIdleCallback(JSContext* aCx,
     938             :                                     IdleRequestCallback& aCallback,
     939             :                                     const IdleRequestOptions& aOptions,
     940             :                                     ErrorResult& aError)
     941             : {
     942           3 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
     943           3 :   AssertIsOnMainThread();
     944             : 
     945           3 :   uint32_t handle = mIdleRequestCallbackCounter++;
     946             : 
     947             :   RefPtr<IdleRequest> request =
     948           6 :     new IdleRequest(&aCallback, handle);
     949             : 
     950           3 :   if (aOptions.mTimeout.WasPassed()) {
     951             :     int32_t timeoutHandle;
     952           6 :     nsCOMPtr<nsITimeoutHandler> handler(new IdleRequestTimeoutHandler(aCx, request, AsInner()));
     953             : 
     954           2 :     nsresult rv = mTimeoutManager->SetTimeout(
     955           2 :         handler, aOptions.mTimeout.Value(), false,
     956           2 :         Timeout::Reason::eIdleCallbackTimeout, &timeoutHandle);
     957             : 
     958           2 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     959           0 :       return 0;
     960             :     }
     961             : 
     962           2 :     request->SetTimeoutHandle(timeoutHandle);
     963             :   }
     964             : 
     965             :   // mIdleRequestCallbacks now owns request
     966           3 :   InsertIdleCallback(request);
     967             : 
     968           3 :   if (!IsSuspended()) {
     969           3 :     ScheduleIdleRequestDispatch();
     970             :   }
     971             : 
     972           3 :   return handle;
     973             : }
     974             : 
     975             : void
     976           0 : nsGlobalWindow::CancelIdleCallback(uint32_t aHandle)
     977             : {
     978           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
     979             : 
     980           0 :   for (IdleRequest* r : mIdleRequestCallbacks) {
     981           0 :     if (r->Handle() == aHandle) {
     982           0 :       RemoveIdleCallback(r);
     983           0 :       break;
     984             :     }
     985             :   }
     986           0 : }
     987             : 
     988             : void
     989           4 : nsGlobalWindow::DisableIdleCallbackRequests()
     990             : {
     991           4 :   if (mIdleRequestExecutor) {
     992           0 :     mIdleRequestExecutor->Cancel();
     993           0 :     mIdleRequestExecutor = nullptr;
     994             :   }
     995             : 
     996           4 :   while (!mIdleRequestCallbacks.isEmpty()) {
     997           0 :     RefPtr<IdleRequest> request = mIdleRequestCallbacks.getFirst();
     998           0 :     RemoveIdleCallback(request);
     999             :   }
    1000           4 : }
    1001             : 
    1002             : bool
    1003          12 : nsGlobalWindow::IsBackgroundInternal() const
    1004             : {
    1005          12 :   return !mOuterWindow || mOuterWindow->IsBackground();
    1006             : }
    1007             : namespace mozilla {
    1008             : namespace dom {
    1009             : extern uint64_t
    1010             : NextWindowID();
    1011             : } // namespace dom
    1012             : } // namespace mozilla
    1013             : 
    1014             : template<class T>
    1015          12 : nsPIDOMWindow<T>::nsPIDOMWindow(nsPIDOMWindowOuter *aOuterWindow)
    1016             : : mFrameElement(nullptr), mDocShell(nullptr), mModalStateDepth(0),
    1017             :   mMutationBits(0), mIsDocumentLoaded(false),
    1018          12 :   mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nullptr),
    1019             :   mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
    1020             :   mMayHaveSelectionChangeEventListener(false),
    1021             :   mMayHaveMouseEnterLeaveEventListener(false),
    1022             :   mMayHavePointerEnterLeaveEventListener(false),
    1023             :   mInnerObjectsFreed(false),
    1024             :   mIsModalContentWindow(false),
    1025             :   mIsActive(false), mIsBackground(false),
    1026          12 :   mMediaSuspend(Preferences::GetBool("media.block-autoplay-until-in-foreground", true) ?
    1027             :     nsISuspendedTypes::SUSPENDED_BLOCK : nsISuspendedTypes::NONE_SUSPENDED),
    1028             :   mAudioMuted(false), mAudioVolume(1.0), mAudioCaptured(false),
    1029             :   mDesktopModeViewport(false), mIsRootOuterWindow(false), mInnerWindow(nullptr),
    1030             :   mOuterWindow(aOuterWindow),
    1031             :   // Make sure no actual window ends up with mWindowID == 0
    1032          12 :   mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
    1033             :   mMarkedCCGeneration(0), mServiceWorkersTestingEnabled(false),
    1034             :   mLargeAllocStatus(LargeAllocStatus::NONE),
    1035             :   mHasTriedToCacheTopInnerWindow(false),
    1036          48 :   mNumOfIndexedDBDatabases(0)
    1037             : {
    1038          12 :   if (aOuterWindow) {
    1039           7 :     mTimeoutManager =
    1040           7 :       MakeUnique<mozilla::dom::TimeoutManager>(*nsGlobalWindow::Cast(AsInner()));
    1041             :   }
    1042          12 : }
    1043             : 
    1044             : template<class T>
    1045           0 : nsPIDOMWindow<T>::~nsPIDOMWindow() {}
    1046             : 
    1047             : /* static */
    1048             : nsPIDOMWindowOuter*
    1049          35 : nsPIDOMWindowOuter::GetFromCurrentInner(nsPIDOMWindowInner* aInner)
    1050             : {
    1051          35 :   if (!aInner) {
    1052           0 :     return nullptr;
    1053             :   }
    1054             : 
    1055          35 :   nsPIDOMWindowOuter* outer = aInner->GetOuterWindow();
    1056          35 :   if (!outer || outer->GetCurrentInnerWindow() != aInner) {
    1057           0 :     return nullptr;
    1058             :   }
    1059             : 
    1060          35 :   return outer;
    1061             : }
    1062             : 
    1063             : // DialogValueHolder CC goop.
    1064           0 : NS_IMPL_CYCLE_COLLECTION(DialogValueHolder, mValue)
    1065             : 
    1066           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DialogValueHolder)
    1067           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
    1068           0 : NS_INTERFACE_MAP_END
    1069             : 
    1070           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DialogValueHolder)
    1071           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DialogValueHolder)
    1072             : 
    1073             : //*****************************************************************************
    1074             : // nsOuterWindowProxy: Outer Window Proxy
    1075             : //*****************************************************************************
    1076             : 
    1077             : class nsOuterWindowProxy : public js::Wrapper
    1078             : {
    1079             : public:
    1080             :   constexpr nsOuterWindowProxy() : js::Wrapper(0) { }
    1081             : 
    1082           7 :   bool finalizeInBackground(const JS::Value& priv) const override {
    1083           7 :     return false;
    1084             :   }
    1085             : 
    1086             :   // Standard internal methods
    1087             :   bool getOwnPropertyDescriptor(JSContext* cx,
    1088             :                                 JS::Handle<JSObject*> proxy,
    1089             :                                 JS::Handle<jsid> id,
    1090             :                                 JS::MutableHandle<JS::PropertyDescriptor> desc)
    1091             :                                 const override;
    1092             :   bool defineProperty(JSContext* cx,
    1093             :                       JS::Handle<JSObject*> proxy,
    1094             :                       JS::Handle<jsid> id,
    1095             :                       JS::Handle<JS::PropertyDescriptor> desc,
    1096             :                       JS::ObjectOpResult &result) const override;
    1097             :   bool ownPropertyKeys(JSContext *cx,
    1098             :                        JS::Handle<JSObject*> proxy,
    1099             :                        JS::AutoIdVector &props) const override;
    1100             :   bool delete_(JSContext *cx, JS::Handle<JSObject*> proxy,
    1101             :                        JS::Handle<jsid> id,
    1102             :                        JS::ObjectOpResult &result) const override;
    1103             : 
    1104             :   bool getPrototypeIfOrdinary(JSContext* cx,
    1105             :                               JS::Handle<JSObject*> proxy,
    1106             :                               bool* isOrdinary,
    1107             :                               JS::MutableHandle<JSObject*> protop) const override;
    1108             : 
    1109             :   JSObject* enumerate(JSContext *cx, JS::Handle<JSObject*> proxy) const override;
    1110             :   bool preventExtensions(JSContext* cx,
    1111             :                          JS::Handle<JSObject*> proxy,
    1112             :                          JS::ObjectOpResult& result) const override;
    1113             :   bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
    1114             :                     const override;
    1115             :   bool has(JSContext *cx, JS::Handle<JSObject*> proxy,
    1116             :            JS::Handle<jsid> id, bool *bp) const override;
    1117             :   bool get(JSContext *cx, JS::Handle<JSObject*> proxy,
    1118             :            JS::Handle<JS::Value> receiver,
    1119             :            JS::Handle<jsid> id,
    1120             :            JS::MutableHandle<JS::Value> vp) const override;
    1121             :   bool set(JSContext *cx, JS::Handle<JSObject*> proxy,
    1122             :            JS::Handle<jsid> id, JS::Handle<JS::Value> v,
    1123             :            JS::Handle<JS::Value> receiver,
    1124             :            JS::ObjectOpResult &result) const override;
    1125             : 
    1126             :   // SpiderMonkey extensions
    1127             :   bool getPropertyDescriptor(JSContext* cx,
    1128             :                              JS::Handle<JSObject*> proxy,
    1129             :                              JS::Handle<jsid> id,
    1130             :                              JS::MutableHandle<JS::PropertyDescriptor> desc)
    1131             :                              const override;
    1132             :   bool hasOwn(JSContext *cx, JS::Handle<JSObject*> proxy,
    1133             :               JS::Handle<jsid> id, bool *bp) const override;
    1134             :   bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> proxy,
    1135             :                                     JS::AutoIdVector &props) const override;
    1136             :   const char *className(JSContext *cx,
    1137             :                         JS::Handle<JSObject*> wrapper) const override;
    1138             : 
    1139             :   void finalize(JSFreeOp *fop, JSObject *proxy) const override;
    1140             : 
    1141          70 :   bool isCallable(JSObject *obj) const override {
    1142          70 :     return false;
    1143             :   }
    1144          17 :   bool isConstructor(JSObject *obj) const override {
    1145          17 :     return false;
    1146             :   }
    1147             : 
    1148             :   bool watch(JSContext *cx, JS::Handle<JSObject*> proxy,
    1149             :              JS::Handle<jsid> id, JS::Handle<JSObject*> callable) const override;
    1150             :   bool unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
    1151             :                JS::Handle<jsid> id) const override;
    1152             : 
    1153             :   static void ObjectMoved(JSObject *obj, const JSObject *old);
    1154             : 
    1155             :   static const nsOuterWindowProxy singleton;
    1156             : 
    1157             : protected:
    1158           0 :   static nsGlobalWindow* GetOuterWindow(JSObject *proxy)
    1159             :   {
    1160             :     nsGlobalWindow* outerWindow = nsGlobalWindow::FromSupports(
    1161           0 :       static_cast<nsISupports*>(js::GetProxyReservedSlot(proxy, 0).toPrivate()));
    1162           0 :     MOZ_ASSERT_IF(outerWindow, outerWindow->IsOuterWindow());
    1163           0 :     return outerWindow;
    1164             :   }
    1165             : 
    1166             :   // False return value means we threw an exception.  True return value
    1167             :   // but false "found" means we didn't have a subframe at that index.
    1168             :   bool GetSubframeWindow(JSContext *cx, JS::Handle<JSObject*> proxy,
    1169             :                          JS::Handle<jsid> id,
    1170             :                          JS::MutableHandle<JS::Value> vp,
    1171             :                          bool &found) const;
    1172             : 
    1173             :   // Returns a non-null window only if id is an index and we have a
    1174             :   // window at that index.
    1175             :   already_AddRefed<nsPIDOMWindowOuter>
    1176             :   GetSubframeWindow(JSContext *cx,
    1177             :                     JS::Handle<JSObject*> proxy,
    1178             :                     JS::Handle<jsid> id) const;
    1179             : 
    1180             :   bool AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
    1181             :                                   JS::AutoIdVector &props) const;
    1182             : };
    1183             : 
    1184             : static const js::ClassExtension OuterWindowProxyClassExtension = PROXY_MAKE_EXT(
    1185             :     nsOuterWindowProxy::ObjectMoved
    1186             : );
    1187             : 
    1188             : // Give OuterWindowProxyClass 2 reserved slots, like the other wrappers, so
    1189             : // JSObject::swap can swap it with CrossCompartmentWrappers without requiring
    1190             : // malloc.
    1191             : const js::Class OuterWindowProxyClass = PROXY_CLASS_WITH_EXT(
    1192             :     "Proxy",
    1193             :     JSCLASS_HAS_RESERVED_SLOTS(2), /* additional class flags */
    1194             :     &OuterWindowProxyClassExtension);
    1195             : 
    1196             : const char *
    1197           0 : nsOuterWindowProxy::className(JSContext *cx, JS::Handle<JSObject*> proxy) const
    1198             : {
    1199           0 :     MOZ_ASSERT(js::IsProxy(proxy));
    1200             : 
    1201           0 :     return "Window";
    1202             : }
    1203             : 
    1204             : void
    1205           0 : nsOuterWindowProxy::finalize(JSFreeOp *fop, JSObject *proxy) const
    1206             : {
    1207           0 :   nsGlobalWindow* outerWindow = GetOuterWindow(proxy);
    1208           0 :   if (outerWindow) {
    1209           0 :     outerWindow->ClearWrapper(proxy);
    1210             : 
    1211             :     // Ideally we would use OnFinalize here, but it's possible that
    1212             :     // EnsureScriptEnvironment will later be called on the window, and we don't
    1213             :     // want to create a new script object in that case. Therefore, we need to
    1214             :     // write a non-null value that will reliably crash when dereferenced.
    1215           0 :     outerWindow->PoisonOuterWindowProxy(proxy);
    1216             :   }
    1217           0 : }
    1218             : 
    1219             : bool
    1220           0 : nsOuterWindowProxy::getPropertyDescriptor(JSContext* cx,
    1221             :                                           JS::Handle<JSObject*> proxy,
    1222             :                                           JS::Handle<jsid> id,
    1223             :                                           JS::MutableHandle<JS::PropertyDescriptor> desc) const
    1224             : {
    1225             :   // The only thing we can do differently from js::Wrapper is shadow stuff with
    1226             :   // our indexed properties, so we can just try getOwnPropertyDescriptor and if
    1227             :   // that gives us nothing call on through to js::Wrapper.
    1228           0 :   desc.object().set(nullptr);
    1229           0 :   if (!getOwnPropertyDescriptor(cx, proxy, id, desc)) {
    1230           0 :     return false;
    1231             :   }
    1232             : 
    1233           0 :   if (desc.object()) {
    1234           0 :     return true;
    1235             :   }
    1236             : 
    1237           0 :   return js::Wrapper::getPropertyDescriptor(cx, proxy, id, desc);
    1238             : }
    1239             : 
    1240             : bool
    1241          30 : nsOuterWindowProxy::getOwnPropertyDescriptor(JSContext* cx,
    1242             :                                              JS::Handle<JSObject*> proxy,
    1243             :                                              JS::Handle<jsid> id,
    1244             :                                              JS::MutableHandle<JS::PropertyDescriptor> desc)
    1245             :                                              const
    1246             : {
    1247             :   bool found;
    1248          30 :   if (!GetSubframeWindow(cx, proxy, id, desc.value(), found)) {
    1249           0 :     return false;
    1250             :   }
    1251          30 :   if (found) {
    1252           0 :     FillPropertyDescriptor(desc, proxy, true);
    1253           0 :     return true;
    1254             :   }
    1255             :   // else fall through to js::Wrapper
    1256             : 
    1257          30 :   return js::Wrapper::getOwnPropertyDescriptor(cx, proxy, id, desc);
    1258             : }
    1259             : 
    1260             : bool
    1261         216 : nsOuterWindowProxy::defineProperty(JSContext* cx,
    1262             :                                    JS::Handle<JSObject*> proxy,
    1263             :                                    JS::Handle<jsid> id,
    1264             :                                    JS::Handle<JS::PropertyDescriptor> desc,
    1265             :                                    JS::ObjectOpResult &result) const
    1266             : {
    1267         216 :   if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
    1268             :     // Spec says to Reject whether this is a supported index or not,
    1269             :     // since we have no indexed setter or indexed creator.  It is up
    1270             :     // to the caller to decide whether to throw a TypeError.
    1271           0 :     return result.failCantDefineWindowElement();
    1272             :   }
    1273             : 
    1274         216 :   return js::Wrapper::defineProperty(cx, proxy, id, desc, result);
    1275             : }
    1276             : 
    1277             : bool
    1278           0 : nsOuterWindowProxy::ownPropertyKeys(JSContext *cx,
    1279             :                                     JS::Handle<JSObject*> proxy,
    1280             :                                     JS::AutoIdVector &props) const
    1281             : {
    1282             :   // Just our indexed stuff followed by our "normal" own property names.
    1283           0 :   if (!AppendIndexedPropertyNames(cx, proxy, props)) {
    1284           0 :     return false;
    1285             :   }
    1286             : 
    1287           0 :   JS::AutoIdVector innerProps(cx);
    1288           0 :   if (!js::Wrapper::ownPropertyKeys(cx, proxy, innerProps)) {
    1289           0 :     return false;
    1290             :   }
    1291           0 :   return js::AppendUnique(cx, props, innerProps);
    1292             : }
    1293             : 
    1294             : bool
    1295          40 : nsOuterWindowProxy::delete_(JSContext *cx, JS::Handle<JSObject*> proxy,
    1296             :                             JS::Handle<jsid> id, JS::ObjectOpResult &result) const
    1297             : {
    1298          80 :   if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
    1299             :     // Fail (which means throw if strict, else return false).
    1300           0 :     return result.failCantDeleteWindowElement();
    1301             :   }
    1302             : 
    1303          40 :   if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
    1304             :     // Indexed, but not supported.  Spec says return true.
    1305           0 :     return result.succeed();
    1306             :   }
    1307             : 
    1308          40 :   return js::Wrapper::delete_(cx, proxy, id, result);
    1309             : }
    1310             : 
    1311             : bool
    1312           0 : nsOuterWindowProxy::getPrototypeIfOrdinary(JSContext* cx,
    1313             :                                            JS::Handle<JSObject*> proxy,
    1314             :                                            bool* isOrdinary,
    1315             :                                            JS::MutableHandle<JSObject*> protop) const
    1316             : {
    1317             :   // Window's [[GetPrototypeOf]] trap isn't the ordinary definition:
    1318             :   //
    1319             :   //   https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-getprototypeof
    1320             :   //
    1321             :   // We nonetheless can implement it with a static [[Prototype]], because
    1322             :   // wrapper-class handlers (particularly, XOW in FilteringWrapper.cpp) supply
    1323             :   // all non-ordinary behavior.
    1324             :   //
    1325             :   // But from a spec point of view, it's the exact same object in both cases --
    1326             :   // only the observer's changed.  So this getPrototypeIfOrdinary trap on the
    1327             :   // non-wrapper object *must* report non-ordinary, even if static [[Prototype]]
    1328             :   // usually means ordinary.
    1329           0 :   *isOrdinary = false;
    1330           0 :   return true;
    1331             : }
    1332             : 
    1333             : bool
    1334           0 : nsOuterWindowProxy::preventExtensions(JSContext* cx,
    1335             :                                       JS::Handle<JSObject*> proxy,
    1336             :                                       JS::ObjectOpResult& result) const
    1337             : {
    1338             :   // If [[Extensible]] could be false, then navigating a window could navigate
    1339             :   // to a window that's [[Extensible]] after being at one that wasn't: an
    1340             :   // invariant violation.  So never change a window's extensibility.
    1341           0 :   return result.failCantPreventExtensions();
    1342             : }
    1343             : 
    1344             : bool
    1345           0 : nsOuterWindowProxy::isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy,
    1346             :                                  bool *extensible) const
    1347             : {
    1348             :   // See above.
    1349           0 :   *extensible = true;
    1350           0 :   return true;
    1351             : }
    1352             : 
    1353             : bool
    1354           0 : nsOuterWindowProxy::has(JSContext *cx, JS::Handle<JSObject*> proxy,
    1355             :                         JS::Handle<jsid> id, bool *bp) const
    1356             : {
    1357           0 :   if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
    1358           0 :     *bp = true;
    1359           0 :     return true;
    1360             :   }
    1361             : 
    1362           0 :   return js::Wrapper::has(cx, proxy, id, bp);
    1363             : }
    1364             : 
    1365             : bool
    1366           1 : nsOuterWindowProxy::hasOwn(JSContext *cx, JS::Handle<JSObject*> proxy,
    1367             :                            JS::Handle<jsid> id, bool *bp) const
    1368             : {
    1369           2 :   if (nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id)) {
    1370           0 :     *bp = true;
    1371           0 :     return true;
    1372             :   }
    1373             : 
    1374           1 :   return js::Wrapper::hasOwn(cx, proxy, id, bp);
    1375             : }
    1376             : 
    1377             : bool
    1378         268 : nsOuterWindowProxy::get(JSContext *cx, JS::Handle<JSObject*> proxy,
    1379             :                         JS::Handle<JS::Value> receiver,
    1380             :                         JS::Handle<jsid> id,
    1381             :                         JS::MutableHandle<JS::Value> vp) const
    1382             : {
    1383         268 :   if (id == nsDOMClassInfo::sWrappedJSObject_id &&
    1384           0 :       xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
    1385           0 :     vp.set(JS::ObjectValue(*proxy));
    1386           0 :     return true;
    1387             :   }
    1388             : 
    1389             :   bool found;
    1390         268 :   if (!GetSubframeWindow(cx, proxy, id, vp, found)) {
    1391           0 :     return false;
    1392             :   }
    1393         268 :   if (found) {
    1394           0 :     return true;
    1395             :   }
    1396             :   // Else fall through to js::Wrapper
    1397             : 
    1398         268 :   return js::Wrapper::get(cx, proxy, receiver, id, vp);
    1399             : }
    1400             : 
    1401             : bool
    1402           6 : nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
    1403             :                         JS::Handle<jsid> id,
    1404             :                         JS::Handle<JS::Value> v,
    1405             :                         JS::Handle<JS::Value> receiver,
    1406             :                         JS::ObjectOpResult &result) const
    1407             : {
    1408           6 :   if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
    1409             :     // Reject the set.  It's up to the caller to decide whether to throw a
    1410             :     // TypeError.  If the caller is strict mode JS code, it'll throw.
    1411           0 :     return result.failReadOnly();
    1412             :   }
    1413             : 
    1414           6 :   return js::Wrapper::set(cx, proxy, id, v, receiver, result);
    1415             : }
    1416             : 
    1417             : bool
    1418           0 : nsOuterWindowProxy::getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> proxy,
    1419             :                                                  JS::AutoIdVector &props) const
    1420             : {
    1421             :   // Like ownPropertyKeys, our indexed stuff followed by our "normal" enumerable
    1422             :   // own property names.
    1423             :   //
    1424             :   // Note that this does not match current spec per
    1425             :   // https://github.com/whatwg/html/issues/2753 but as that issue says I believe
    1426             :   // the spec is wrong.
    1427           0 :   if (!AppendIndexedPropertyNames(cx, proxy, props)) {
    1428           0 :     return false;
    1429             :   }
    1430             : 
    1431           0 :   JS::AutoIdVector innerProps(cx);
    1432           0 :   if (!js::Wrapper::getOwnEnumerablePropertyKeys(cx, proxy, innerProps)) {
    1433           0 :     return false;
    1434             :   }
    1435           0 :   return js::AppendUnique(cx, props, innerProps);
    1436             : }
    1437             : 
    1438             : JSObject*
    1439           0 : nsOuterWindowProxy::enumerate(JSContext *cx, JS::Handle<JSObject*> proxy) const
    1440             : {
    1441             :   // BaseProxyHandler::enumerate seems to do what we want here: fall
    1442             :   // back on the property names returned from js::GetPropertyKeys()
    1443           0 :   return js::BaseProxyHandler::enumerate(cx, proxy);
    1444             : }
    1445             : 
    1446             : bool
    1447         298 : nsOuterWindowProxy::GetSubframeWindow(JSContext *cx,
    1448             :                                       JS::Handle<JSObject*> proxy,
    1449             :                                       JS::Handle<jsid> id,
    1450             :                                       JS::MutableHandle<JS::Value> vp,
    1451             :                                       bool& found) const
    1452             : {
    1453         596 :   nsCOMPtr<nsPIDOMWindowOuter> frame = GetSubframeWindow(cx, proxy, id);
    1454         298 :   if (!frame) {
    1455         298 :     found = false;
    1456         298 :     return true;
    1457             :   }
    1458             : 
    1459           0 :   found = true;
    1460             :   // Just return the window's global
    1461           0 :   nsGlobalWindow* global = nsGlobalWindow::Cast(frame);
    1462           0 :   frame->EnsureInnerWindow();
    1463           0 :   JSObject* obj = global->FastGetGlobalJSObject();
    1464             :   // This null check fixes a hard-to-reproduce crash that occurs when we
    1465             :   // get here when we're mid-call to nsDocShell::Destroy. See bug 640904
    1466             :   // comment 105.
    1467           0 :   if (MOZ_UNLIKELY(!obj)) {
    1468           0 :     return xpc::Throw(cx, NS_ERROR_FAILURE);
    1469             :   }
    1470           0 :   JS::ExposeObjectToActiveJS(obj);
    1471           0 :   vp.setObject(*obj);
    1472           0 :   return JS_WrapValue(cx, vp);
    1473             : }
    1474             : 
    1475             : already_AddRefed<nsPIDOMWindowOuter>
    1476         339 : nsOuterWindowProxy::GetSubframeWindow(JSContext *cx,
    1477             :                                       JS::Handle<JSObject*> proxy,
    1478             :                                       JS::Handle<jsid> id) const
    1479             : {
    1480         339 :   uint32_t index = GetArrayIndexFromId(cx, id);
    1481         339 :   if (!IsArrayIndex(index)) {
    1482         339 :     return nullptr;
    1483             :   }
    1484             : 
    1485           0 :   nsGlobalWindow* win = GetOuterWindow(proxy);
    1486           0 :   MOZ_ASSERT(win->IsOuterWindow());
    1487           0 :   return win->IndexedGetterOuter(index);
    1488             : }
    1489             : 
    1490             : bool
    1491           0 : nsOuterWindowProxy::AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
    1492             :                                                JS::AutoIdVector &props) const
    1493             : {
    1494           0 :   uint32_t length = GetOuterWindow(proxy)->Length();
    1495           0 :   MOZ_ASSERT(int32_t(length) >= 0);
    1496           0 :   if (!props.reserve(props.length() + length)) {
    1497           0 :     return false;
    1498             :   }
    1499           0 :   for (int32_t i = 0; i < int32_t(length); ++i) {
    1500           0 :     if (!props.append(INT_TO_JSID(i))) {
    1501           0 :       return false;
    1502             :     }
    1503             :   }
    1504             : 
    1505           0 :   return true;
    1506             : }
    1507             : 
    1508             : bool
    1509           0 : nsOuterWindowProxy::watch(JSContext *cx, JS::Handle<JSObject*> proxy,
    1510             :                           JS::Handle<jsid> id, JS::Handle<JSObject*> callable) const
    1511             : {
    1512           0 :   return js::WatchGuts(cx, proxy, id, callable);
    1513             : }
    1514             : 
    1515             : bool
    1516           0 : nsOuterWindowProxy::unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
    1517             :                             JS::Handle<jsid> id) const
    1518             : {
    1519           0 :   return js::UnwatchGuts(cx, proxy, id);
    1520             : }
    1521             : 
    1522             : void
    1523           0 : nsOuterWindowProxy::ObjectMoved(JSObject *obj, const JSObject *old)
    1524             : {
    1525           0 :   nsGlobalWindow* outerWindow = GetOuterWindow(obj);
    1526           0 :   if (outerWindow) {
    1527           0 :     outerWindow->UpdateWrapper(obj, old);
    1528             :   }
    1529           0 : }
    1530             : 
    1531             : const nsOuterWindowProxy
    1532             : nsOuterWindowProxy::singleton;
    1533             : 
    1534             : class nsChromeOuterWindowProxy : public nsOuterWindowProxy
    1535             : {
    1536             : public:
    1537             :   constexpr nsChromeOuterWindowProxy() : nsOuterWindowProxy() { }
    1538             : 
    1539             :   const char *className(JSContext *cx, JS::Handle<JSObject*> wrapper) const override;
    1540             : 
    1541             :   static const nsChromeOuterWindowProxy singleton;
    1542             : };
    1543             : 
    1544             : const char *
    1545           0 : nsChromeOuterWindowProxy::className(JSContext *cx,
    1546             :                                     JS::Handle<JSObject*> proxy) const
    1547             : {
    1548           0 :     MOZ_ASSERT(js::IsProxy(proxy));
    1549             : 
    1550           0 :     return "ChromeWindow";
    1551             : }
    1552             : 
    1553             : const nsChromeOuterWindowProxy
    1554             : nsChromeOuterWindowProxy::singleton;
    1555             : 
    1556             : static JSObject*
    1557           7 : NewOuterWindowProxy(JSContext *cx, JS::Handle<JSObject*> global, bool isChrome)
    1558             : {
    1559          14 :   JSAutoCompartment ac(cx, global);
    1560           7 :   MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(global) == global);
    1561             : 
    1562          14 :   js::WrapperOptions options;
    1563           7 :   options.setClass(&OuterWindowProxyClass);
    1564           7 :   options.setSingleton(true);
    1565          14 :   JSObject *obj = js::Wrapper::New(cx, global,
    1566             :                                    isChrome ? &nsChromeOuterWindowProxy::singleton
    1567             :                                             : &nsOuterWindowProxy::singleton,
    1568          14 :                                    options);
    1569           7 :   MOZ_ASSERT_IF(obj, js::IsWindowProxy(obj));
    1570          14 :   return obj;
    1571             : }
    1572             : 
    1573             : //*****************************************************************************
    1574             : //***    nsGlobalWindow: Object Management
    1575             : //*****************************************************************************
    1576             : 
    1577          12 : nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
    1578           7 :   : nsPIDOMWindow<nsISupports>(aOuterWindow ? aOuterWindow->AsOuter() : nullptr),
    1579             :     mIdleFuzzFactor(0),
    1580             :     mIdleCallbackIndex(-1),
    1581             :     mCurrentlyIdle(false),
    1582             :     mAddActiveEventFuzzTime(true),
    1583             :     mFullScreen(false),
    1584             :     mFullscreenMode(false),
    1585             :     mIsClosed(false),
    1586             :     mInClose(false),
    1587             :     mHavePendingClose(false),
    1588             :     mHadOriginalOpener(false),
    1589             :     mOriginalOpenerWasSecureContext(false),
    1590             :     mIsPopupSpam(false),
    1591             :     mBlockScriptedClosingFlag(false),
    1592             :     mWasOffline(false),
    1593             :     mHasHadSlowScript(false),
    1594             :     mNotifyIdleObserversIdleOnThaw(false),
    1595             :     mNotifyIdleObserversActiveOnThaw(false),
    1596             :     mCreatingInnerWindow(false),
    1597             :     mIsChrome(false),
    1598             :     mCleanMessageManager(false),
    1599             :     mNeedsFocus(true),
    1600             :     mHasFocus(false),
    1601             :     mShowFocusRingForContent(false),
    1602             :     mFocusByKeyOccurred(false),
    1603             :     mHasGamepad(false),
    1604             :     mHasVREvents(false),
    1605             :     mHasVRDisplayActivateEvents(false),
    1606             :     mHasSeenGamepadInput(false),
    1607             :     mNotifiedIDDestroyed(false),
    1608             :     mAllowScriptsToClose(false),
    1609             :     mTopLevelOuterContentWindow(false),
    1610             :     mSuspendDepth(0),
    1611             :     mFreezeDepth(0),
    1612             :     mFocusMethod(0),
    1613             :     mSerial(0),
    1614             :     mIdleRequestCallbackCounter(1),
    1615             :     mIdleRequestExecutor(nullptr),
    1616             : #ifdef DEBUG
    1617             :     mSetOpenerWindowCalled(false),
    1618             : #endif
    1619             : #ifdef MOZ_B2G
    1620             :     mNetworkUploadObserverEnabled(false),
    1621             :     mNetworkDownloadObserverEnabled(false),
    1622             : #endif
    1623             :     mCleanedUp(false),
    1624             :     mDialogAbuseCount(0),
    1625             :     mAreDialogsEnabled(true),
    1626             : #ifdef DEBUG
    1627             :     mIsValidatingTabGroup(false),
    1628             : #endif
    1629             :     mCanSkipCCGeneration(0),
    1630             :     mAutoActivateVRDisplayID(0),
    1631          19 :     mBeforeUnloadListenerCount(0)
    1632             : {
    1633          12 :   AssertIsOnMainThread();
    1634             : 
    1635          12 :   nsLayoutStatics::AddRef();
    1636             : 
    1637             :   // Initialize the PRCList (this).
    1638          12 :   PR_INIT_CLIST(this);
    1639             : 
    1640          12 :   if (aOuterWindow) {
    1641             :     // |this| is an inner window, add this inner window to the outer
    1642             :     // window list of inners.
    1643           7 :     PR_INSERT_AFTER(this, aOuterWindow);
    1644             : 
    1645           7 :     mObserver = new nsGlobalWindowObserver(this);
    1646           7 :     if (mObserver) {
    1647          14 :       nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1648           7 :       if (os) {
    1649             :         // Watch for online/offline status changes so we can fire events. Use
    1650             :         // a strong reference.
    1651           7 :         os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
    1652           7 :                         false);
    1653             :       }
    1654             : 
    1655           7 :       Preferences::AddStrongObserver(mObserver, "intl.accept_languages");
    1656             : 
    1657             :       // Watch for storage notifications so we can fire storage events.
    1658             :       RefPtr<StorageNotifierService> sns =
    1659          14 :         StorageNotifierService::GetOrCreate();
    1660           7 :       if (sns) {
    1661           7 :         sns->Register(mObserver);
    1662             :       }
    1663             :     }
    1664             :   } else {
    1665             :     // |this| is an outer window. Outer windows start out frozen and
    1666             :     // remain frozen until they get an inner window.
    1667           5 :     MOZ_ASSERT(IsFrozen());
    1668             :   }
    1669             : 
    1670          12 :   if (XRE_IsContentProcess()) {
    1671           6 :     nsCOMPtr<nsIDocShell> docShell = GetDocShell();
    1672           3 :     if (docShell) {
    1673           2 :       mTabChild = docShell->GetTabChild();
    1674             :     }
    1675             :   }
    1676             : 
    1677             :   // We could have failed the first time through trying
    1678             :   // to create the entropy collector, so we should
    1679             :   // try to get one until we succeed.
    1680             : 
    1681          12 :   gRefCnt++;
    1682             : 
    1683             :   static bool sFirstTime = true;
    1684          12 :   if (sFirstTime) {
    1685           2 :     TimeoutManager::Initialize();
    1686             :     Preferences::AddBoolVarCache(&sIdleObserversAPIFuzzTimeDisabled,
    1687             :                                  "dom.idle-observers-api.fuzz_time.disabled",
    1688           2 :                                  false);
    1689             : 
    1690             :     Preferences::AddUintVarCache(&gThrottledIdlePeriodLength,
    1691             :                                  "dom.idle_period.throttled_length",
    1692           2 :                                  DEFAULT_THROTTLED_IDLE_PERIOD_LENGTH);
    1693           2 :     sFirstTime = false;
    1694             :   }
    1695             : 
    1696          12 :   if (gDumpFile == nullptr) {
    1697             :     const nsAdoptingCString& fname =
    1698           4 :       Preferences::GetCString("browser.dom.window.dump.file");
    1699           2 :     if (!fname.IsEmpty()) {
    1700             :       // if this fails to open, Dump() knows to just go to stdout
    1701             :       // on null.
    1702           0 :       gDumpFile = fopen(fname, "wb+");
    1703             :     } else {
    1704           2 :       gDumpFile = stdout;
    1705             :     }
    1706             :   }
    1707             : 
    1708          12 :   mSerial = ++gSerialCounter;
    1709             : 
    1710             : #ifdef DEBUG
    1711          12 :   if (!PR_GetEnv("MOZ_QUIET")) {
    1712          12 :     printf_stderr("++DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p]\n",
    1713             :                   gRefCnt,
    1714          12 :                   static_cast<void*>(ToCanonicalSupports(this)),
    1715             :                   getpid(),
    1716             :                   gSerialCounter,
    1717          24 :                   static_cast<void*>(ToCanonicalSupports(aOuterWindow)));
    1718             :   }
    1719             : #endif
    1720             : 
    1721          12 :   MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
    1722             :           ("DOMWINDOW %p created outer=%p", this, aOuterWindow));
    1723             : 
    1724          12 :   NS_ASSERTION(sWindowsById, "Windows hash table must be created!");
    1725          12 :   NS_ASSERTION(!sWindowsById->Get(mWindowID),
    1726             :                "This window shouldn't be in the hash table yet!");
    1727             :   // We seem to see crashes in release builds because of null |sWindowsById|.
    1728          12 :   if (sWindowsById) {
    1729          12 :     sWindowsById->Put(mWindowID, this);
    1730             :   }
    1731          12 : }
    1732             : 
    1733             : #ifdef DEBUG
    1734             : 
    1735             : /* static */
    1736             : void
    1737        1174 : nsGlobalWindow::AssertIsOnMainThread()
    1738             : {
    1739        1174 :   MOZ_ASSERT(NS_IsMainThread());
    1740        1174 : }
    1741             : 
    1742             : #endif // DEBUG
    1743             : 
    1744             : /* static */
    1745             : void
    1746           3 : nsGlobalWindow::Init()
    1747             : {
    1748           3 :   AssertIsOnMainThread();
    1749             : 
    1750           3 :   NS_ASSERTION(gDOMLeakPRLog, "gDOMLeakPRLog should have been initialized!");
    1751             : 
    1752           3 :   sWindowsById = new WindowByIdTable();
    1753           3 : }
    1754             : 
    1755           0 : nsGlobalWindow::~nsGlobalWindow()
    1756             : {
    1757           0 :   AssertIsOnMainThread();
    1758             : 
    1759           0 :   DisconnectEventTargetObjects();
    1760             : 
    1761             :   // We have to check if sWindowsById isn't null because ::Shutdown might have
    1762             :   // been called.
    1763           0 :   if (sWindowsById) {
    1764           0 :     NS_ASSERTION(sWindowsById->Get(mWindowID),
    1765             :                  "This window should be in the hash table");
    1766           0 :     sWindowsById->Remove(mWindowID);
    1767             :   }
    1768             : 
    1769           0 :   --gRefCnt;
    1770             : 
    1771             : #ifdef DEBUG
    1772           0 :   if (!PR_GetEnv("MOZ_QUIET")) {
    1773           0 :     nsAutoCString url;
    1774           0 :     if (mLastOpenedURI) {
    1775           0 :       url = mLastOpenedURI->GetSpecOrDefault();
    1776             : 
    1777             :       // Data URLs can be very long, so truncate to avoid flooding the log.
    1778           0 :       const uint32_t maxURLLength = 1000;
    1779           0 :       if (url.Length() > maxURLLength) {
    1780           0 :         url.Truncate(maxURLLength);
    1781             :       }
    1782             :     }
    1783             : 
    1784           0 :     nsGlobalWindow* outer = nsGlobalWindow::Cast(mOuterWindow);
    1785           0 :     printf_stderr("--DOMWINDOW == %d (%p) [pid = %d] [serial = %d] [outer = %p] [url = %s]\n",
    1786             :                   gRefCnt,
    1787           0 :                   static_cast<void*>(ToCanonicalSupports(this)),
    1788             :                   getpid(),
    1789             :                   mSerial,
    1790           0 :                   static_cast<void*>(ToCanonicalSupports(outer)),
    1791           0 :                   url.get());
    1792             :   }
    1793             : #endif
    1794             : 
    1795           0 :   MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug, ("DOMWINDOW %p destroyed", this));
    1796             : 
    1797           0 :   if (IsOuterWindow()) {
    1798           0 :     JSObject *proxy = GetWrapperMaybeDead();
    1799           0 :     if (proxy) {
    1800           0 :       js::SetProxyReservedSlot(proxy, 0, js::PrivateValue(nullptr));
    1801             :     }
    1802             : 
    1803             :     // An outer window is destroyed with inner windows still possibly
    1804             :     // alive, iterate through the inner windows and null out their
    1805             :     // back pointer to this outer, and pull them out of the list of
    1806             :     // inner windows.
    1807             : 
    1808             :     nsGlobalWindow *w;
    1809           0 :     while ((w = (nsGlobalWindow *)PR_LIST_HEAD(this)) != this) {
    1810           0 :       PR_REMOVE_AND_INIT_LINK(w);
    1811             :     }
    1812             : 
    1813           0 :     DropOuterWindowDocs();
    1814             :   } else {
    1815           0 :     Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
    1816           0 :                           mMutationBits ? 1 : 0);
    1817             : 
    1818           0 :     if (mListenerManager) {
    1819           0 :       mListenerManager->Disconnect();
    1820           0 :       mListenerManager = nullptr;
    1821             :     }
    1822             : 
    1823             :     // An inner window is destroyed, pull it out of the outer window's
    1824             :     // list if inner windows.
    1825             : 
    1826           0 :     PR_REMOVE_LINK(this);
    1827             : 
    1828             :     // If our outer window's inner window is this window, null out the
    1829             :     // outer window's reference to this window that's being deleted.
    1830           0 :     nsGlobalWindow *outer = GetOuterWindowInternal();
    1831           0 :     if (outer) {
    1832           0 :       outer->MaybeClearInnerWindow(this);
    1833             :     }
    1834             :   }
    1835             : 
    1836             :   // We don't have to leave the tab group if we are an inner window.
    1837           0 :   if (mTabGroup && IsOuterWindow()) {
    1838           0 :     mTabGroup->Leave(AsOuter());
    1839             :   }
    1840             : 
    1841             :   // Outer windows are always supposed to call CleanUp before letting themselves
    1842             :   // be destroyed. And while CleanUp generally seems to be intended to clean up
    1843             :   // outers, we've historically called it for both. Changing this would probably
    1844             :   // involve auditing all of the references that inners and outers can have, and
    1845             :   // separating the handling into CleanUp() and FreeInnerObjects.
    1846           0 :   if (IsInnerWindow()) {
    1847           0 :     CleanUp();
    1848             :   } else {
    1849           0 :     MOZ_ASSERT(mCleanedUp);
    1850             :   }
    1851             : 
    1852           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
    1853           0 :   if (ac)
    1854           0 :     ac->RemoveWindowAsListener(this);
    1855             : 
    1856           0 :   nsLayoutStatics::Release();
    1857           0 : }
    1858             : 
    1859             : void
    1860          11 : nsGlobalWindow::AddEventTargetObject(DOMEventTargetHelper* aObject)
    1861             : {
    1862          11 :   MOZ_ASSERT(IsInnerWindow());
    1863          11 :   mEventTargetObjects.PutEntry(aObject);
    1864          11 : }
    1865             : 
    1866             : void
    1867           0 : nsGlobalWindow::RemoveEventTargetObject(DOMEventTargetHelper* aObject)
    1868             : {
    1869           0 :   MOZ_ASSERT(IsInnerWindow());
    1870           0 :   mEventTargetObjects.RemoveEntry(aObject);
    1871           0 : }
    1872             : 
    1873             : void
    1874           2 : nsGlobalWindow::DisconnectEventTargetObjects()
    1875             : {
    1876           3 :   for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done();
    1877           1 :        iter.Next()) {
    1878           2 :     RefPtr<DOMEventTargetHelper> target = iter.Get()->GetKey();
    1879           1 :     target->DisconnectFromOwner();
    1880             :   }
    1881           2 :   mEventTargetObjects.Clear();
    1882           2 : }
    1883             : 
    1884             : // static
    1885             : void
    1886           0 : nsGlobalWindow::ShutDown()
    1887             : {
    1888           0 :   AssertIsOnMainThread();
    1889             : 
    1890           0 :   if (gDumpFile && gDumpFile != stdout) {
    1891           0 :     fclose(gDumpFile);
    1892             :   }
    1893           0 :   gDumpFile = nullptr;
    1894             : 
    1895           0 :   delete sWindowsById;
    1896           0 :   sWindowsById = nullptr;
    1897           0 : }
    1898             : 
    1899             : // static
    1900             : void
    1901           5 : nsGlobalWindow::CleanupCachedXBLHandlers(nsGlobalWindow* aWindow)
    1902             : {
    1903           5 :   if (aWindow->mCachedXBLPrototypeHandlers &&
    1904           5 :       aWindow->mCachedXBLPrototypeHandlers->Count() > 0) {
    1905           0 :     aWindow->mCachedXBLPrototypeHandlers->Clear();
    1906             :   }
    1907           5 : }
    1908             : 
    1909             : void
    1910           1 : nsGlobalWindow::MaybeForgiveSpamCount()
    1911             : {
    1912           2 :   if (IsOuterWindow() &&
    1913           1 :       IsPopupSpamWindow()) {
    1914           0 :     SetIsPopupSpamWindow(false);
    1915             :   }
    1916           1 : }
    1917             : 
    1918             : void
    1919           0 : nsGlobalWindow::SetIsPopupSpamWindow(bool aIsPopupSpam)
    1920             : {
    1921           0 :   MOZ_ASSERT(IsOuterWindow());
    1922             : 
    1923           0 :   mIsPopupSpam = aIsPopupSpam;
    1924           0 :   if (aIsPopupSpam) {
    1925           0 :     ++gOpenPopupSpamCount;
    1926             :   } else {
    1927           0 :     --gOpenPopupSpamCount;
    1928           0 :     NS_ASSERTION(gOpenPopupSpamCount >= 0,
    1929             :                  "Unbalanced decrement of gOpenPopupSpamCount");
    1930             :   }
    1931           0 : }
    1932             : 
    1933             : void
    1934           1 : nsGlobalWindow::DropOuterWindowDocs()
    1935             : {
    1936           1 :   MOZ_ASSERT(IsOuterWindow());
    1937           1 :   MOZ_ASSERT_IF(mDoc, !mDoc->EventHandlingSuppressed());
    1938           1 :   mDoc = nullptr;
    1939           1 :   mSuspendedDoc = nullptr;
    1940           1 : }
    1941             : 
    1942             : void
    1943           2 : nsGlobalWindow::CleanUp()
    1944             : {
    1945             :   // Guarantee idempotence.
    1946           2 :   if (mCleanedUp)
    1947           0 :     return;
    1948           2 :   mCleanedUp = true;
    1949             : 
    1950           2 :   StartDying();
    1951             : 
    1952           2 :   DisconnectEventTargetObjects();
    1953             : 
    1954           2 :   if (mObserver) {
    1955           2 :     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1956           1 :     if (os) {
    1957           1 :       os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
    1958             :     }
    1959             : 
    1960           2 :     RefPtr<StorageNotifierService> sns = StorageNotifierService::GetOrCreate();
    1961           1 :     if (sns) {
    1962           1 :      sns->Unregister(mObserver);
    1963             :     }
    1964             : 
    1965             : #ifdef MOZ_B2G
    1966             :     DisableNetworkEvent(eNetworkUpload);
    1967             :     DisableNetworkEvent(eNetworkDownload);
    1968             : #endif // MOZ_B2G
    1969             : 
    1970           1 :     if (mIdleService) {
    1971           0 :       mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
    1972             :     }
    1973             : 
    1974           1 :     Preferences::RemoveObserver(mObserver, "intl.accept_languages");
    1975             : 
    1976             :     // Drop its reference to this dying window, in case for some bogus reason
    1977             :     // the object stays around.
    1978           1 :     mObserver->Forget();
    1979             :   }
    1980             : 
    1981           2 :   if (mNavigator) {
    1982           0 :     mNavigator->Invalidate();
    1983           0 :     mNavigator = nullptr;
    1984             :   }
    1985             : 
    1986           2 :   mScreen = nullptr;
    1987           2 :   mMenubar = nullptr;
    1988           2 :   mToolbar = nullptr;
    1989           2 :   mLocationbar = nullptr;
    1990           2 :   mPersonalbar = nullptr;
    1991           2 :   mStatusbar = nullptr;
    1992           2 :   mScrollbars = nullptr;
    1993           2 :   mHistory = nullptr;
    1994           2 :   mCustomElements = nullptr;
    1995           2 :   mFrames = nullptr;
    1996           2 :   mWindowUtils = nullptr;
    1997           2 :   mApplicationCache = nullptr;
    1998           2 :   mIndexedDB = nullptr;
    1999             : 
    2000           2 :   mConsole = nullptr;
    2001             : 
    2002           2 :   mAudioWorklet = nullptr;
    2003           2 :   mPaintWorklet = nullptr;
    2004             : 
    2005           2 :   mExternal = nullptr;
    2006             : 
    2007           2 :   mMozSelfSupport = nullptr;
    2008             : 
    2009           2 :   mPerformance = nullptr;
    2010             : 
    2011             : #ifdef MOZ_WEBSPEECH
    2012           2 :   mSpeechSynthesis = nullptr;
    2013             : #endif
    2014             : 
    2015             : #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
    2016             :   mOrientationChangeObserver = nullptr;
    2017             : #endif
    2018             : 
    2019           2 :   ClearControllers();
    2020             : 
    2021           2 :   mOpener = nullptr;             // Forces Release
    2022           2 :   if (mContext) {
    2023           0 :     mContext = nullptr;            // Forces Release
    2024             :   }
    2025           2 :   mChromeEventHandler = nullptr; // Forces Release
    2026           2 :   mParentTarget = nullptr;
    2027             : 
    2028           2 :   if (IsOuterWindow()) {
    2029           1 :     nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
    2030           1 :     if (inner) {
    2031           1 :       inner->CleanUp();
    2032             :     }
    2033             :   }
    2034             : 
    2035           2 :   if (IsInnerWindow()) {
    2036           1 :     DisableGamepadUpdates();
    2037           1 :     mHasGamepad = false;
    2038           1 :     DisableVRUpdates();
    2039           1 :     mHasVREvents = false;
    2040           1 :     mHasVRDisplayActivateEvents = false;
    2041             : #ifdef MOZ_B2G
    2042             :     DisableTimeChangeNotifications();
    2043             : #endif
    2044           1 :     DisableIdleCallbackRequests();
    2045             :   } else {
    2046           1 :     MOZ_ASSERT(!mHasGamepad);
    2047           1 :     MOZ_ASSERT(!mHasVREvents);
    2048           1 :     MOZ_ASSERT(!mHasVRDisplayActivateEvents);
    2049             :   }
    2050             : 
    2051           2 :   if (mCleanMessageManager) {
    2052           0 :     MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
    2053           0 :     nsGlobalChromeWindow *asChrome = static_cast<nsGlobalChromeWindow*>(this);
    2054           0 :     if (asChrome->mMessageManager) {
    2055             :       static_cast<nsFrameMessageManager*>(
    2056           0 :         asChrome->mMessageManager.get())->Disconnect();
    2057             :     }
    2058             :   }
    2059             : 
    2060           2 :   mArguments = nullptr;
    2061           2 :   mDialogArguments = nullptr;
    2062             : 
    2063           2 :   CleanupCachedXBLHandlers(this);
    2064             : 
    2065           2 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    2066           0 :     mAudioContexts[i]->Shutdown();
    2067             :   }
    2068           2 :   mAudioContexts.Clear();
    2069             : 
    2070           2 :   if (mIdleTimer) {
    2071           0 :     mIdleTimer->Cancel();
    2072           0 :     mIdleTimer = nullptr;
    2073             :   }
    2074             : 
    2075           2 :   mServiceWorkerRegistrationTable.Clear();
    2076             : 
    2077             : #ifdef ENABLE_INTL_API
    2078           2 :   mIntlUtils = nullptr;
    2079             : #endif
    2080             : }
    2081             : 
    2082             : void
    2083           3 : nsGlobalWindow::ClearControllers()
    2084             : {
    2085           3 :   if (mControllers) {
    2086             :     uint32_t count;
    2087           0 :     mControllers->GetControllerCount(&count);
    2088             : 
    2089           0 :     while (count--) {
    2090           0 :       nsCOMPtr<nsIController> controller;
    2091           0 :       mControllers->GetControllerAt(count, getter_AddRefs(controller));
    2092             : 
    2093           0 :       nsCOMPtr<nsIControllerContext> context = do_QueryInterface(controller);
    2094           0 :       if (context)
    2095           0 :         context->SetCommandContext(nullptr);
    2096             :     }
    2097             : 
    2098           0 :     mControllers = nullptr;
    2099             :   }
    2100           3 : }
    2101             : 
    2102             : void
    2103           3 : nsGlobalWindow::FreeInnerObjects()
    2104             : {
    2105           3 :   NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
    2106             : 
    2107             :   // Make sure that this is called before we null out the document and
    2108             :   // other members that the window destroyed observers could
    2109             :   // re-create.
    2110           3 :   NotifyDOMWindowDestroyed(this);
    2111           3 :   if (auto* reporter = nsWindowMemoryReporter::Get()) {
    2112           3 :     reporter->ObserveDOMWindowDetached(this);
    2113             :   }
    2114             : 
    2115           3 :   mInnerObjectsFreed = true;
    2116             : 
    2117             :   // Kill all of the workers for this window.
    2118           3 :   mozilla::dom::workers::CancelWorkersForWindow(AsInner());
    2119             : 
    2120           3 :   if (mTimeoutManager) {
    2121           3 :     mTimeoutManager->ClearAllTimeouts();
    2122             :   }
    2123             : 
    2124           3 :   if (mIdleTimer) {
    2125           0 :     mIdleTimer->Cancel();
    2126           0 :     mIdleTimer = nullptr;
    2127             :   }
    2128             : 
    2129           3 :   mIdleObservers.Clear();
    2130             : 
    2131           3 :   DisableIdleCallbackRequests();
    2132             : 
    2133           3 :   mChromeEventHandler = nullptr;
    2134             : 
    2135           3 :   if (mListenerManager) {
    2136           0 :     mListenerManager->Disconnect();
    2137           0 :     mListenerManager = nullptr;
    2138             :   }
    2139             : 
    2140           3 :   mHistory = nullptr;
    2141           3 :   mCustomElements = nullptr;
    2142             : 
    2143           3 :   if (mNavigator) {
    2144           0 :     mNavigator->OnNavigation();
    2145           0 :     mNavigator->Invalidate();
    2146           0 :     mNavigator = nullptr;
    2147             :   }
    2148             : 
    2149           3 :   if (mScreen) {
    2150           0 :     mScreen = nullptr;
    2151             :   }
    2152             : 
    2153             : #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
    2154             :   mOrientationChangeObserver = nullptr;
    2155             : #endif
    2156             : 
    2157           3 :   if (mDoc) {
    2158             :     // Remember the document's principal and URI.
    2159           3 :     mDocumentPrincipal = mDoc->NodePrincipal();
    2160           3 :     mDocumentURI = mDoc->GetDocumentURI();
    2161           3 :     mDocBaseURI = mDoc->GetDocBaseURI();
    2162             : 
    2163           3 :     while (mDoc->EventHandlingSuppressed()) {
    2164           0 :       mDoc->UnsuppressEventHandlingAndFireEvents(false);
    2165             :     }
    2166             :   }
    2167             : 
    2168             :   // Remove our reference to the document and the document principal.
    2169           3 :   mFocusedNode = nullptr;
    2170             : 
    2171           3 :   if (mApplicationCache) {
    2172           0 :     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();
    2173           0 :     mApplicationCache = nullptr;
    2174             :   }
    2175             : 
    2176           3 :   mIndexedDB = nullptr;
    2177             : 
    2178           3 :   UnlinkHostObjectURIs();
    2179             : 
    2180           3 :   NotifyWindowIDDestroyed("inner-window-destroyed");
    2181             : 
    2182           3 :   CleanupCachedXBLHandlers(this);
    2183             : 
    2184           3 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    2185           0 :     mAudioContexts[i]->Shutdown();
    2186             :   }
    2187           3 :   mAudioContexts.Clear();
    2188             : 
    2189           3 :   DisableGamepadUpdates();
    2190           3 :   mHasGamepad = false;
    2191           3 :   mGamepads.Clear();
    2192           3 :   DisableVRUpdates();
    2193           3 :   mHasVREvents = false;
    2194           3 :   mHasVRDisplayActivateEvents = false;
    2195           3 :   mVRDisplays.Clear();
    2196             : 
    2197           3 :   if (mTabChild) {
    2198           1 :     while (mBeforeUnloadListenerCount-- > 0) {
    2199           0 :       mTabChild->BeforeUnloadRemoved();
    2200             :     }
    2201             :   }
    2202           3 : }
    2203             : 
    2204             : //*****************************************************************************
    2205             : // nsGlobalWindow::nsISupports
    2206             : //*****************************************************************************
    2207             : 
    2208             : // QueryInterface implementation for nsGlobalWindow
    2209       14404 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
    2210       14393 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    2211             :   // Make sure this matches the cast in nsGlobalWindow::FromWrapper()
    2212       14181 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventTarget)
    2213       13905 :   NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)
    2214       13901 :   if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) {
    2215           0 :     foundInterface = static_cast<nsIDOMWindowInternal*>(this);
    2216           0 :     if (!sWarnedAboutWindowInternal) {
    2217           0 :       sWarnedAboutWindowInternal = true;
    2218           0 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    2219           0 :                                       NS_LITERAL_CSTRING("Extensions"), mDoc,
    2220             :                                       nsContentUtils::eDOM_PROPERTIES,
    2221           0 :                                       "nsIDOMWindowInternalWarning");
    2222             :     }
    2223             :   } else
    2224       13901 :   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
    2225        5270 :   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
    2226        4086 :   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
    2227        4017 :   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
    2228        4017 :   NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
    2229        3522 :   if (aIID.Equals(NS_GET_IID(nsPIDOMWindowInner))) {
    2230         759 :     foundInterface = AsInner();
    2231             :   } else
    2232        2763 :   if (aIID.Equals(NS_GET_IID(mozIDOMWindow)) && IsInnerWindow()) {
    2233           2 :     foundInterface = AsInner();
    2234             :   } else
    2235        2761 :   if (aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter))) {
    2236        2236 :     foundInterface = AsOuter();
    2237             :   } else
    2238         525 :   if (aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)) && IsOuterWindow()) {
    2239         260 :     foundInterface = AsOuter();
    2240             :   } else
    2241         265 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    2242         228 :   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
    2243         176 : NS_INTERFACE_MAP_END
    2244             : 
    2245             : 
    2246       19922 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindow)
    2247       19623 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindow)
    2248             : 
    2249           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
    2250           0 :   if (tmp->IsBlackForCC(false)) {
    2251           0 :     if (nsCCUncollectableMarker::InGeneration(tmp->mCanSkipCCGeneration)) {
    2252           0 :       return true;
    2253             :     }
    2254           0 :     tmp->mCanSkipCCGeneration = nsCCUncollectableMarker::sGeneration;
    2255           0 :     if (tmp->mCachedXBLPrototypeHandlers) {
    2256           0 :       for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
    2257           0 :            !iter.Done();
    2258           0 :            iter.Next()) {
    2259           0 :         iter.Data().exposeToActiveJS();
    2260             :       }
    2261             :     }
    2262           0 :     if (EventListenerManager* elm = tmp->GetExistingListenerManager()) {
    2263           0 :       elm->MarkForCC();
    2264             :     }
    2265           0 :     if (tmp->mTimeoutManager) {
    2266           0 :       tmp->mTimeoutManager->UnmarkGrayTimers();
    2267             :     }
    2268           0 :     return true;
    2269             :   }
    2270           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
    2271             : 
    2272           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindow)
    2273           0 :   return tmp->IsBlackForCC(true);
    2274             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
    2275             : 
    2276           0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindow)
    2277           0 :   return tmp->IsBlackForCC(false);
    2278             : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
    2279             : 
    2280             : inline void
    2281           0 : ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
    2282             :                             IdleObserverHolder& aField,
    2283             :                             const char* aName,
    2284             :                             unsigned aFlags)
    2285             : {
    2286           0 :   CycleCollectionNoteChild(aCallback, aField.mIdleObserver.get(), aName, aFlags);
    2287           0 : }
    2288             : 
    2289             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow)
    2290             : 
    2291           1 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
    2292           1 :   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
    2293             :     char name[512];
    2294           0 :     nsAutoCString uri;
    2295           0 :     if (tmp->mDoc && tmp->mDoc->GetDocumentURI()) {
    2296           0 :       uri = tmp->mDoc->GetDocumentURI()->GetSpecOrDefault();
    2297             :     }
    2298           0 :     SprintfLiteral(name, "nsGlobalWindow # %" PRIu64 " %s %s", tmp->mWindowID,
    2299           0 :                    tmp->IsInnerWindow() ? "inner" : "outer", uri.get());
    2300           0 :     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
    2301             :   } else {
    2302           1 :     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGlobalWindow, tmp->mRefCnt.get())
    2303             :   }
    2304             : 
    2305           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext)
    2306             : 
    2307           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mControllers)
    2308           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mArguments)
    2309           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDialogArguments)
    2310           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReturnValue)
    2311           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNavigator)
    2312             : 
    2313           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPerformance)
    2314             : 
    2315           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerRegistrationTable)
    2316             : 
    2317             : #ifdef MOZ_WEBSPEECH
    2318           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSpeechSynthesis)
    2319             : #endif
    2320             : 
    2321           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOuterWindow)
    2322             : 
    2323           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTopInnerWindow)
    2324             : 
    2325           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
    2326             : 
    2327           1 :   if (tmp->mTimeoutManager) {
    2328          13 :     tmp->mTimeoutManager->ForEachUnorderedTimeout([&cb](Timeout* timeout) {
    2329          12 :       cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(Timeout));
    2330           8 :     });
    2331             :   }
    2332             : 
    2333           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
    2334           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)
    2335           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)
    2336             : 
    2337           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)
    2338           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)
    2339           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplicationCache)
    2340           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSuspendedDoc)
    2341           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIndexedDB)
    2342           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentPrincipal)
    2343           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTabChild)
    2344           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDoc)
    2345           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleService)
    2346           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWakeLock)
    2347             : 
    2348           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleRequestExecutor)
    2349           3 :   for (IdleRequest* request : tmp->mIdleRequestCallbacks) {
    2350           2 :     cb.NoteNativeChild(request, NS_CYCLE_COLLECTION_PARTICIPANT(IdleRequest));
    2351             :   }
    2352             : 
    2353           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIdleObservers)
    2354             : 
    2355           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepads)
    2356             : 
    2357           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheStorage)
    2358           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRDisplays)
    2359             : 
    2360             :   // Traverse stuff from nsPIDOMWindow
    2361           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeEventHandler)
    2362           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParentTarget)
    2363           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameElement)
    2364           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedNode)
    2365             : 
    2366           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMenubar)
    2367           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mToolbar)
    2368           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocationbar)
    2369           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPersonalbar)
    2370           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusbar)
    2371           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScrollbars)
    2372           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCrypto)
    2373           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mU2F)
    2374           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsole)
    2375           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioWorklet)
    2376           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPaintWorklet)
    2377           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)
    2378           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMozSelfSupport)
    2379             : #ifdef ENABLE_INTL_API
    2380           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)
    2381             : #endif
    2382             : 
    2383           1 :   tmp->TraverseHostObjectURIs(cb);
    2384           1 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    2385             : 
    2386           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
    2387           0 :   nsGlobalWindow::CleanupCachedXBLHandlers(tmp);
    2388             : 
    2389           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
    2390             : 
    2391           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mControllers)
    2392           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mArguments)
    2393           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDialogArguments)
    2394           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mReturnValue)
    2395           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNavigator)
    2396             : 
    2397           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPerformance)
    2398             : 
    2399           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mServiceWorkerRegistrationTable)
    2400             : 
    2401             : #ifdef MOZ_WEBSPEECH
    2402           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSpeechSynthesis)
    2403             : #endif
    2404             : 
    2405           0 :   if (tmp->mOuterWindow) {
    2406           0 :     nsGlobalWindow::Cast(tmp->mOuterWindow)->MaybeClearInnerWindow(tmp);
    2407           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mOuterWindow)
    2408             :   }
    2409             : 
    2410           0 :   if (tmp->mListenerManager) {
    2411           0 :     tmp->mListenerManager->Disconnect();
    2412           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mListenerManager)
    2413             :   }
    2414             : 
    2415           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTopInnerWindow)
    2416             : 
    2417           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
    2418           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)
    2419           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)
    2420           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
    2421           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
    2422           0 :   if (tmp->mApplicationCache) {
    2423           0 :     static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())->Disconnect();
    2424           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
    2425             :   }
    2426           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSuspendedDoc)
    2427           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIndexedDB)
    2428           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
    2429           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTabChild)
    2430           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
    2431           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)
    2432           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mWakeLock)
    2433           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleObservers)
    2434             : 
    2435           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGamepads)
    2436             : 
    2437           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheStorage)
    2438           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mVRDisplays)
    2439             : 
    2440             :   // Unlink stuff from nsPIDOMWindow
    2441           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeEventHandler)
    2442           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParentTarget)
    2443           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameElement)
    2444           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFocusedNode)
    2445             : 
    2446           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMenubar)
    2447           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mToolbar)
    2448           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocationbar)
    2449           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPersonalbar)
    2450           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusbar)
    2451           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mScrollbars)
    2452           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCrypto)
    2453           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mU2F)
    2454           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsole)
    2455           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioWorklet)
    2456           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPaintWorklet)
    2457           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)
    2458           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mMozSelfSupport)
    2459             : #ifdef ENABLE_INTL_API
    2460           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)
    2461             : #endif
    2462             : 
    2463           0 :   tmp->UnlinkHostObjectURIs();
    2464             : 
    2465           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
    2466           0 :   tmp->DisableIdleCallbackRequests();
    2467             : 
    2468           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
    2469           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    2470             : 
    2471             : #ifdef DEBUG
    2472             : void
    2473           0 : nsGlobalWindow::RiskyUnlink()
    2474             : {
    2475           0 :   NS_CYCLE_COLLECTION_INNERNAME.Unlink(this);
    2476           0 : }
    2477             : #endif
    2478             : 
    2479           3 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow)
    2480           3 :   if (tmp->mCachedXBLPrototypeHandlers) {
    2481          10 :     for (auto iter = tmp->mCachedXBLPrototypeHandlers->Iter();
    2482           5 :          !iter.Done();
    2483           2 :          iter.Next()) {
    2484           2 :       aCallbacks.Trace(&iter.Data(), "Cached XBL prototype handler", aClosure);
    2485             :     }
    2486             :   }
    2487           3 :   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
    2488           3 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    2489             : 
    2490             : bool
    2491           0 : nsGlobalWindow::IsBlackForCC(bool aTracingNeeded)
    2492             : {
    2493           0 :   if (!nsCCUncollectableMarker::sGeneration) {
    2494           0 :     return false;
    2495             :   }
    2496             : 
    2497           0 :   return (nsCCUncollectableMarker::InGeneration(GetMarkedCCGeneration()) ||
    2498           0 :           HasKnownLiveWrapper()) &&
    2499           0 :          (!aTracingNeeded ||
    2500           0 :           HasNothingToTrace(static_cast<nsIDOMEventTarget*>(this)));
    2501             : }
    2502             : 
    2503             : //*****************************************************************************
    2504             : // nsGlobalWindow::nsIScriptGlobalObject
    2505             : //*****************************************************************************
    2506             : 
    2507             : nsresult
    2508         606 : nsGlobalWindow::EnsureScriptEnvironment()
    2509             : {
    2510         606 :   nsGlobalWindow* outer = GetOuterWindowInternal();
    2511         606 :   if (!outer) {
    2512           0 :     NS_WARNING("No outer window available!");
    2513           0 :     return NS_ERROR_FAILURE;
    2514             :   }
    2515             : 
    2516         606 :   if (outer->GetWrapperPreserveColor()) {
    2517         601 :     return NS_OK;
    2518             :   }
    2519             : 
    2520           5 :   NS_ASSERTION(!outer->GetCurrentInnerWindowInternal(),
    2521             :                "No cached wrapper, but we have an inner window?");
    2522             : 
    2523             :   // If this window is a [i]frame, don't bother GC'ing when the frame's context
    2524             :   // is destroyed since a GC will happen when the frameset or host document is
    2525             :   // destroyed anyway.
    2526          15 :   nsCOMPtr<nsIScriptContext> context = new nsJSContext(!IsFrame(), outer);
    2527             : 
    2528           5 :   NS_ASSERTION(!outer->mContext, "Will overwrite mContext!");
    2529             : 
    2530             :   // should probably assert the context is clean???
    2531           5 :   context->WillInitializeContext();
    2532             : 
    2533           5 :   nsresult rv = context->InitContext();
    2534           5 :   NS_ENSURE_SUCCESS(rv, rv);
    2535             : 
    2536           5 :   outer->mContext = context;
    2537           5 :   return NS_OK;
    2538             : }
    2539             : 
    2540             : nsIScriptContext *
    2541         559 : nsGlobalWindow::GetScriptContext()
    2542             : {
    2543         559 :   nsGlobalWindow* outer = GetOuterWindowInternal();
    2544         559 :   if (!outer) {
    2545           0 :     return nullptr;
    2546             :   }
    2547         559 :   return outer->mContext;
    2548             : }
    2549             : 
    2550             : JSObject *
    2551        9585 : nsGlobalWindow::GetGlobalJSObject()
    2552             : {
    2553        9585 :   return FastGetGlobalJSObject();
    2554             : }
    2555             : 
    2556             : void
    2557           3 : nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc)
    2558             : {
    2559           3 :   TraceWrapper(aTrc, "active window global");
    2560           3 : }
    2561             : 
    2562             : bool
    2563           8 : nsGlobalWindow::WouldReuseInnerWindow(nsIDocument* aNewDocument)
    2564             : {
    2565           8 :   MOZ_ASSERT(IsOuterWindow());
    2566             : 
    2567             :   // We reuse the inner window when:
    2568             :   // a. We are currently at our original document.
    2569             :   // b. At least one of the following conditions are true:
    2570             :   // -- The new document is the same as the old document. This means that we're
    2571             :   //    getting called from document.open().
    2572             :   // -- The new document has the same origin as what we have loaded right now.
    2573             : 
    2574           8 :   if (!mDoc || !aNewDocument) {
    2575           5 :     return false;
    2576             :   }
    2577             : 
    2578           3 :   if (!mDoc->IsInitialDocument()) {
    2579           0 :     return false;
    2580             :   }
    2581             : 
    2582             : #ifdef DEBUG
    2583             : {
    2584           6 :   nsCOMPtr<nsIURI> uri;
    2585           3 :   mDoc->GetDocumentURI()->CloneIgnoringRef(getter_AddRefs(uri));
    2586           3 :   NS_ASSERTION(NS_IsAboutBlank(uri), "How'd this happen?");
    2587             : }
    2588             : #endif
    2589             : 
    2590             :   // Great, we're the original document, check for one of the other
    2591             :   // conditions.
    2592             : 
    2593           3 :   if (mDoc == aNewDocument) {
    2594           0 :     return true;
    2595             :   }
    2596             : 
    2597             :   bool equal;
    2598           6 :   if (NS_SUCCEEDED(mDoc->NodePrincipal()->Equals(aNewDocument->NodePrincipal(),
    2599           3 :                                                  &equal)) &&
    2600             :       equal) {
    2601             :     // The origin is the same.
    2602           1 :     return true;
    2603             :   }
    2604             : 
    2605           2 :   return false;
    2606             : }
    2607             : 
    2608             : void
    2609           2 : nsGlobalWindow::SetInitialPrincipalToSubject()
    2610             : {
    2611           2 :   MOZ_ASSERT(IsOuterWindow());
    2612             : 
    2613             :   // First, grab the subject principal.
    2614           2 :   nsCOMPtr<nsIPrincipal> newWindowPrincipal = nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller();
    2615             : 
    2616             :   // We should never create windows with an expanded principal.
    2617             :   // If we have a system principal, make sure we're not using it for a content
    2618             :   // docshell.
    2619             :   // NOTE: Please keep this logic in sync with nsWebShellWindow::Initialize().
    2620           4 :   if (nsContentUtils::IsExpandedPrincipal(newWindowPrincipal) ||
    2621           4 :       (nsContentUtils::IsSystemPrincipal(newWindowPrincipal) &&
    2622           2 :        GetDocShell()->ItemType() != nsIDocShellTreeItem::typeChrome)) {
    2623           0 :     newWindowPrincipal = nullptr;
    2624             :   }
    2625             : 
    2626             :   // If there's an existing document, bail if it either:
    2627           2 :   if (mDoc) {
    2628             :     // (a) is not an initial about:blank document, or
    2629           2 :     if (!mDoc->IsInitialDocument())
    2630           2 :       return;
    2631             :     // (b) already has the correct principal.
    2632           2 :     if (mDoc->NodePrincipal() == newWindowPrincipal)
    2633           2 :       return;
    2634             : 
    2635             : #ifdef DEBUG
    2636             :     // If we have a document loaded at this point, it had better be about:blank.
    2637             :     // Otherwise, something is really weird. An about:blank page has a
    2638             :     // NullPrincipal.
    2639             :     bool isNullPrincipal;
    2640           0 :     MOZ_ASSERT(NS_SUCCEEDED(mDoc->NodePrincipal()->GetIsNullPrincipal(&isNullPrincipal)) &&
    2641             :                isNullPrincipal);
    2642             : #endif
    2643             :   }
    2644             : 
    2645           0 :   GetDocShell()->CreateAboutBlankContentViewer(newWindowPrincipal);
    2646           0 :   mDoc->SetIsInitialDocument(true);
    2647             : 
    2648           0 :   nsCOMPtr<nsIPresShell> shell = GetDocShell()->GetPresShell();
    2649             : 
    2650           0 :   if (shell && !shell->DidInitialize()) {
    2651             :     // Ensure that if someone plays with this document they will get
    2652             :     // layout happening.
    2653           0 :     nsRect r = shell->GetPresContext()->GetVisibleArea();
    2654           0 :     shell->Initialize(r.width, r.height);
    2655             :   }
    2656             : }
    2657             : 
    2658             : PopupControlState
    2659         830 : PushPopupControlState(PopupControlState aState, bool aForce)
    2660             : {
    2661         830 :   MOZ_ASSERT(NS_IsMainThread());
    2662             : 
    2663         830 :   PopupControlState oldState = gPopupControlState;
    2664             : 
    2665         830 :   if (aState < gPopupControlState || aForce) {
    2666           9 :     gPopupControlState = aState;
    2667             :   }
    2668             : 
    2669         830 :   return oldState;
    2670             : }
    2671             : 
    2672             : void
    2673         830 : PopPopupControlState(PopupControlState aState)
    2674             : {
    2675         830 :   MOZ_ASSERT(NS_IsMainThread());
    2676             : 
    2677         830 :   gPopupControlState = aState;
    2678         830 : }
    2679             : 
    2680             : PopupControlState
    2681           0 : nsGlobalWindow::PushPopupControlState(PopupControlState aState,
    2682             :                                       bool aForce) const
    2683             : {
    2684           0 :   return ::PushPopupControlState(aState, aForce);
    2685             : }
    2686             : 
    2687             : void
    2688           0 : nsGlobalWindow::PopPopupControlState(PopupControlState aState) const
    2689             : {
    2690           0 :   ::PopPopupControlState(aState);
    2691           0 : }
    2692             : 
    2693             : PopupControlState
    2694          13 : nsGlobalWindow::GetPopupControlState() const
    2695             : {
    2696          13 :   MOZ_ASSERT(NS_IsMainThread());
    2697          13 :   return gPopupControlState;
    2698             : }
    2699             : 
    2700             : #define WINDOWSTATEHOLDER_IID \
    2701             : {0x0b917c3e, 0xbd50, 0x4683, {0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33, 0x26}}
    2702             : 
    2703             : class WindowStateHolder final : public nsISupports
    2704             : {
    2705             : public:
    2706             :   NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID)
    2707             :   NS_DECL_ISUPPORTS
    2708             : 
    2709             :   explicit WindowStateHolder(nsGlobalWindow *aWindow);
    2710             : 
    2711           0 :   nsGlobalWindow* GetInnerWindow() { return mInnerWindow; }
    2712             : 
    2713           0 :   void DidRestoreWindow()
    2714             :   {
    2715           0 :     mInnerWindow = nullptr;
    2716           0 :     mInnerWindowReflector = nullptr;
    2717           0 :   }
    2718             : 
    2719             : protected:
    2720             :   ~WindowStateHolder();
    2721             : 
    2722             :   nsGlobalWindow *mInnerWindow;
    2723             :   // We hold onto this to make sure the inner window doesn't go away. The outer
    2724             :   // window ends up recalculating it anyway.
    2725             :   JS::PersistentRooted<JSObject*> mInnerWindowReflector;
    2726             : };
    2727             : 
    2728             : NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder, WINDOWSTATEHOLDER_IID)
    2729             : 
    2730           0 : WindowStateHolder::WindowStateHolder(nsGlobalWindow* aWindow)
    2731             :   : mInnerWindow(aWindow),
    2732           0 :     mInnerWindowReflector(RootingCx(), aWindow->GetWrapper())
    2733             : {
    2734           0 :   NS_PRECONDITION(aWindow, "null window");
    2735           0 :   NS_PRECONDITION(aWindow->IsInnerWindow(), "Saving an outer window");
    2736             : 
    2737           0 :   aWindow->Suspend();
    2738             : 
    2739             :   // When a global goes into the bfcache, we disable script.
    2740           0 :   xpc::Scriptability::Get(mInnerWindowReflector).SetDocShellAllowsScript(false);
    2741           0 : }
    2742             : 
    2743           0 : WindowStateHolder::~WindowStateHolder()
    2744             : {
    2745           0 :   if (mInnerWindow) {
    2746             :     // This window was left in the bfcache and is now going away. We need to
    2747             :     // free it up.
    2748             :     // Note that FreeInnerObjects may already have been called on the
    2749             :     // inner window if its outer has already had SetDocShell(null)
    2750             :     // called.
    2751           0 :     mInnerWindow->FreeInnerObjects();
    2752             :   }
    2753           0 : }
    2754             : 
    2755           0 : NS_IMPL_ISUPPORTS(WindowStateHolder, WindowStateHolder)
    2756             : 
    2757             : // We need certain special behavior for remote XUL whitelisted domains, but we
    2758             : // don't want that behavior to take effect in automation, because we whitelist
    2759             : // all the mochitest domains. So we need to check a pref here.
    2760             : static bool
    2761           4 : TreatAsRemoteXUL(nsIPrincipal* aPrincipal)
    2762             : {
    2763           4 :   MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(aPrincipal));
    2764           4 :   return nsContentUtils::AllowXULXBLForPrincipal(aPrincipal) &&
    2765           4 :          !Preferences::GetBool("dom.use_xbl_scopes_for_remote_xul", false);
    2766             : }
    2767             : 
    2768             : static bool
    2769           3 : EnablePrivilege(JSContext* cx, unsigned argc, JS::Value* vp)
    2770             : {
    2771           3 :   Telemetry::Accumulate(Telemetry::ENABLE_PRIVILEGE_EVER_CALLED, true);
    2772           3 :   return xpc::EnableUniversalXPConnect(cx);
    2773             : }
    2774             : 
    2775             : static const JSFunctionSpec EnablePrivilegeSpec[] = {
    2776             :   JS_FS("enablePrivilege", EnablePrivilege, 1, 0),
    2777             :   JS_FS_END
    2778             : };
    2779             : 
    2780             : static bool
    2781           7 : InitializeLegacyNetscapeObject(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
    2782             : {
    2783          14 :   JSAutoCompartment ac(aCx, aGlobal);
    2784             : 
    2785             :   // Note: MathJax depends on window.netscape being exposed. See bug 791526.
    2786          14 :   JS::Rooted<JSObject*> obj(aCx);
    2787           7 :   obj = JS_DefineObject(aCx, aGlobal, "netscape", nullptr);
    2788           7 :   NS_ENSURE_TRUE(obj, false);
    2789             : 
    2790           7 :   obj = JS_DefineObject(aCx, obj, "security", nullptr);
    2791           7 :   NS_ENSURE_TRUE(obj, false);
    2792             : 
    2793             :   // We hide enablePrivilege behind a pref because it has been altered in a
    2794             :   // way that makes it fundamentally insecure to use in production. Mozilla
    2795             :   // uses this pref during automated testing to support legacy test code that
    2796             :   // uses enablePrivilege. If you're not doing test automation, you _must_ not
    2797             :   // flip this pref, or you will be exposing all your users to security
    2798             :   // vulnerabilities.
    2799           7 :   if (!xpc::IsInAutomation()) {
    2800           0 :     return true;
    2801             :   }
    2802             : 
    2803             :   /* Define PrivilegeManager object with the necessary "static" methods. */
    2804           7 :   obj = JS_DefineObject(aCx, obj, "PrivilegeManager", nullptr);
    2805           7 :   NS_ENSURE_TRUE(obj, false);
    2806             : 
    2807           7 :   return JS_DefineFunctions(aCx, obj, EnablePrivilegeSpec);
    2808             : }
    2809             : 
    2810             : bool
    2811          14 : nsGlobalWindow::ComputeIsSecureContext(nsIDocument* aDocument, SecureContextFlags aFlags)
    2812             : {
    2813          14 :   MOZ_ASSERT(IsOuterWindow());
    2814             : 
    2815          28 :   nsCOMPtr<nsIPrincipal> principal = aDocument->NodePrincipal();
    2816          14 :   if (nsContentUtils::IsSystemPrincipal(principal)) {
    2817           6 :     return true;
    2818             :   }
    2819             : 
    2820             :   // Implement https://w3c.github.io/webappsec-secure-contexts/#settings-object
    2821             :   // With some modifications to allow for aFlags.
    2822             : 
    2823           8 :   bool hadNonSecureContextCreator = false;
    2824             : 
    2825           8 :   nsPIDOMWindowOuter* parentOuterWin = GetScriptableParent();
    2826           8 :   MOZ_ASSERT(parentOuterWin, "How can we get here? No docShell somehow?");
    2827           8 :   if (nsGlobalWindow::Cast(parentOuterWin) != this) {
    2828             :     // There may be a small chance that parentOuterWin has navigated in
    2829             :     // the time that it took us to start loading this sub-document.  If that
    2830             :     // were the case then parentOuterWin->GetCurrentInnerWindow() wouldn't
    2831             :     // return the window for the document that is embedding us.  For this
    2832             :     // reason we only use the GetScriptableParent call above to check that we
    2833             :     // have a same-type parent, but actually get the inner window via the
    2834             :     // document that we know is embedding us.
    2835           0 :     nsIDocument* creatorDoc = aDocument->GetParentDocument();
    2836           0 :     if (!creatorDoc) {
    2837           0 :       return false; // we must be tearing down
    2838             :     }
    2839             :     nsGlobalWindow* parentWin =
    2840           0 :       nsGlobalWindow::Cast(creatorDoc->GetInnerWindow());
    2841           0 :     if (!parentWin) {
    2842           0 :       return false; // we must be tearing down
    2843             :     }
    2844           0 :     MOZ_ASSERT(parentWin ==
    2845             :                nsGlobalWindow::Cast(parentOuterWin->GetCurrentInnerWindow()),
    2846             :                "Creator window mismatch while setting Secure Context state");
    2847           0 :     if (aFlags != SecureContextFlags::eIgnoreOpener) {
    2848           0 :       hadNonSecureContextCreator = !parentWin->IsSecureContext();
    2849             :     } else {
    2850           0 :       hadNonSecureContextCreator = !parentWin->IsSecureContextIfOpenerIgnored();
    2851             :     }
    2852           8 :   } else if (mHadOriginalOpener) {
    2853           0 :     if (aFlags != SecureContextFlags::eIgnoreOpener) {
    2854           0 :       hadNonSecureContextCreator = !mOriginalOpenerWasSecureContext;
    2855             :     }
    2856             :   }
    2857             : 
    2858           8 :   if (hadNonSecureContextCreator) {
    2859           0 :     return false;
    2860             :   }
    2861             : 
    2862           8 :   if (nsContentUtils::HttpsStateIsModern(aDocument)) {
    2863           4 :     return true;
    2864             :   }
    2865             : 
    2866           4 :   if (principal->GetIsNullPrincipal()) {
    2867           8 :     nsCOMPtr<nsIURI> uri = aDocument->GetOriginalURI();
    2868             :     // IsOriginPotentiallyTrustworthy doesn't care about origin attributes so
    2869             :     // it doesn't actually matter what we use here, but reusing the document
    2870             :     // principal's attributes is convenient.
    2871           4 :     const OriginAttributes& attrs = principal->OriginAttributesRef();
    2872             :     // CreateCodebasePrincipal correctly gets a useful principal for blob: and
    2873             :     // other URI_INHERITS_SECURITY_CONTEXT URIs.
    2874           4 :     principal = BasePrincipal::CreateCodebasePrincipal(uri, attrs);
    2875           4 :     if (NS_WARN_IF(!principal)) {
    2876           0 :       return false;
    2877             :     }
    2878             :   }
    2879             : 
    2880             :   nsCOMPtr<nsIContentSecurityManager> csm =
    2881           8 :     do_GetService(NS_CONTENTSECURITYMANAGER_CONTRACTID);
    2882           4 :   NS_WARNING_ASSERTION(csm, "csm is null");
    2883           4 :   if (csm) {
    2884           4 :     bool isTrustworthyOrigin = false;
    2885           4 :     csm->IsOriginPotentiallyTrustworthy(principal, &isTrustworthyOrigin);
    2886           4 :     if (isTrustworthyOrigin) {
    2887           0 :       return true;
    2888             :     }
    2889             :   }
    2890             : 
    2891           4 :   return false;
    2892             : }
    2893             : 
    2894             : static JS::CompartmentCreationOptions&
    2895           7 : SelectZoneGroup(nsGlobalWindow* aNewInner,
    2896             :                 JS::CompartmentCreationOptions& aOptions)
    2897             : {
    2898           7 :   JS::CompartmentCreationOptions options;
    2899             : 
    2900           7 :   if (aNewInner->GetOuterWindow()) {
    2901           7 :     nsGlobalWindow *top = aNewInner->GetTopInternal();
    2902             : 
    2903             :     // If we have a top-level window, use its zone (and zone group).
    2904           7 :     if (top && top->GetGlobalJSObject()) {
    2905           3 :       return aOptions.setExistingZone(top->GetGlobalJSObject());
    2906             :     }
    2907             :   }
    2908             : 
    2909             :   // If we're in the parent process, don't bother with zone groups.
    2910           4 :   if (XRE_IsParentProcess()) {
    2911           3 :     return aOptions.setNewZoneInSystemZoneGroup();
    2912             :   }
    2913             : 
    2914             :   // Otherwise, find a zone group from the TabGroup. Typically we only have to
    2915             :   // go through one iteration of this loop.
    2916           2 :   RefPtr<TabGroup> tabGroup = aNewInner->TabGroup();
    2917           2 :   for (nsPIDOMWindowOuter* outer : tabGroup->GetWindows()) {
    2918           1 :     nsGlobalWindow* window = nsGlobalWindow::Cast(outer);
    2919           1 :     if (JSObject* global = window->GetGlobalJSObject()) {
    2920           0 :       return aOptions.setNewZoneInExistingZoneGroup(global);
    2921             :     }
    2922             :   }
    2923             : 
    2924           1 :   return aOptions.setNewZoneInNewZoneGroup();
    2925             : }
    2926             : 
    2927             : /**
    2928             :  * Create a new global object that will be used for an inner window.
    2929             :  * Return the native global and an nsISupports 'holder' that can be used
    2930             :  * to manage the lifetime of it.
    2931             :  */
    2932             : static nsresult
    2933           7 : CreateNativeGlobalForInner(JSContext* aCx,
    2934             :                            nsGlobalWindow* aNewInner,
    2935             :                            nsIURI* aURI,
    2936             :                            nsIPrincipal* aPrincipal,
    2937             :                            JS::MutableHandle<JSObject*> aGlobal,
    2938             :                            bool aIsSecureContext)
    2939             : {
    2940           7 :   MOZ_ASSERT(aCx);
    2941           7 :   MOZ_ASSERT(aNewInner);
    2942           7 :   MOZ_ASSERT(aNewInner->IsInnerWindow());
    2943           7 :   MOZ_ASSERT(aPrincipal);
    2944             : 
    2945             :   // DOMWindow with nsEP is not supported, we have to make sure
    2946             :   // no one creates one accidentally.
    2947          14 :   nsCOMPtr<nsIExpandedPrincipal> nsEP = do_QueryInterface(aPrincipal);
    2948           7 :   MOZ_RELEASE_ASSERT(!nsEP, "DOMWindow with nsEP is not supported");
    2949             : 
    2950           7 :   JS::CompartmentOptions options;
    2951             : 
    2952           7 :   SelectZoneGroup(aNewInner, options.creationOptions());
    2953             : 
    2954             :   // Sometimes add-ons load their own XUL windows, either as separate top-level
    2955             :   // windows or inside a browser element. In such cases we want to tag the
    2956             :   // window's compartment with the add-on ID. See bug 1092156.
    2957           7 :   if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
    2958           3 :     options.creationOptions().setAddonId(MapURIToAddonID(aURI));
    2959             :   }
    2960             : 
    2961           7 :   options.creationOptions().setSecureContext(aIsSecureContext);
    2962             : 
    2963           7 :   xpc::InitGlobalObjectOptions(options, aPrincipal);
    2964             : 
    2965             :   // Determine if we need the Components object.
    2966          11 :   bool needComponents = nsContentUtils::IsSystemPrincipal(aPrincipal) ||
    2967          11 :                         TreatAsRemoteXUL(aPrincipal);
    2968           7 :   uint32_t flags = needComponents ? 0 : nsIXPConnect::OMIT_COMPONENTS_OBJECT;
    2969           7 :   flags |= nsIXPConnect::DONT_FIRE_ONNEWGLOBALHOOK;
    2970             : 
    2971          21 :   if (!WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
    2972          28 :                            nsJSPrincipals::get(aPrincipal), false, aGlobal) ||
    2973          28 :       !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
    2974           0 :     return NS_ERROR_FAILURE;
    2975             :   }
    2976             : 
    2977           7 :   MOZ_ASSERT(aNewInner->GetWrapperPreserveColor() == aGlobal);
    2978             : 
    2979             :   // Set the location information for the new global, so that tools like
    2980             :   // about:memory may use that information
    2981           7 :   xpc::SetLocationForGlobal(aGlobal, aURI);
    2982             : 
    2983           7 :   if (!InitializeLegacyNetscapeObject(aCx, aGlobal)) {
    2984           0 :     return NS_ERROR_FAILURE;
    2985             :   }
    2986             : 
    2987           7 :   return NS_OK;
    2988             : }
    2989             : 
    2990             : nsresult
    2991           8 : nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
    2992             :                                nsISupports* aState,
    2993             :                                bool aForceReuseInnerWindow)
    2994             : {
    2995           8 :   NS_PRECONDITION(mDocumentPrincipal == nullptr,
    2996             :                   "mDocumentPrincipal prematurely set!");
    2997           8 :   MOZ_ASSERT(aDocument);
    2998             : 
    2999           8 :   if (IsInnerWindow()) {
    3000           0 :     if (!mOuterWindow) {
    3001           0 :       return NS_ERROR_NOT_INITIALIZED;
    3002             :     }
    3003             : 
    3004             :     // Refuse to set a new document if the call came from an inner
    3005             :     // window that's not the current inner window.
    3006           0 :     if (mOuterWindow->GetCurrentInnerWindow() != AsInner()) {
    3007           0 :       return NS_ERROR_NOT_AVAILABLE;
    3008             :     }
    3009             : 
    3010           0 :     return GetOuterWindowInternal()->SetNewDocument(aDocument, aState,
    3011           0 :                                                     aForceReuseInnerWindow);
    3012             :   }
    3013             : 
    3014           8 :   NS_PRECONDITION(IsOuterWindow(), "Must only be called on outer windows");
    3015             : 
    3016             :   // Bail out early if we're in process of closing down the window.
    3017           8 :   NS_ENSURE_STATE(!mCleanedUp);
    3018             : 
    3019           8 :   NS_ASSERTION(!AsOuter()->GetCurrentInnerWindow() ||
    3020             :                AsOuter()->GetCurrentInnerWindow()->GetExtantDoc() == mDoc,
    3021             :                "Uh, mDoc doesn't match the current inner window "
    3022             :                "document!");
    3023             : 
    3024           8 :   bool wouldReuseInnerWindow = WouldReuseInnerWindow(aDocument);
    3025           8 :   if (aForceReuseInnerWindow &&
    3026           0 :       !wouldReuseInnerWindow &&
    3027           8 :       mDoc &&
    3028           0 :       mDoc->NodePrincipal() != aDocument->NodePrincipal()) {
    3029           0 :     NS_ERROR("Attempted forced inner window reuse while changing principal");
    3030           0 :     return NS_ERROR_UNEXPECTED;
    3031             :   }
    3032             : 
    3033          16 :   nsCOMPtr<nsIDocument> oldDoc = mDoc;
    3034             : 
    3035          16 :   AutoJSAPI jsapi;
    3036           8 :   jsapi.Init();
    3037           8 :   JSContext *cx = jsapi.cx();
    3038             : 
    3039             :   // Check if we're anywhere near the stack limit before we reach the
    3040             :   // transplanting code, since it has no good way to handle errors. This uses
    3041             :   // the untrusted script limit, which is not strictly necessary since no
    3042             :   // actual script should run.
    3043           8 :   if (!js::CheckRecursionLimitConservativeDontReport(cx)) {
    3044           0 :     NS_WARNING("Overrecursion in SetNewDocument");
    3045           0 :     return NS_ERROR_FAILURE;
    3046             :   }
    3047             : 
    3048           8 :   if (!mDoc) {
    3049             :     // First document load.
    3050             : 
    3051             :     // Get our private root. If it is equal to us, then we need to
    3052             :     // attach our global key bindings that handles browser scrolling
    3053             :     // and other browser commands.
    3054           5 :     nsPIDOMWindowOuter* privateRoot = nsGlobalWindow::GetPrivateRoot();
    3055             : 
    3056           5 :     if (privateRoot == AsOuter()) {
    3057           3 :       nsXBLService::AttachGlobalKeyHandler(mChromeEventHandler);
    3058             :     }
    3059             :   }
    3060             : 
    3061             :   /* No mDocShell means we're already been partially closed down.  When that
    3062             :      happens, setting status isn't a big requirement, so don't. (Doesn't happen
    3063             :      under normal circumstances, but bug 49615 describes a case.) */
    3064             : 
    3065          16 :   nsContentUtils::AddScriptRunner(NewRunnableMethod(
    3066           8 :     "nsGlobalWindow::ClearStatus", this, &nsGlobalWindow::ClearStatus));
    3067             : 
    3068             :   // Sometimes, WouldReuseInnerWindow() returns true even if there's no inner
    3069             :   // window (see bug 776497). Be safe.
    3070           9 :   bool reUseInnerWindow = (aForceReuseInnerWindow || wouldReuseInnerWindow) &&
    3071           9 :                           GetCurrentInnerWindowInternal();
    3072             : 
    3073           8 :   nsresult rv = NS_OK;
    3074             : 
    3075             :   // We set mDoc even though this is an outer window to avoid
    3076             :   // having to *always* reach into the inner window to find the
    3077             :   // document.
    3078           8 :   mDoc = aDocument;
    3079             : 
    3080             :   // Take this opportunity to clear mSuspendedDoc. Our old inner window is now
    3081             :   // responsible for unsuspending it.
    3082           8 :   mSuspendedDoc = nullptr;
    3083             : 
    3084             : #ifdef DEBUG
    3085           8 :   mLastOpenedURI = aDocument->GetDocumentURI();
    3086             : #endif
    3087             : 
    3088           8 :   mContext->WillInitializeContext();
    3089             : 
    3090           8 :   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
    3091             : 
    3092           8 :   if (currentInner && currentInner->mNavigator) {
    3093           0 :     currentInner->mNavigator->OnNavigation();
    3094             :   }
    3095             : 
    3096          16 :   RefPtr<nsGlobalWindow> newInnerWindow;
    3097           8 :   bool createdInnerWindow = false;
    3098             : 
    3099           8 :   bool thisChrome = IsChromeWindow();
    3100             : 
    3101          16 :   nsCOMPtr<WindowStateHolder> wsh = do_QueryInterface(aState);
    3102           8 :   NS_ASSERTION(!aState || wsh, "What kind of weird state are you giving me here?");
    3103             : 
    3104          16 :   JS::Rooted<JSObject*> newInnerGlobal(cx);
    3105           8 :   if (reUseInnerWindow) {
    3106             :     // We're reusing the current inner window.
    3107           1 :     NS_ASSERTION(!currentInner->IsFrozen(),
    3108             :                  "We should never be reusing a shared inner window");
    3109           1 :     newInnerWindow = currentInner;
    3110           1 :     newInnerGlobal = currentInner->GetWrapperPreserveColor();
    3111             : 
    3112           1 :     if (aDocument != oldDoc) {
    3113           1 :       JS::ExposeObjectToActiveJS(newInnerGlobal);
    3114             :     }
    3115             : 
    3116             :     // We're reusing the inner window, but this still counts as a navigation,
    3117             :     // so all expandos and such defined on the outer window should go away. Force
    3118             :     // all Xray wrappers to be recomputed.
    3119           2 :     JS::Rooted<JSObject*> rootedObject(cx, GetWrapper());
    3120           1 :     if (!JS_RefreshCrossCompartmentWrappers(cx, rootedObject)) {
    3121           0 :       return NS_ERROR_FAILURE;
    3122             :     }
    3123             : 
    3124             :     // Inner windows are only reused for same-origin principals, but the principals
    3125             :     // don't necessarily match exactly. Update the principal on the compartment to
    3126             :     // match the new document.
    3127             :     // NB: We don't just call currentInner->RefreshCompartmentPrincipals() here
    3128             :     // because we haven't yet set its mDoc to aDocument.
    3129           1 :     JSCompartment *compartment = js::GetObjectCompartment(newInnerGlobal);
    3130             : #ifdef DEBUG
    3131           1 :     bool sameOrigin = false;
    3132             :     nsIPrincipal *existing =
    3133           1 :       nsJSPrincipals::get(JS_GetCompartmentPrincipals(compartment));
    3134           1 :     aDocument->NodePrincipal()->Equals(existing, &sameOrigin);
    3135           1 :     MOZ_ASSERT(sameOrigin);
    3136             : #endif
    3137           1 :     MOZ_ASSERT_IF(aDocument == oldDoc,
    3138             :                   xpc::GetCompartmentPrincipal(compartment) ==
    3139             :                   aDocument->NodePrincipal());
    3140           1 :     if (aDocument != oldDoc) {
    3141           1 :       JS_SetCompartmentPrincipals(compartment,
    3142           2 :                                   nsJSPrincipals::get(aDocument->NodePrincipal()));
    3143             :       // Make sure we clear out the old content XBL scope, so the new one will
    3144             :       // get created with a principal that subsumes our new principal.
    3145           1 :       xpc::ClearContentXBLScope(newInnerGlobal);
    3146             :     }
    3147             :   } else {
    3148           7 :     if (aState) {
    3149           0 :       newInnerWindow = wsh->GetInnerWindow();
    3150           0 :       newInnerGlobal = newInnerWindow->GetWrapperPreserveColor();
    3151             :     } else {
    3152           7 :       if (thisChrome) {
    3153           4 :         newInnerWindow = nsGlobalChromeWindow::Create(this);
    3154           3 :       } else if (mIsModalContentWindow) {
    3155           0 :         newInnerWindow = nsGlobalModalWindow::Create(this);
    3156             :       } else {
    3157           3 :         newInnerWindow = nsGlobalWindow::Create(this);
    3158             :       }
    3159             : 
    3160             :       // The outer window is automatically treated as frozen when we
    3161             :       // null out the inner window. As a result, initializing classes
    3162             :       // on the new inner won't end up reaching into the old inner
    3163             :       // window for classes etc.
    3164             :       //
    3165             :       // [This happens with Object.prototype when XPConnect creates
    3166             :       // a temporary global while initializing classes; the reason
    3167             :       // being that xpconnect creates the temp global w/o a parent
    3168             :       // and proto, which makes the JS engine look up classes in
    3169             :       // cx->globalObject, i.e. this outer window].
    3170             : 
    3171           7 :       mInnerWindow = nullptr;
    3172             : 
    3173           7 :       mCreatingInnerWindow = true;
    3174             :       // Every script context we are initialized with must create a
    3175             :       // new global.
    3176          14 :       rv = CreateNativeGlobalForInner(cx, newInnerWindow,
    3177             :                                       aDocument->GetDocumentURI(),
    3178             :                                       aDocument->NodePrincipal(),
    3179             :                                       &newInnerGlobal,
    3180          14 :                                       ComputeIsSecureContext(aDocument));
    3181           7 :       NS_ASSERTION(NS_SUCCEEDED(rv) && newInnerGlobal &&
    3182             :                    newInnerWindow->GetWrapperPreserveColor() == newInnerGlobal,
    3183             :                    "Failed to get script global");
    3184          14 :       newInnerWindow->mIsSecureContextIfOpenerIgnored =
    3185           7 :         ComputeIsSecureContext(aDocument, SecureContextFlags::eIgnoreOpener);
    3186             : 
    3187           7 :       mCreatingInnerWindow = false;
    3188           7 :       createdInnerWindow = true;
    3189             : 
    3190           7 :       NS_ENSURE_SUCCESS(rv, rv);
    3191             :     }
    3192             : 
    3193           7 :     if (currentInner && currentInner->GetWrapperPreserveColor()) {
    3194           2 :       if (oldDoc == aDocument) {
    3195             :         // Make a copy of the old window's performance object on document.open.
    3196             :         // Note that we have to force eager creation of it here, because we need
    3197             :         // to grab the current document channel and whatnot before that changes.
    3198           0 :         currentInner->AsInner()->CreatePerformanceObjectIfNeeded();
    3199           0 :         if (currentInner->mPerformance) {
    3200           0 :           newInnerWindow->mPerformance =
    3201           0 :             Performance::CreateForMainThread(newInnerWindow->AsInner(),
    3202           0 :                                              currentInner->mPerformance->GetDOMTiming(),
    3203           0 :                                              currentInner->mPerformance->GetChannel());
    3204             :         }
    3205             :       }
    3206             : 
    3207             :       // Don't free objects on our current inner window if it's going to be
    3208             :       // held in the bfcache.
    3209           2 :       if (!currentInner->IsFrozen()) {
    3210           2 :         currentInner->FreeInnerObjects();
    3211             :       }
    3212             :     }
    3213             : 
    3214           7 :     mInnerWindow = newInnerWindow->AsInner();
    3215           7 :     MOZ_ASSERT(mInnerWindow);
    3216           7 :     mInnerWindow->TryToCacheTopInnerWindow();
    3217             : 
    3218           7 :     if (!GetWrapperPreserveColor()) {
    3219             :       JS::Rooted<JSObject*> outer(cx,
    3220          10 :         NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
    3221           5 :       NS_ENSURE_TRUE(outer, NS_ERROR_FAILURE);
    3222             : 
    3223           5 :       js::SetProxyReservedSlot(outer, 0, js::PrivateValue(ToSupports(this)));
    3224             : 
    3225             :       // Inform the nsJSContext, which is the canonical holder of the outer.
    3226           5 :       mContext->SetWindowProxy(outer);
    3227           5 :       mContext->DidInitializeContext();
    3228             : 
    3229           5 :       SetWrapper(mContext->GetWindowProxy());
    3230             :     } else {
    3231           2 :       JS::ExposeObjectToActiveJS(newInnerGlobal);
    3232             :       JS::Rooted<JSObject*> outerObject(cx,
    3233           4 :         NewOuterWindowProxy(cx, newInnerGlobal, thisChrome));
    3234           2 :       if (!outerObject) {
    3235           0 :         NS_ERROR("out of memory");
    3236           0 :         return NS_ERROR_FAILURE;
    3237             :       }
    3238             : 
    3239           4 :       JS::Rooted<JSObject*> obj(cx, GetWrapperPreserveColor());
    3240             : 
    3241           2 :       js::SetProxyReservedSlot(obj, 0, js::PrivateValue(nullptr));
    3242           2 :       js::SetProxyReservedSlot(outerObject, 0, js::PrivateValue(nullptr));
    3243             : 
    3244           2 :       outerObject = xpc::TransplantObject(cx, obj, outerObject);
    3245           2 :       if (!outerObject) {
    3246           0 :         NS_ERROR("unable to transplant wrappers, probably OOM");
    3247           0 :         return NS_ERROR_FAILURE;
    3248             :       }
    3249             : 
    3250           2 :       js::SetProxyReservedSlot(outerObject, 0, js::PrivateValue(ToSupports(this)));
    3251             : 
    3252           2 :       SetWrapper(outerObject);
    3253             : 
    3254           2 :       MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(outerObject) == newInnerGlobal);
    3255             : 
    3256             :       // Inform the nsJSContext, which is the canonical holder of the outer.
    3257           2 :       mContext->SetWindowProxy(outerObject);
    3258             :     }
    3259             : 
    3260             :     // Enter the new global's compartment.
    3261          14 :     JSAutoCompartment ac(cx, GetWrapperPreserveColor());
    3262             : 
    3263             :     {
    3264          14 :       JS::Rooted<JSObject*> outer(cx, GetWrapperPreserveColor());
    3265           7 :       js::SetWindowProxy(cx, newInnerGlobal, outer);
    3266             :     }
    3267             : 
    3268             :     // Set scriptability based on the state of the docshell.
    3269           7 :     bool allow = GetDocShell()->GetCanExecuteScripts();
    3270           7 :     xpc::Scriptability::Get(GetWrapperPreserveColor()).SetDocShellAllowsScript(allow);
    3271             : 
    3272           7 :     if (!aState) {
    3273             :       // Get the "window" property once so it will be cached on our inner.  We
    3274             :       // have to do this here, not in binding code, because this has to happen
    3275             :       // after we've created the outer window proxy and stashed it in the outer
    3276             :       // nsGlobalWindow, so GetWrapperPreserveColor() on that outer
    3277             :       // nsGlobalWindow doesn't return null and nsGlobalWindow::OuterObject
    3278             :       // works correctly.
    3279          14 :       JS::Rooted<JS::Value> unused(cx);
    3280           7 :       if (!JS_GetProperty(cx, newInnerGlobal, "window", &unused)) {
    3281           0 :         NS_ERROR("can't create the 'window' property");
    3282           0 :         return NS_ERROR_FAILURE;
    3283             :       }
    3284             : 
    3285             :       // And same thing for the "self" property.
    3286           7 :       if (!JS_GetProperty(cx, newInnerGlobal, "self", &unused)) {
    3287           0 :         NS_ERROR("can't create the 'self' property");
    3288           0 :         return NS_ERROR_FAILURE;
    3289             :       }
    3290             :     }
    3291             :   }
    3292             : 
    3293          16 :   JSAutoCompartment ac(cx, GetWrapperPreserveColor());
    3294             : 
    3295           8 :   if (!aState && !reUseInnerWindow) {
    3296             :     // Loading a new page and creating a new inner window, *not*
    3297             :     // restoring from session history.
    3298             : 
    3299             :     // Now that both the the inner and outer windows are initialized
    3300             :     // let the script context do its magic to hook them together.
    3301           7 :     MOZ_ASSERT(mContext->GetWindowProxy() == GetWrapperPreserveColor());
    3302             : #ifdef DEBUG
    3303          14 :     JS::Rooted<JSObject*> rootedJSObject(cx, GetWrapperPreserveColor());
    3304          14 :     JS::Rooted<JSObject*> proto1(cx), proto2(cx);
    3305           7 :     JS_GetPrototype(cx, rootedJSObject, &proto1);
    3306           7 :     JS_GetPrototype(cx, newInnerGlobal, &proto2);
    3307           7 :     NS_ASSERTION(proto1 == proto2,
    3308             :                  "outer and inner globals should have the same prototype");
    3309             : #endif
    3310             : 
    3311           7 :     mInnerWindow->SyncStateFromParentWindow();
    3312             :   }
    3313             : 
    3314             :   // Add an extra ref in case we release mContext during GC.
    3315          16 :   nsCOMPtr<nsIScriptContext> kungFuDeathGrip(mContext);
    3316             : 
    3317           8 :   aDocument->SetScriptGlobalObject(newInnerWindow);
    3318           8 :   MOZ_ASSERT(newInnerWindow->mTabGroup,
    3319             :              "We must have a TabGroup cached at this point");
    3320             : 
    3321           8 :   if (!aState) {
    3322           8 :     if (reUseInnerWindow) {
    3323             : 
    3324           1 :       if (newInnerWindow->mDoc != aDocument) {
    3325           1 :         newInnerWindow->mDoc = aDocument;
    3326             : 
    3327             :         // The storage objects contain the URL of the window. We have to
    3328             :         // recreate them when the innerWindow is reused.
    3329           1 :         newInnerWindow->mLocalStorage = nullptr;
    3330           1 :         newInnerWindow->mSessionStorage = nullptr;
    3331             : 
    3332           1 :         newInnerWindow->ClearDocumentDependentSlots(cx);
    3333             :       }
    3334             :     } else {
    3335           7 :       newInnerWindow->InnerSetNewDocument(cx, aDocument);
    3336             : 
    3337             :       // Initialize DOM classes etc on the inner window.
    3338          14 :       JS::Rooted<JSObject*> obj(cx, newInnerGlobal);
    3339           7 :       rv = kungFuDeathGrip->InitClasses(obj);
    3340           7 :       NS_ENSURE_SUCCESS(rv, rv);
    3341             :     }
    3342             : 
    3343             :     // If the document comes from a JAR, check if the channel was determined
    3344             :     // to be unsafe. If so, permanently disable script on the compartment by
    3345             :     // calling Block() and throwing away the key.
    3346          16 :     nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(aDocument->GetChannel());
    3347           8 :     if (jarChannel && jarChannel->GetIsUnsafe()) {
    3348           0 :       xpc::Scriptability::Get(newInnerGlobal).Block();
    3349             :     }
    3350             : 
    3351           8 :     if (mArguments) {
    3352           1 :       newInnerWindow->DefineArgumentsProperty(mArguments);
    3353           1 :       mArguments = nullptr;
    3354             :     }
    3355             : 
    3356             :     // Give the new inner window our chrome event handler (since it
    3357             :     // doesn't have one).
    3358           8 :     newInnerWindow->mChromeEventHandler = mChromeEventHandler;
    3359             :   }
    3360             : 
    3361             :   // Ask the JS engine to assert that it's valid to access our DocGroup whenever
    3362             :   // it runs JS code for this compartment. We skip the check if this window is
    3363             :   // for chrome JS or an add-on.
    3364          16 :   nsCOMPtr<nsIPrincipal> principal = mDoc->NodePrincipal();
    3365          16 :   nsString addonId;
    3366           8 :   principal->GetAddonId(addonId);
    3367           8 :   if (GetDocGroup() && !nsContentUtils::IsSystemPrincipal(principal) && addonId.IsEmpty()) {
    3368           8 :     js::SetCompartmentValidAccessPtr(cx, newInnerGlobal,
    3369           8 :                                      newInnerWindow->GetDocGroup()->GetValidAccessPtr());
    3370             :   }
    3371             : 
    3372           8 :   kungFuDeathGrip->DidInitializeContext();
    3373             : 
    3374             :   // We wait to fire the debugger hook until the window is all set up and hooked
    3375             :   // up with the outer. See bug 969156.
    3376           8 :   if (createdInnerWindow) {
    3377          14 :     nsContentUtils::AddScriptRunner(
    3378          14 :       NewRunnableMethod("nsGlobalWindow::FireOnNewGlobalObject",
    3379             :                         newInnerWindow,
    3380           7 :                         &nsGlobalWindow::FireOnNewGlobalObject));
    3381             :   }
    3382             : 
    3383           8 :   if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
    3384             :     // We should probably notify. However if this is the, arguably bad,
    3385             :     // situation when we're creating a temporary non-chrome-about-blank
    3386             :     // document in a chrome docshell, don't notify just yet. Instead wait
    3387             :     // until we have a real chrome doc.
    3388          21 :     if (!mDocShell ||
    3389          11 :         mDocShell->ItemType() != nsIDocShellTreeItem::typeChrome ||
    3390           4 :         nsContentUtils::IsSystemPrincipal(mDoc->NodePrincipal())) {
    3391           6 :       newInnerWindow->mHasNotifiedGlobalCreated = true;
    3392          12 :       nsContentUtils::AddScriptRunner(
    3393          12 :         NewRunnableMethod("nsGlobalWindow::DispatchDOMWindowCreated",
    3394             :                           this,
    3395           6 :                           &nsGlobalWindow::DispatchDOMWindowCreated));
    3396             :     }
    3397             :   }
    3398             : 
    3399           8 :   PreloadLocalStorage();
    3400             : 
    3401             :   // If we have a recorded interesting Large-Allocation header status, report it
    3402             :   // to the newly attached document.
    3403           8 :   ReportLargeAllocStatus();
    3404           8 :   mLargeAllocStatus = LargeAllocStatus::NONE;
    3405             : 
    3406           8 :   return NS_OK;
    3407             : }
    3408             : 
    3409             : void
    3410           8 : nsGlobalWindow::PreloadLocalStorage()
    3411             : {
    3412           8 :   MOZ_ASSERT(IsOuterWindow());
    3413             : 
    3414           8 :   if (!Preferences::GetBool(kStorageEnabled)) {
    3415           5 :     return;
    3416             :   }
    3417             : 
    3418           8 :   if (IsChromeWindow()) {
    3419           5 :     return;
    3420             :   }
    3421             : 
    3422           3 :   nsIPrincipal* principal = GetPrincipal();
    3423           3 :   if (!principal) {
    3424           0 :     return;
    3425             :   }
    3426             : 
    3427             :   nsresult rv;
    3428             : 
    3429             :   nsCOMPtr<nsIDOMStorageManager> storageManager =
    3430           6 :     do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
    3431           3 :   if (NS_FAILED(rv)) {
    3432           0 :     return;
    3433             :   }
    3434             : 
    3435             :   // private browsing windows do not persist local storage to disk so we should
    3436             :   // only try to precache storage when we're not a private browsing window.
    3437           3 :   if (principal->GetPrivateBrowsingId() == 0) {
    3438           6 :     nsCOMPtr<nsIDOMStorage> storage;
    3439           3 :     rv = storageManager->PrecacheStorage(principal, getter_AddRefs(storage));
    3440           3 :     if (NS_SUCCEEDED(rv)) {
    3441           1 :       mLocalStorage = static_cast<Storage*>(storage.get());
    3442             :     }
    3443             :   }
    3444             : }
    3445             : 
    3446             : void
    3447           6 : nsGlobalWindow::DispatchDOMWindowCreated()
    3448             : {
    3449           6 :   MOZ_ASSERT(IsOuterWindow());
    3450             : 
    3451           6 :   if (!mDoc) {
    3452           0 :     return;
    3453             :   }
    3454             : 
    3455             :   // Fire DOMWindowCreated at chrome event listeners
    3456          24 :   nsContentUtils::DispatchChromeEvent(mDoc, mDoc, NS_LITERAL_STRING("DOMWindowCreated"),
    3457             :                                       true /* bubbles */,
    3458          18 :                                       false /* not cancellable */);
    3459             : 
    3460             :   nsCOMPtr<nsIObserverService> observerService =
    3461          12 :     mozilla::services::GetObserverService();
    3462             : 
    3463             :   // The event dispatching could possibly cause docshell destory, and
    3464             :   // consequently cause mDoc to be set to nullptr by DropOuterWindowDocs(),
    3465             :   // so check it again here.
    3466           6 :   if (observerService && mDoc) {
    3467          12 :     nsAutoString origin;
    3468           6 :     nsIPrincipal* principal = mDoc->NodePrincipal();
    3469           6 :     nsContentUtils::GetUTFOrigin(principal, origin);
    3470           6 :     observerService->
    3471          12 :       NotifyObservers(static_cast<nsIDOMWindow*>(this),
    3472           6 :                       nsContentUtils::IsSystemPrincipal(principal) ?
    3473             :                         "chrome-document-global-created" :
    3474             :                         "content-document-global-created",
    3475          12 :                       origin.get());
    3476             :   }
    3477             : }
    3478             : 
    3479             : void
    3480           8 : nsGlobalWindow::ClearStatus()
    3481             : {
    3482           8 :   SetStatusOuter(EmptyString());
    3483           8 : }
    3484             : 
    3485             : void
    3486           7 : nsGlobalWindow::InnerSetNewDocument(JSContext* aCx, nsIDocument* aDocument)
    3487             : {
    3488           7 :   NS_PRECONDITION(IsInnerWindow(), "Must only be called on inner windows");
    3489           7 :   MOZ_ASSERT(aDocument);
    3490             : 
    3491           7 :   if (MOZ_LOG_TEST(gDOMLeakPRLog, LogLevel::Debug)) {
    3492           0 :     nsIURI *uri = aDocument->GetDocumentURI();
    3493           0 :     MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
    3494             :             ("DOMWINDOW %p SetNewDocument %s",
    3495             :              this, uri ? uri->GetSpecOrDefault().get() : ""));
    3496             :   }
    3497             : 
    3498           7 :   mDoc = aDocument;
    3499           7 :   ClearDocumentDependentSlots(aCx);
    3500           7 :   mFocusedNode = nullptr;
    3501           7 :   mLocalStorage = nullptr;
    3502           7 :   mSessionStorage = nullptr;
    3503             : 
    3504             : #ifdef DEBUG
    3505           7 :   mLastOpenedURI = aDocument->GetDocumentURI();
    3506             : #endif
    3507             : 
    3508           7 :   Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
    3509          14 :                         mMutationBits ? 1 : 0);
    3510             : 
    3511             :   // Clear our mutation bitfield.
    3512           7 :   mMutationBits = 0;
    3513           7 : }
    3514             : 
    3515             : void
    3516           5 : nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
    3517             : {
    3518           5 :   NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!");
    3519           5 :   MOZ_ASSERT(aDocShell);
    3520             : 
    3521           5 :   if (aDocShell == mDocShell) {
    3522           0 :     return;
    3523             :   }
    3524             : 
    3525           5 :   mDocShell = aDocShell; // Weak Reference
    3526             : 
    3527          10 :   nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
    3528           5 :   MOZ_RELEASE_ASSERT(!parentWindow || !mTabGroup || mTabGroup == Cast(parentWindow)->mTabGroup);
    3529             : 
    3530           5 :   mTopLevelOuterContentWindow =
    3531           5 :     !mIsChrome && GetScriptableTopInternal() == this;
    3532             : 
    3533           5 :   NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
    3534             : 
    3535           5 :   if (mFrames) {
    3536           0 :     mFrames->SetDocShell(aDocShell);
    3537             :   }
    3538             : 
    3539             :   // Get our enclosing chrome shell and retrieve its global window impl, so
    3540             :   // that we can do some forwarding to the chrome document.
    3541          10 :   nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
    3542           5 :   mDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
    3543           5 :   mChromeEventHandler = do_QueryInterface(chromeEventHandler);
    3544           5 :   if (!mChromeEventHandler) {
    3545             :     // We have no chrome event handler. If we have a parent,
    3546             :     // get our chrome event handler from the parent. If
    3547             :     // we don't have a parent, then we need to make a new
    3548             :     // window root object that will function as a chrome event
    3549             :     // handler and receive all events that occur anywhere inside
    3550             :     // our window.
    3551           6 :     nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetParent();
    3552           3 :     if (parentWindow.get() != AsOuter()) {
    3553           0 :       mChromeEventHandler = parentWindow->GetChromeEventHandler();
    3554             :     }
    3555             :     else {
    3556           3 :       mChromeEventHandler = NS_NewWindowRoot(AsOuter());
    3557           3 :       mIsRootOuterWindow = true;
    3558             :     }
    3559             :   }
    3560             : 
    3561             :   bool docShellActive;
    3562           5 :   mDocShell->GetIsActive(&docShellActive);
    3563           5 :   SetIsBackgroundInternal(!docShellActive);
    3564             : }
    3565             : 
    3566             : void
    3567           1 : nsGlobalWindow::DetachFromDocShell()
    3568             : {
    3569           1 :   NS_ASSERTION(IsOuterWindow(), "Uh, DetachFromDocShell() called on inner window!");
    3570             : 
    3571             :   // DetachFromDocShell means the window is being torn down. Drop our
    3572             :   // reference to the script context, allowing it to be deleted
    3573             :   // later. Meanwhile, keep our weak reference to the script object
    3574             :   // so that it can be retrieved later (until it is finalized by the JS GC).
    3575             : 
    3576             :   // Call FreeInnerObjects on all inner windows, not just the current
    3577             :   // one, since some could be held by WindowStateHolder objects that
    3578             :   // are GC-owned.
    3579           2 :   for (RefPtr<nsGlobalWindow> inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
    3580             :        inner != this;
    3581           1 :        inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
    3582           1 :     MOZ_ASSERT(!inner->mOuterWindow || inner->mOuterWindow == AsOuter());
    3583           1 :     inner->FreeInnerObjects();
    3584             :   }
    3585             : 
    3586           1 :   if (auto* reporter = nsWindowMemoryReporter::Get()) {
    3587           1 :     reporter->ObserveDOMWindowDetached(this);
    3588             :   }
    3589             : 
    3590           1 :   NotifyWindowIDDestroyed("outer-window-destroyed");
    3591             : 
    3592           1 :   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
    3593             : 
    3594           1 :   if (currentInner) {
    3595           1 :     NS_ASSERTION(mDoc, "Must have doc!");
    3596             : 
    3597             :     // Remember the document's principal and URI.
    3598           1 :     mDocumentPrincipal = mDoc->NodePrincipal();
    3599           1 :     mDocumentURI = mDoc->GetDocumentURI();
    3600           1 :     mDocBaseURI = mDoc->GetDocBaseURI();
    3601             : 
    3602             :     // Release our document reference
    3603           1 :     DropOuterWindowDocs();
    3604           1 :     mFocusedNode = nullptr;
    3605             :   }
    3606             : 
    3607           1 :   ClearControllers();
    3608             : 
    3609           1 :   mChromeEventHandler = nullptr; // force release now
    3610             : 
    3611           1 :   if (mContext) {
    3612             :     // When we're about to destroy a top level content window
    3613             :     // (for example a tab), we trigger a full GC by passing null as the last
    3614             :     // param. We also trigger a full GC for chrome windows.
    3615           1 :     nsJSContext::PokeGC(JS::gcreason::SET_DOC_SHELL,
    3616           1 :                         (mTopLevelOuterContentWindow || mIsChrome) ?
    3617           1 :                           nullptr : GetWrapperPreserveColor());
    3618           1 :     mContext = nullptr;
    3619             :   }
    3620             : 
    3621           1 :   mDocShell = nullptr; // Weak Reference
    3622             : 
    3623           1 :   NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
    3624             : 
    3625           1 :   if (mFrames) {
    3626           0 :     mFrames->SetDocShell(nullptr);
    3627             :   }
    3628             : 
    3629           1 :   MaybeForgiveSpamCount();
    3630           1 :   CleanUp();
    3631           1 : }
    3632             : 
    3633             : void
    3634           1 : nsGlobalWindow::SetOpenerWindow(nsPIDOMWindowOuter* aOpener,
    3635             :                                 bool aOriginalOpener)
    3636             : {
    3637           2 :   FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener, aOriginalOpener));
    3638             : 
    3639           1 :   nsWeakPtr opener = do_GetWeakReference(aOpener);
    3640           1 :   if (opener == mOpener) {
    3641           1 :     return;
    3642             :   }
    3643             : 
    3644           0 :   NS_ASSERTION(!aOriginalOpener || !mSetOpenerWindowCalled,
    3645             :                "aOriginalOpener is true, but not first call to "
    3646             :                "SetOpenerWindow!");
    3647           0 :   NS_ASSERTION(aOpener || !aOriginalOpener,
    3648             :                "Shouldn't set mHadOriginalOpener if aOpener is null");
    3649             : 
    3650           0 :   mOpener = opener.forget();
    3651           0 :   NS_ASSERTION(mOpener || !aOpener, "Opener must support weak references!");
    3652             : 
    3653             :   // Check that the js visible opener matches! We currently don't depend on this
    3654             :   // being true outside of nightly, so we disable the assertion in optimized
    3655             :   // release / beta builds.
    3656           0 :   nsPIDOMWindowOuter* contentOpener = GetSanitizedOpener(aOpener);
    3657             : 
    3658             :   // contentOpener is not used when the DIAGNOSTIC_ASSERT is compiled out.
    3659             :   mozilla::Unused << contentOpener;
    3660           0 :   MOZ_DIAGNOSTIC_ASSERT(!contentOpener || !mTabGroup ||
    3661             :     mTabGroup == Cast(contentOpener)->mTabGroup);
    3662             : 
    3663           0 :   if (aOriginalOpener) {
    3664           0 :     MOZ_ASSERT(!mHadOriginalOpener,
    3665             :                "Probably too late to call ComputeIsSecureContext again");
    3666           0 :     mHadOriginalOpener = true;
    3667           0 :     mOriginalOpenerWasSecureContext =
    3668           0 :       aOpener->GetCurrentInnerWindow()->IsSecureContext();
    3669             :   }
    3670             : 
    3671             : #ifdef DEBUG
    3672           0 :   mSetOpenerWindowCalled = true;
    3673             : #endif
    3674             : }
    3675             : 
    3676             : static
    3677             : already_AddRefed<EventTarget>
    3678          32 : TryGetTabChildGlobalAsEventTarget(nsISupports *aFrom)
    3679             : {
    3680          64 :   nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner = do_QueryInterface(aFrom);
    3681          32 :   if (!frameLoaderOwner) {
    3682          26 :     return nullptr;
    3683             :   }
    3684             : 
    3685          12 :   RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
    3686           6 :   if (!frameLoader) {
    3687           0 :     return nullptr;
    3688             :   }
    3689             : 
    3690          12 :   nsCOMPtr<EventTarget> target = frameLoader->GetTabChildGlobalAsEventTarget();
    3691           6 :   return target.forget();
    3692             : }
    3693             : 
    3694             : void
    3695          12 : nsGlobalWindow::UpdateParentTarget()
    3696             : {
    3697             :   // Try to get our frame element's tab child global (its in-process message
    3698             :   // manager).  If that fails, fall back to the chrome event handler's tab
    3699             :   // child global, and if it doesn't have one, just use the chrome event
    3700             :   // handler itself.
    3701             : 
    3702          24 :   nsCOMPtr<Element> frameElement = GetOuterWindow()->GetFrameElementInternal();
    3703             :   nsCOMPtr<EventTarget> eventTarget =
    3704          24 :     TryGetTabChildGlobalAsEventTarget(frameElement);
    3705             : 
    3706          12 :   if (!eventTarget) {
    3707          10 :     nsGlobalWindow* topWin = GetScriptableTopInternal();
    3708          10 :     if (topWin) {
    3709          10 :       frameElement = topWin->AsOuter()->GetFrameElementInternal();
    3710          10 :       eventTarget = TryGetTabChildGlobalAsEventTarget(frameElement);
    3711             :     }
    3712             :   }
    3713             : 
    3714          12 :   if (!eventTarget) {
    3715          10 :     eventTarget = TryGetTabChildGlobalAsEventTarget(mChromeEventHandler);
    3716             :   }
    3717             : 
    3718          12 :   if (!eventTarget) {
    3719          10 :     eventTarget = mChromeEventHandler;
    3720             :   }
    3721             : 
    3722          12 :   mParentTarget = eventTarget;
    3723          12 : }
    3724             : 
    3725             : EventTarget*
    3726          68 : nsGlobalWindow::GetTargetForDOMEvent()
    3727             : {
    3728          68 :   return GetOuterWindowInternal();
    3729             : }
    3730             : 
    3731             : EventTarget*
    3732         460 : nsGlobalWindow::GetTargetForEventTargetChain()
    3733             : {
    3734         460 :   return IsInnerWindow() ? this : GetCurrentInnerWindowInternal();
    3735             : }
    3736             : 
    3737             : nsresult
    3738           0 : nsGlobalWindow::WillHandleEvent(EventChainPostVisitor& aVisitor)
    3739             : {
    3740           0 :   return NS_OK;
    3741             : }
    3742             : 
    3743             : nsresult
    3744         215 : nsGlobalWindow::GetEventTargetParent(EventChainPreVisitor& aVisitor)
    3745             : {
    3746         215 :   NS_PRECONDITION(IsInnerWindow(),
    3747             :                   "GetEventTargetParent is used on outer window!?");
    3748         215 :   EventMessage msg = aVisitor.mEvent->mMessage;
    3749             : 
    3750         215 :   aVisitor.mCanHandle = true;
    3751         215 :   aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
    3752         215 :   if (msg == eResize && aVisitor.mEvent->IsTrusted()) {
    3753             :     // QIing to window so that we can keep the old behavior also in case
    3754             :     // a child window is handling resize.
    3755             :     nsCOMPtr<nsPIDOMWindowInner> window =
    3756           4 :       do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
    3757           2 :     if (window) {
    3758           2 :       mIsHandlingResizeEvent = true;
    3759             :     }
    3760         213 :   } else if (msg == eMouseDown && aVisitor.mEvent->IsTrusted()) {
    3761           0 :     gMouseDown = true;
    3762         213 :   } else if ((msg == eMouseUp || msg == eDragEnd) &&
    3763           0 :              aVisitor.mEvent->IsTrusted()) {
    3764           0 :     gMouseDown = false;
    3765           0 :     if (gDragServiceDisabled) {
    3766             :       nsCOMPtr<nsIDragService> ds =
    3767           0 :         do_GetService("@mozilla.org/widget/dragservice;1");
    3768           0 :       if (ds) {
    3769           0 :         gDragServiceDisabled = false;
    3770           0 :         ds->Unsuppress();
    3771             :       }
    3772             :     }
    3773             :   }
    3774             : 
    3775         215 :   aVisitor.mParentTarget = GetParentTarget();
    3776             : 
    3777             :   // Handle 'active' event.
    3778         430 :   if (!mIdleObservers.IsEmpty() &&
    3779         215 :       aVisitor.mEvent->IsTrusted() &&
    3780           0 :       (aVisitor.mEvent->HasMouseEventMessage() ||
    3781           0 :        aVisitor.mEvent->HasDragEventMessage())) {
    3782           0 :     mAddActiveEventFuzzTime = false;
    3783             :   }
    3784             : 
    3785         215 :   return NS_OK;
    3786             : }
    3787             : 
    3788             : bool
    3789           0 : nsGlobalWindow::ShouldPromptToBlockDialogs()
    3790             : {
    3791           0 :   MOZ_ASSERT(IsOuterWindow());
    3792             : 
    3793           0 :   nsGlobalWindow *topWindow = GetScriptableTopInternal();
    3794           0 :   if (!topWindow) {
    3795           0 :     NS_ASSERTION(!mDocShell, "ShouldPromptToBlockDialogs() called without a top window?");
    3796           0 :     return true;
    3797             :   }
    3798             : 
    3799           0 :   topWindow = topWindow->GetCurrentInnerWindowInternal();
    3800           0 :   if (!topWindow) {
    3801           0 :     return true;
    3802             :   }
    3803             : 
    3804           0 :   return topWindow->DialogsAreBeingAbused();
    3805             : }
    3806             : 
    3807             : bool
    3808           5 : nsGlobalWindow::AreDialogsEnabled()
    3809             : {
    3810           5 :   MOZ_ASSERT(IsOuterWindow());
    3811             : 
    3812           5 :   nsGlobalWindow *topWindow = GetScriptableTopInternal();
    3813           5 :   if (!topWindow) {
    3814           0 :     NS_ERROR("AreDialogsEnabled() called without a top window?");
    3815           0 :     return false;
    3816             :   }
    3817             : 
    3818             :   // TODO: Warn if no top window?
    3819           5 :   topWindow = topWindow->GetCurrentInnerWindowInternal();
    3820           5 :   if (!topWindow) {
    3821           0 :     return false;
    3822             :   }
    3823             : 
    3824             :   // Dialogs are blocked if the content viewer is hidden
    3825           5 :   if (mDocShell) {
    3826          10 :     nsCOMPtr<nsIContentViewer> cv;
    3827           5 :     mDocShell->GetContentViewer(getter_AddRefs(cv));
    3828             : 
    3829             :     bool isHidden;
    3830           5 :     cv->GetIsHidden(&isHidden);
    3831           5 :     if (isHidden) {
    3832           0 :       return false;
    3833             :     }
    3834             :   }
    3835             : 
    3836             :   // Dialogs are also blocked if the document is sandboxed with SANDBOXED_MODALS
    3837             :   // (or if we have no document, of course).  Which document?  Who knows; the
    3838             :   // spec is daft.  See <https://github.com/whatwg/html/issues/1206>.  For now
    3839             :   // just go ahead and check mDoc, since in everything except edge cases in
    3840             :   // which a frame is allow-same-origin but not allow-scripts and is being poked
    3841             :   // at by some other window this should be the right thing anyway.
    3842           5 :   if (!mDoc || (mDoc->GetSandboxFlags() & SANDBOXED_MODALS)) {
    3843           0 :     return false;
    3844             :   }
    3845             : 
    3846           5 :   return topWindow->mAreDialogsEnabled;
    3847             : }
    3848             : 
    3849             : bool
    3850           0 : nsGlobalWindow::DialogsAreBeingAbused()
    3851             : {
    3852           0 :   MOZ_ASSERT(IsInnerWindow());
    3853           0 :   NS_ASSERTION(GetScriptableTopInternal() &&
    3854             :                GetScriptableTopInternal()->GetCurrentInnerWindowInternal() == this,
    3855             :                "DialogsAreBeingAbused called with invalid window");
    3856             : 
    3857           0 :   if (mLastDialogQuitTime.IsNull() ||
    3858           0 :       nsContentUtils::IsCallerChrome()) {
    3859           0 :     return false;
    3860             :   }
    3861             : 
    3862           0 :   TimeDuration dialogInterval(TimeStamp::Now() - mLastDialogQuitTime);
    3863           0 :   if (dialogInterval.ToSeconds() <
    3864           0 :       Preferences::GetInt("dom.successive_dialog_time_limit",
    3865             :                           DEFAULT_SUCCESSIVE_DIALOG_TIME_LIMIT)) {
    3866           0 :     mDialogAbuseCount++;
    3867             : 
    3868           0 :     return GetPopupControlState() > openAllowed ||
    3869           0 :            mDialogAbuseCount > MAX_SUCCESSIVE_DIALOG_COUNT;
    3870             :   }
    3871             : 
    3872             :   // Reset the abuse counter
    3873           0 :   mDialogAbuseCount = 0;
    3874             : 
    3875           0 :   return false;
    3876             : }
    3877             : 
    3878             : bool
    3879           0 : nsGlobalWindow::ConfirmDialogIfNeeded()
    3880             : {
    3881           0 :   MOZ_ASSERT(IsOuterWindow());
    3882             : 
    3883           0 :   NS_ENSURE_TRUE(mDocShell, false);
    3884             :   nsCOMPtr<nsIPromptService> promptSvc =
    3885           0 :     do_GetService("@mozilla.org/embedcomp/prompt-service;1");
    3886             : 
    3887           0 :   if (!promptSvc) {
    3888           0 :     return true;
    3889             :   }
    3890             : 
    3891             :   // Reset popup state while opening a modal dialog, and firing events
    3892             :   // about the dialog, to prevent the current state from being active
    3893             :   // the whole time a modal dialog is open.
    3894           0 :   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    3895             : 
    3896           0 :   bool disableDialog = false;
    3897           0 :   nsXPIDLString label, title;
    3898             :   nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    3899           0 :                                      "ScriptDialogLabel", label);
    3900             :   nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    3901           0 :                                      "ScriptDialogPreventTitle", title);
    3902           0 :   promptSvc->Confirm(AsOuter(), title.get(), label.get(), &disableDialog);
    3903           0 :   if (disableDialog) {
    3904           0 :     DisableDialogs();
    3905           0 :     return false;
    3906             :   }
    3907             : 
    3908           0 :   return true;
    3909             : }
    3910             : 
    3911             : void
    3912           0 : nsGlobalWindow::DisableDialogs()
    3913             : {
    3914           0 :   nsGlobalWindow *topWindow = GetScriptableTopInternal();
    3915           0 :   if (!topWindow) {
    3916           0 :     NS_ERROR("DisableDialogs() called without a top window?");
    3917           0 :     return;
    3918             :   }
    3919             : 
    3920           0 :   topWindow = topWindow->GetCurrentInnerWindowInternal();
    3921             :   // TODO: Warn if no top window?
    3922           0 :   if (topWindow) {
    3923           0 :     topWindow->mAreDialogsEnabled = false;
    3924             :   }
    3925             : }
    3926             : 
    3927             : void
    3928           0 : nsGlobalWindow::EnableDialogs()
    3929             : {
    3930           0 :   nsGlobalWindow *topWindow = GetScriptableTopInternal();
    3931           0 :   if (!topWindow) {
    3932           0 :     NS_ERROR("EnableDialogs() called without a top window?");
    3933           0 :     return;
    3934             :   }
    3935             : 
    3936             :   // TODO: Warn if no top window?
    3937           0 :   topWindow = topWindow->GetCurrentInnerWindowInternal();
    3938           0 :   if (topWindow) {
    3939           0 :     topWindow->mAreDialogsEnabled = true;
    3940             :   }
    3941             : }
    3942             : 
    3943             : nsresult
    3944         134 : nsGlobalWindow::PostHandleEvent(EventChainPostVisitor& aVisitor)
    3945             : {
    3946         134 :   NS_PRECONDITION(IsInnerWindow(), "PostHandleEvent is used on outer window!?");
    3947             : 
    3948             :   // Return early if there is nothing to do.
    3949         134 :   switch (aVisitor.mEvent->mMessage) {
    3950             :     case eResize:
    3951             :     case eUnload:
    3952             :     case eLoad:
    3953          10 :       break;
    3954             :     default:
    3955         124 :       return NS_OK;
    3956             :   }
    3957             : 
    3958             :   /* mChromeEventHandler and mContext go dangling in the middle of this
    3959             :    function under some circumstances (events that destroy the window)
    3960             :    without this addref. */
    3961          20 :   nsCOMPtr<nsIDOMEventTarget> kungFuDeathGrip1(mChromeEventHandler);
    3962             :   mozilla::Unused << kungFuDeathGrip1; // These aren't referred to through the function
    3963          20 :   nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
    3964             :   mozilla::Unused << kungFuDeathGrip2; // These aren't referred to through the function
    3965             : 
    3966             : 
    3967          10 :   if (aVisitor.mEvent->mMessage == eResize) {
    3968           2 :     mIsHandlingResizeEvent = false;
    3969          12 :   } else if (aVisitor.mEvent->mMessage == eUnload &&
    3970           4 :              aVisitor.mEvent->IsTrusted()) {
    3971             : 
    3972             :     // If any VR display presentation is active at unload, the next page
    3973             :     // will receive a vrdisplayactive event to indicate that it should
    3974             :     // immediately begin vr presentation. This should occur when navigating
    3975             :     // forwards, navigating backwards, and on page reload.
    3976           4 :     for (const auto& display : mVRDisplays) {
    3977           0 :       if (display->IsPresenting()) {
    3978             :         // Save this VR display ID to trigger vrdisplayactivate event
    3979             :         // after the next load event.
    3980           0 :         nsGlobalWindow* outer = GetOuterWindowInternal();
    3981           0 :         if (outer) {
    3982           0 :           outer->SetAutoActivateVRDisplayID(display->DisplayId());
    3983             :         }
    3984             : 
    3985             :         // XXX The WebVR 1.1 spec does not define which of multiple VR
    3986             :         // presenting VR displays will be chosen during navigation.
    3987             :         // As the underlying platform VR API's currently only allow a single
    3988             :         // VR display, it is safe to choose the first VR display for now.
    3989           0 :         break;
    3990             :       }
    3991             :     }
    3992             :     // Execute bindingdetached handlers before we tear ourselves
    3993             :     // down.
    3994           4 :     if (mDoc) {
    3995           4 :       mDoc->BindingManager()->ExecuteDetachedHandlers();
    3996             :     }
    3997           4 :     mIsDocumentLoaded = false;
    3998           8 :   } else if (aVisitor.mEvent->mMessage == eLoad &&
    3999           4 :              aVisitor.mEvent->IsTrusted()) {
    4000             :     // This is page load event since load events don't propagate to |window|.
    4001             :     // @see nsDocument::GetEventTargetParent.
    4002           4 :     mIsDocumentLoaded = true;
    4003             : 
    4004           4 :     mTimeoutManager->OnDocumentLoaded();
    4005             : 
    4006           8 :     nsCOMPtr<Element> element = GetOuterWindow()->GetFrameElementInternal();
    4007           4 :     nsIDocShell* docShell = GetDocShell();
    4008           9 :     if (element && GetParentInternal() &&
    4009           5 :         docShell && docShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
    4010             :       // If we're not in chrome, or at a chrome boundary, fire the
    4011             :       // onload event for the frame element.
    4012             : 
    4013           0 :       nsEventStatus status = nsEventStatus_eIgnore;
    4014           0 :       WidgetEvent event(aVisitor.mEvent->IsTrusted(), eLoad);
    4015           0 :       event.mFlags.mBubbles = false;
    4016           0 :       event.mFlags.mCancelable = false;
    4017             : 
    4018             :       // Most of the time we could get a pres context to pass in here,
    4019             :       // but not always (i.e. if this window is not shown there won't
    4020             :       // be a pres context available). Since we're not firing a GUI
    4021             :       // event we don't need a pres context anyway so we just pass
    4022             :       // null as the pres context all the time here.
    4023           0 :       EventDispatcher::Dispatch(element, nullptr, &event, nullptr, &status);
    4024             :     }
    4025             : 
    4026           4 :     uint32_t autoActivateVRDisplayID = 0;
    4027           4 :     nsGlobalWindow* outer = GetOuterWindowInternal();
    4028           4 :     if (outer) {
    4029           4 :       autoActivateVRDisplayID = outer->GetAutoActivateVRDisplayID();
    4030             :     }
    4031           4 :     if (autoActivateVRDisplayID) {
    4032             :       DispatchVRDisplayActivate(autoActivateVRDisplayID,
    4033           0 :                                 VRDisplayEventReason::Navigation);
    4034             :     }
    4035             :   }
    4036             : 
    4037          10 :   return NS_OK;
    4038             : }
    4039             : 
    4040             : nsresult
    4041           0 : nsGlobalWindow::DispatchDOMEvent(WidgetEvent* aEvent,
    4042             :                                  nsIDOMEvent* aDOMEvent,
    4043             :                                  nsPresContext* aPresContext,
    4044             :                                  nsEventStatus* aEventStatus)
    4045             : {
    4046           0 :   return EventDispatcher::DispatchDOMEvent(static_cast<nsPIDOMWindow*>(this),
    4047             :                                            aEvent, aDOMEvent, aPresContext,
    4048           0 :                                            aEventStatus);
    4049             : }
    4050             : 
    4051             : void
    4052           0 : nsGlobalWindow::PoisonOuterWindowProxy(JSObject *aObject)
    4053             : {
    4054           0 :   MOZ_ASSERT(IsOuterWindow());
    4055           0 :   if (aObject == GetWrapperMaybeDead()) {
    4056           0 :     PoisonWrapper();
    4057             :   }
    4058           0 : }
    4059             : 
    4060             : nsresult
    4061           1 : nsGlobalWindow::SetArguments(nsIArray *aArguments)
    4062             : {
    4063           1 :   MOZ_ASSERT(IsOuterWindow());
    4064             :   nsresult rv;
    4065             : 
    4066             :   // Historically, we've used the same machinery to handle openDialog arguments
    4067             :   // (exposed via window.arguments) and showModalDialog arguments (exposed via
    4068             :   // window.dialogArguments), even though the former is XUL-only and uses an XPCOM
    4069             :   // array while the latter is web-exposed and uses an arbitrary JS value.
    4070             :   // Moreover, per-spec |dialogArguments| is a property of the browsing context
    4071             :   // (outer), whereas |arguments| lives on the inner.
    4072             :   //
    4073             :   // We've now mostly separated them, but the difference is still opaque to
    4074             :   // nsWindowWatcher (the caller of SetArguments in this little back-and-forth
    4075             :   // embedding waltz we do here).
    4076             :   //
    4077             :   // So we need to demultiplex the two cases here.
    4078           1 :   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
    4079           1 :   if (mIsModalContentWindow) {
    4080             :     // nsWindowWatcher blindly converts the original nsISupports into an array
    4081             :     // of length 1. We need to recover it, and then cast it back to the concrete
    4082             :     // object we know it to be.
    4083           0 :     nsCOMPtr<nsISupports> supports = do_QueryElementAt(aArguments, 0, &rv);
    4084           0 :     NS_ENSURE_SUCCESS(rv, rv);
    4085           0 :     mDialogArguments = static_cast<DialogValueHolder*>(supports.get());
    4086             :   } else {
    4087           1 :     mArguments = aArguments;
    4088           1 :     rv = currentInner->DefineArgumentsProperty(aArguments);
    4089           1 :     NS_ENSURE_SUCCESS(rv, rv);
    4090             :   }
    4091             : 
    4092           1 :   return NS_OK;
    4093             : }
    4094             : 
    4095             : nsresult
    4096           2 : nsGlobalWindow::DefineArgumentsProperty(nsIArray *aArguments)
    4097             : {
    4098           2 :   MOZ_ASSERT(IsInnerWindow());
    4099           2 :   MOZ_ASSERT(!mIsModalContentWindow); // Handled separately.
    4100             : 
    4101           2 :   nsIScriptContext *ctx = GetOuterWindowInternal()->mContext;
    4102           2 :   NS_ENSURE_TRUE(aArguments && ctx, NS_ERROR_NOT_INITIALIZED);
    4103             : 
    4104           4 :   JS::Rooted<JSObject*> obj(RootingCx(), GetWrapperPreserveColor());
    4105           2 :   return ctx->SetProperty(obj, "arguments", aArguments);
    4106             : }
    4107             : 
    4108             : //*****************************************************************************
    4109             : // nsGlobalWindow::nsIScriptObjectPrincipal
    4110             : //*****************************************************************************
    4111             : 
    4112             : nsIPrincipal*
    4113          72 : nsGlobalWindow::GetPrincipal()
    4114             : {
    4115          72 :   if (mDoc) {
    4116             :     // If we have a document, get the principal from the document
    4117          72 :     return mDoc->NodePrincipal();
    4118             :   }
    4119             : 
    4120           0 :   if (mDocumentPrincipal) {
    4121           0 :     return mDocumentPrincipal;
    4122             :   }
    4123             : 
    4124             :   // If we don't have a principal and we don't have a document we
    4125             :   // ask the parent window for the principal. This can happen when
    4126             :   // loading a frameset that has a <frame src="javascript:xxx">, in
    4127             :   // that case the global window is used in JS before we've loaded
    4128             :   // a document into the window.
    4129             : 
    4130             :   nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
    4131           0 :     do_QueryInterface(GetParentInternal());
    4132             : 
    4133           0 :   if (objPrincipal) {
    4134           0 :     return objPrincipal->GetPrincipal();
    4135             :   }
    4136             : 
    4137           0 :   return nullptr;
    4138             : }
    4139             : 
    4140             : //*****************************************************************************
    4141             : // nsGlobalWindow::nsIDOMWindow
    4142             : //*****************************************************************************
    4143             : 
    4144             : template <class T>
    4145             : nsIURI*
    4146           0 : nsPIDOMWindow<T>::GetDocumentURI() const
    4147             : {
    4148           0 :   return mDoc ? mDoc->GetDocumentURI() : mDocumentURI.get();
    4149             : }
    4150             : 
    4151             : template <class T>
    4152             : nsIURI*
    4153           0 : nsPIDOMWindow<T>::GetDocBaseURI() const
    4154             : {
    4155           0 :   return mDoc ? mDoc->GetDocBaseURI() : mDocBaseURI.get();
    4156             : }
    4157             : 
    4158             : template <class T>
    4159             : void
    4160           9 : nsPIDOMWindow<T>::MaybeCreateDoc()
    4161             : {
    4162           9 :   MOZ_ASSERT(!mDoc);
    4163           9 :   if (nsIDocShell* docShell = GetDocShell()) {
    4164             :     // Note that |document| here is the same thing as our mDoc, but we
    4165             :     // don't have to explicitly set the member variable because the docshell
    4166             :     // has already called SetNewDocument().
    4167           9 :     nsCOMPtr<nsIDocument> document = docShell->GetDocument();
    4168             :     Unused << document;
    4169             :   }
    4170           9 : }
    4171             : 
    4172             : void
    4173           1 : nsPIDOMWindowOuter::SetInitialKeyboardIndicators(
    4174             :   UIStateChangeType aShowAccelerators, UIStateChangeType aShowFocusRings)
    4175             : {
    4176           1 :   MOZ_ASSERT(IsOuterWindow());
    4177           1 :   MOZ_ASSERT(!GetCurrentInnerWindow());
    4178             : 
    4179           1 :   nsPIDOMWindowOuter* piWin = GetPrivateRoot();
    4180           1 :   if (!piWin) {
    4181           0 :     return;
    4182             :   }
    4183             : 
    4184           1 :   MOZ_ASSERT(piWin == AsOuter());
    4185             : 
    4186             :   // only change the flags that have been modified
    4187           2 :   nsCOMPtr<nsPIWindowRoot> windowRoot = do_QueryInterface(mChromeEventHandler);
    4188           1 :   if (!windowRoot) {
    4189           0 :     return;
    4190             :   }
    4191             : 
    4192           1 :   if (aShowAccelerators != UIStateChangeType_NoChange) {
    4193           1 :     windowRoot->SetShowAccelerators(aShowAccelerators == UIStateChangeType_Set);
    4194             :   }
    4195           1 :   if (aShowFocusRings != UIStateChangeType_NoChange) {
    4196           1 :     windowRoot->SetShowFocusRings(aShowFocusRings == UIStateChangeType_Set);
    4197             :   }
    4198             : 
    4199           1 :   nsContentUtils::SetKeyboardIndicatorsOnRemoteChildren(GetOuterWindow(),
    4200             :                                                         aShowAccelerators,
    4201           1 :                                                         aShowFocusRings);
    4202             : }
    4203             : 
    4204             : Element*
    4205         101 : nsPIDOMWindowOuter::GetFrameElementInternal() const
    4206             : {
    4207         101 :   MOZ_ASSERT(IsOuterWindow());
    4208         101 :   return mFrameElement;
    4209             : }
    4210             : 
    4211             : void
    4212           3 : nsPIDOMWindowOuter::SetFrameElementInternal(Element* aFrameElement)
    4213             : {
    4214           3 :   MOZ_ASSERT(IsOuterWindow());
    4215           3 :   mFrameElement = aFrameElement;
    4216           3 : }
    4217             : 
    4218             : bool
    4219           0 : nsPIDOMWindowInner::AddAudioContext(AudioContext* aAudioContext)
    4220             : {
    4221           0 :   MOZ_ASSERT(IsInnerWindow());
    4222             : 
    4223           0 :   mAudioContexts.AppendElement(aAudioContext);
    4224             : 
    4225             :   // Return true if the context should be muted and false if not.
    4226           0 :   nsIDocShell* docShell = GetDocShell();
    4227           0 :   return docShell && !docShell->GetAllowMedia() && !aAudioContext->IsOffline();
    4228             : }
    4229             : 
    4230             : void
    4231           0 : nsPIDOMWindowInner::RemoveAudioContext(AudioContext* aAudioContext)
    4232             : {
    4233           0 :   MOZ_ASSERT(IsInnerWindow());
    4234             : 
    4235           0 :   mAudioContexts.RemoveElement(aAudioContext);
    4236           0 : }
    4237             : 
    4238             : void
    4239           0 : nsPIDOMWindowInner::MuteAudioContexts()
    4240             : {
    4241           0 :   MOZ_ASSERT(IsInnerWindow());
    4242             : 
    4243           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    4244           0 :     if (!mAudioContexts[i]->IsOffline()) {
    4245           0 :       mAudioContexts[i]->Mute();
    4246             :     }
    4247             :   }
    4248           0 : }
    4249             : 
    4250             : void
    4251           0 : nsPIDOMWindowInner::UnmuteAudioContexts()
    4252             : {
    4253           0 :   MOZ_ASSERT(IsInnerWindow());
    4254             : 
    4255           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
    4256           0 :     if (!mAudioContexts[i]->IsOffline()) {
    4257           0 :       mAudioContexts[i]->Unmute();
    4258             :     }
    4259             :   }
    4260           0 : }
    4261             : 
    4262             : nsGlobalWindow*
    4263           7 : nsGlobalWindow::Window()
    4264             : {
    4265           7 :   return this;
    4266             : }
    4267             : 
    4268             : nsGlobalWindow*
    4269           7 : nsGlobalWindow::Self()
    4270             : {
    4271           7 :   return this;
    4272             : }
    4273             : 
    4274             : Navigator*
    4275           0 : nsGlobalWindow::Navigator()
    4276             : {
    4277           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    4278             : 
    4279           0 :   if (!mNavigator) {
    4280           0 :     mNavigator = new mozilla::dom::Navigator(AsInner());
    4281             :   }
    4282             : 
    4283           0 :   return mNavigator;
    4284             : }
    4285             : 
    4286             : nsIDOMNavigator*
    4287           0 : nsGlobalWindow::GetNavigator()
    4288             : {
    4289           0 :   FORWARD_TO_INNER(GetNavigator, (), nullptr);
    4290             : 
    4291           0 :   return Navigator();
    4292             : }
    4293             : 
    4294             : nsScreen*
    4295           6 : nsGlobalWindow::GetScreen(ErrorResult& aError)
    4296             : {
    4297           6 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    4298             : 
    4299           6 :   if (!mScreen) {
    4300           1 :     mScreen = nsScreen::Create(AsInner());
    4301           1 :     if (!mScreen) {
    4302           0 :       aError.Throw(NS_ERROR_UNEXPECTED);
    4303           0 :       return nullptr;
    4304             :     }
    4305             :   }
    4306             : 
    4307           6 :   return mScreen;
    4308             : }
    4309             : 
    4310             : nsIDOMScreen*
    4311           2 : nsGlobalWindow::GetScreen()
    4312             : {
    4313           2 :   FORWARD_TO_INNER(GetScreen, (), nullptr);
    4314             : 
    4315           2 :   ErrorResult dummy;
    4316           1 :   nsIDOMScreen* screen = GetScreen(dummy);
    4317           1 :   dummy.SuppressException();
    4318           1 :   return screen;
    4319             : }
    4320             : 
    4321             : nsHistory*
    4322           0 : nsGlobalWindow::GetHistory(ErrorResult& aError)
    4323             : {
    4324           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    4325             : 
    4326           0 :   if (!mHistory) {
    4327           0 :     mHistory = new nsHistory(AsInner());
    4328             :   }
    4329             : 
    4330           0 :   return mHistory;
    4331             : }
    4332             : 
    4333             : CustomElementRegistry*
    4334           0 : nsGlobalWindow::CustomElements()
    4335             : {
    4336           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    4337             : 
    4338           0 :   if (!mCustomElements) {
    4339           0 :     mCustomElements = new CustomElementRegistry(AsInner());
    4340             :   }
    4341             : 
    4342           0 :   return mCustomElements;
    4343             : }
    4344             : 
    4345             : Performance*
    4346         112 : nsPIDOMWindowInner::GetPerformance()
    4347             : {
    4348         112 :   MOZ_ASSERT(IsInnerWindow());
    4349         112 :   CreatePerformanceObjectIfNeeded();
    4350         112 :   return mPerformance;
    4351             : }
    4352             : 
    4353             : Performance*
    4354          15 : nsGlobalWindow::GetPerformance()
    4355             : {
    4356          15 :   return AsInner()->GetPerformance();
    4357             : }
    4358             : 
    4359             : void
    4360         112 : nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded()
    4361             : {
    4362         112 :   MOZ_ASSERT(IsInnerWindow());
    4363             : 
    4364         112 :   if (mPerformance || !mDoc) {
    4365         105 :     return;
    4366             :   }
    4367          14 :   RefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
    4368          14 :   nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
    4369           7 :   bool timingEnabled = false;
    4370          15 :   if (!timedChannel ||
    4371           8 :       !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
    4372           1 :       !timingEnabled) {
    4373           6 :     timedChannel = nullptr;
    4374             :   }
    4375           7 :   if (timing) {
    4376           7 :     mPerformance = Performance::CreateForMainThread(this, timing, timedChannel);
    4377             :   }
    4378             : }
    4379             : 
    4380             : bool
    4381           0 : nsPIDOMWindowInner::IsSecureContext() const
    4382             : {
    4383           0 :   return nsGlobalWindow::Cast(this)->IsSecureContext();
    4384             : }
    4385             : 
    4386             : bool
    4387           0 : nsPIDOMWindowInner::IsSecureContextIfOpenerIgnored() const
    4388             : {
    4389           0 :   return nsGlobalWindow::Cast(this)->IsSecureContextIfOpenerIgnored();
    4390             : }
    4391             : 
    4392             : void
    4393           0 : nsPIDOMWindowInner::Suspend()
    4394             : {
    4395           0 :   nsGlobalWindow::Cast(this)->Suspend();
    4396           0 : }
    4397             : 
    4398             : void
    4399           0 : nsPIDOMWindowInner::Resume()
    4400             : {
    4401           0 :   nsGlobalWindow::Cast(this)->Resume();
    4402           0 : }
    4403             : 
    4404             : void
    4405           0 : nsPIDOMWindowInner::Freeze()
    4406             : {
    4407           0 :   nsGlobalWindow::Cast(this)->Freeze();
    4408           0 : }
    4409             : 
    4410             : void
    4411           0 : nsPIDOMWindowInner::Thaw()
    4412             : {
    4413           0 :   nsGlobalWindow::Cast(this)->Thaw();
    4414           0 : }
    4415             : 
    4416             : void
    4417           7 : nsPIDOMWindowInner::SyncStateFromParentWindow()
    4418             : {
    4419           7 :   nsGlobalWindow::Cast(this)->SyncStateFromParentWindow();
    4420           7 : }
    4421             : 
    4422             : bool
    4423           4 : nsPIDOMWindowInner::IsPlayingAudio()
    4424             : {
    4425           8 :   RefPtr<AudioChannelService> acs = AudioChannelService::Get();
    4426           4 :   if (!acs) {
    4427           0 :     return false;
    4428             :   }
    4429           4 :   auto outer = GetOuterWindow();
    4430           4 :   if (!outer) {
    4431             :     // We've been unlinked and are about to die.  Not a good time to pretend to
    4432             :     // be playing audio.
    4433           0 :     return false;
    4434             :   }
    4435           4 :   return acs->IsWindowActive(outer);
    4436             : }
    4437             : 
    4438             : bool
    4439           0 : nsPIDOMWindowInner::IsDocumentLoaded() const
    4440             : {
    4441           0 :   return mIsDocumentLoaded;
    4442             : }
    4443             : 
    4444             : mozilla::dom::TimeoutManager&
    4445           0 : nsPIDOMWindowInner::TimeoutManager()
    4446             : {
    4447           0 :   return *mTimeoutManager;
    4448             : }
    4449             : 
    4450             : bool
    4451           0 : nsPIDOMWindowInner::IsRunningTimeout()
    4452             : {
    4453           0 :   return TimeoutManager().IsRunningTimeout();
    4454             : }
    4455             : 
    4456             : void
    4457           7 : nsPIDOMWindowInner::TryToCacheTopInnerWindow()
    4458             : {
    4459           7 :   if (mHasTriedToCacheTopInnerWindow) {
    4460           0 :     return;
    4461             :   }
    4462             : 
    4463           7 :   MOZ_ASSERT(!mInnerObjectsFreed);
    4464             : 
    4465           7 :   mHasTriedToCacheTopInnerWindow = true;
    4466             : 
    4467           7 :   nsGlobalWindow* window = nsGlobalWindow::Cast(AsInner());
    4468             : 
    4469           7 :   MOZ_ASSERT(window);
    4470             : 
    4471          14 :   if (nsCOMPtr<nsPIDOMWindowOuter> topOutter = window->GetScriptableTop()) {
    4472           7 :     mTopInnerWindow = topOutter->GetCurrentInnerWindow();
    4473             :   }
    4474             : }
    4475             : 
    4476             : void
    4477           0 : nsPIDOMWindowInner::UpdateActiveIndexedDBTransactionCount(int32_t aDelta)
    4478             : {
    4479           0 :   MOZ_ASSERT(NS_IsMainThread());
    4480             : 
    4481           0 :   if (aDelta == 0) {
    4482           0 :     return;
    4483             :   }
    4484             : 
    4485           0 :   TabGroup()->IndexedDBTransactionCounter() += aDelta;
    4486             : }
    4487             : 
    4488             : void
    4489           0 : nsPIDOMWindowInner::UpdateActiveIndexedDBDatabaseCount(int32_t aDelta)
    4490             : {
    4491           0 :   MOZ_ASSERT(NS_IsMainThread());
    4492             : 
    4493           0 :   if (aDelta == 0) {
    4494           0 :     return;
    4495             :   }
    4496             : 
    4497             :   // We count databases but not transactions because only active databases
    4498             :   // could block throttling.
    4499             :   uint32_t& counter = mTopInnerWindow ?
    4500           0 :     mTopInnerWindow->mNumOfIndexedDBDatabases : mNumOfIndexedDBDatabases;
    4501             : 
    4502           0 :   counter+= aDelta;
    4503             : 
    4504           0 :   TabGroup()->IndexedDBDatabaseCounter() += aDelta;
    4505             : }
    4506             : 
    4507             : bool
    4508           4 : nsPIDOMWindowInner::HasActiveIndexedDBDatabases()
    4509             : {
    4510           4 :   MOZ_ASSERT(NS_IsMainThread());
    4511             : 
    4512           8 :   return mTopInnerWindow ?
    4513           4 :     mTopInnerWindow->mNumOfIndexedDBDatabases > 0 :
    4514           8 :     mNumOfIndexedDBDatabases > 0;
    4515             : }
    4516             : 
    4517             : void
    4518           5 : nsPIDOMWindowOuter::MaybeActiveMediaComponents()
    4519             : {
    4520           5 :   if (IsInnerWindow()) {
    4521           0 :     return mOuterWindow->MaybeActiveMediaComponents();
    4522             :   }
    4523             : 
    4524           5 :   if (mMediaSuspend != nsISuspendedTypes::SUSPENDED_BLOCK) {
    4525           1 :     return;
    4526             :   }
    4527             : 
    4528           4 :   MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
    4529             :          ("nsPIDOMWindowOuter, MaybeActiveMediaComponents, "
    4530             :           "resume the window from blocked, this = %p\n", this));
    4531             : 
    4532           4 :   SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED);
    4533             : }
    4534             : 
    4535             : SuspendTypes
    4536           0 : nsPIDOMWindowOuter::GetMediaSuspend() const
    4537             : {
    4538           0 :   if (IsInnerWindow()) {
    4539           0 :     return mOuterWindow->GetMediaSuspend();
    4540             :   }
    4541             : 
    4542           0 :   return mMediaSuspend;
    4543             : }
    4544             : 
    4545             : void
    4546           4 : nsPIDOMWindowOuter::SetMediaSuspend(SuspendTypes aSuspend)
    4547             : {
    4548           4 :   if (IsInnerWindow()) {
    4549           0 :     mOuterWindow->SetMediaSuspend(aSuspend);
    4550           0 :     return;
    4551             :   }
    4552             : 
    4553           4 :   if (!IsDisposableSuspend(aSuspend)) {
    4554           4 :     MaybeNotifyMediaResumedFromBlock(aSuspend);
    4555           4 :     mMediaSuspend = aSuspend;
    4556             :   }
    4557             : 
    4558           4 :   RefreshMediaElementsSuspend(aSuspend);
    4559             : }
    4560             : 
    4561             : void
    4562           4 : nsPIDOMWindowOuter::MaybeNotifyMediaResumedFromBlock(SuspendTypes aSuspend)
    4563             : {
    4564           4 :   if (mMediaSuspend == nsISuspendedTypes::SUSPENDED_BLOCK &&
    4565             :       aSuspend == nsISuspendedTypes::NONE_SUSPENDED) {
    4566           8 :     RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
    4567           4 :     if (service) {
    4568           4 :       service->NotifyMediaResumedFromBlock(GetOuterWindow());
    4569             :     }
    4570             :   }
    4571           4 : }
    4572             : 
    4573             : bool
    4574           0 : nsPIDOMWindowOuter::GetAudioMuted() const
    4575             : {
    4576           0 :   if (IsInnerWindow()) {
    4577           0 :     return mOuterWindow->GetAudioMuted();
    4578             :   }
    4579             : 
    4580           0 :   return mAudioMuted;
    4581             : }
    4582             : 
    4583             : void
    4584           0 : nsPIDOMWindowOuter::SetAudioMuted(bool aMuted)
    4585             : {
    4586           0 :   if (IsInnerWindow()) {
    4587           0 :     mOuterWindow->SetAudioMuted(aMuted);
    4588           0 :     return;
    4589             :   }
    4590             : 
    4591           0 :   if (mAudioMuted == aMuted) {
    4592           0 :     return;
    4593             :   }
    4594             : 
    4595           0 :   mAudioMuted = aMuted;
    4596           0 :   RefreshMediaElementsVolume();
    4597             : }
    4598             : 
    4599             : float
    4600           0 : nsPIDOMWindowOuter::GetAudioVolume() const
    4601             : {
    4602           0 :   if (IsInnerWindow()) {
    4603           0 :     return mOuterWindow->GetAudioVolume();
    4604             :   }
    4605             : 
    4606           0 :   return mAudioVolume;
    4607             : }
    4608             : 
    4609             : nsresult
    4610           0 : nsPIDOMWindowOuter::SetAudioVolume(float aVolume)
    4611             : {
    4612           0 :   if (IsInnerWindow()) {
    4613           0 :     return mOuterWindow->SetAudioVolume(aVolume);
    4614             :   }
    4615             : 
    4616           0 :   if (aVolume < 0.0) {
    4617           0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
    4618             :   }
    4619             : 
    4620           0 :   if (mAudioVolume == aVolume) {
    4621           0 :     return NS_OK;
    4622             :   }
    4623             : 
    4624           0 :   mAudioVolume = aVolume;
    4625           0 :   RefreshMediaElementsVolume();
    4626           0 :   return NS_OK;
    4627             : }
    4628             : 
    4629             : void
    4630           0 : nsPIDOMWindowOuter::RefreshMediaElementsVolume()
    4631             : {
    4632           0 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
    4633           0 :   if (service) {
    4634           0 :     service->RefreshAgentsVolume(GetOuterWindow());
    4635             :   }
    4636           0 : }
    4637             : 
    4638             : void
    4639           4 : nsPIDOMWindowOuter::RefreshMediaElementsSuspend(SuspendTypes aSuspend)
    4640             : {
    4641           8 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
    4642           4 :   if (service) {
    4643           4 :     service->RefreshAgentsSuspend(GetOuterWindow(), aSuspend);
    4644             :   }
    4645           4 : }
    4646             : 
    4647             : bool
    4648           4 : nsPIDOMWindowOuter::IsDisposableSuspend(SuspendTypes aSuspend) const
    4649             : {
    4650           4 :   return (aSuspend == nsISuspendedTypes::SUSPENDED_PAUSE_DISPOSABLE ||
    4651           4 :           aSuspend == nsISuspendedTypes::SUSPENDED_STOP_DISPOSABLE);
    4652             : }
    4653             : 
    4654             : void
    4655           0 : nsPIDOMWindowOuter::SetServiceWorkersTestingEnabled(bool aEnabled)
    4656             : {
    4657             :   // Devtools should only be setting this on the top level window.  Its
    4658             :   // ok if devtools clears the flag on clean up of nested windows, though.
    4659             :   // It will have no affect.
    4660             : #ifdef DEBUG
    4661           0 :   nsCOMPtr<nsPIDOMWindowOuter> topWindow = GetScriptableTop();
    4662           0 :   MOZ_ASSERT_IF(aEnabled, this == topWindow);
    4663             : #endif
    4664           0 :   mServiceWorkersTestingEnabled = aEnabled;
    4665           0 : }
    4666             : 
    4667             : bool
    4668           0 : nsPIDOMWindowOuter::GetServiceWorkersTestingEnabled()
    4669             : {
    4670             :   // Automatically get this setting from the top level window so that nested
    4671             :   // iframes get the correct devtools setting.
    4672           0 :   nsCOMPtr<nsPIDOMWindowOuter> topWindow = GetScriptableTop();
    4673           0 :   if (!topWindow) {
    4674           0 :     return false;
    4675             :   }
    4676           0 :   return topWindow->mServiceWorkersTestingEnabled;
    4677             : }
    4678             : 
    4679             : bool
    4680           0 : nsPIDOMWindowInner::GetAudioCaptured() const
    4681             : {
    4682           0 :   MOZ_ASSERT(IsInnerWindow());
    4683           0 :   return mAudioCaptured;
    4684             : }
    4685             : 
    4686             : nsresult
    4687           0 : nsPIDOMWindowInner::SetAudioCapture(bool aCapture)
    4688             : {
    4689           0 :   MOZ_ASSERT(IsInnerWindow());
    4690             : 
    4691           0 :   mAudioCaptured = aCapture;
    4692             : 
    4693           0 :   RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
    4694           0 :   if (service) {
    4695           0 :     service->SetWindowAudioCaptured(GetOuterWindow(), mWindowID, aCapture);
    4696             :   }
    4697             : 
    4698           0 :   return NS_OK;
    4699             : }
    4700             : 
    4701             : // nsISpeechSynthesisGetter
    4702             : 
    4703             : #ifdef MOZ_WEBSPEECH
    4704             : SpeechSynthesis*
    4705           0 : nsGlobalWindow::GetSpeechSynthesis(ErrorResult& aError)
    4706             : {
    4707           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    4708             : 
    4709           0 :   if (!mSpeechSynthesis) {
    4710           0 :     mSpeechSynthesis = new SpeechSynthesis(AsInner());
    4711             :   }
    4712             : 
    4713           0 :   return mSpeechSynthesis;
    4714             : }
    4715             : 
    4716             : bool
    4717           0 : nsGlobalWindow::HasActiveSpeechSynthesis()
    4718             : {
    4719           0 :   MOZ_ASSERT(IsInnerWindow());
    4720             : 
    4721           0 :   if (mSpeechSynthesis) {
    4722           0 :     return !mSpeechSynthesis->HasEmptyQueue();
    4723             :   }
    4724             : 
    4725           0 :   return false;
    4726             : }
    4727             : 
    4728             : #endif
    4729             : 
    4730             : already_AddRefed<nsPIDOMWindowOuter>
    4731         184 : nsGlobalWindow::GetParentOuter()
    4732             : {
    4733         184 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    4734             : 
    4735         184 :   if (!mDocShell) {
    4736           0 :     return nullptr;
    4737             :   }
    4738             : 
    4739         368 :   nsCOMPtr<nsPIDOMWindowOuter> parent;
    4740         184 :   if (mDocShell->GetIsMozBrowser()) {
    4741           0 :     parent = AsOuter();
    4742             :   } else {
    4743         184 :     parent = GetParent();
    4744             :   }
    4745             : 
    4746         184 :   return parent.forget();
    4747             : }
    4748             : 
    4749             : already_AddRefed<nsPIDOMWindowOuter>
    4750           0 : nsGlobalWindow::GetParent(ErrorResult& aError)
    4751             : {
    4752           0 :   FORWARD_TO_OUTER_OR_THROW(GetParentOuter, (), aError, nullptr);
    4753             : }
    4754             : 
    4755             : /**
    4756             :  * GetScriptableParent is called when script reads window.parent.
    4757             :  *
    4758             :  * In contrast to GetRealParent, GetScriptableParent respects <iframe
    4759             :  * mozbrowser> boundaries, so if |this| is contained by an <iframe
    4760             :  * mozbrowser>, we will return |this| as its own parent.
    4761             :  */
    4762             : nsPIDOMWindowOuter*
    4763         184 : nsGlobalWindow::GetScriptableParent()
    4764             : {
    4765         184 :   FORWARD_TO_OUTER(GetScriptableParent, (), nullptr);
    4766             : 
    4767         368 :   nsCOMPtr<nsPIDOMWindowOuter> parent = GetParentOuter();
    4768         184 :   return parent.get();
    4769             : }
    4770             : 
    4771             : /**
    4772             :  * Behavies identically to GetScriptableParent extept that it returns null
    4773             :  * if GetScriptableParent would return this window.
    4774             :  */
    4775             : nsPIDOMWindowOuter*
    4776          24 : nsGlobalWindow::GetScriptableParentOrNull()
    4777             : {
    4778          24 :   FORWARD_TO_OUTER(GetScriptableParentOrNull, (), nullptr);
    4779             : 
    4780          24 :   nsPIDOMWindowOuter* parent = GetScriptableParent();
    4781          24 :   return (Cast(parent) == this) ? nullptr : parent;
    4782             : }
    4783             : 
    4784             : /**
    4785             :  * nsPIDOMWindow::GetParent (when called from C++) is just a wrapper around
    4786             :  * GetRealParent.
    4787             :  */
    4788             : already_AddRefed<nsPIDOMWindowOuter>
    4789         315 : nsGlobalWindow::GetParent()
    4790             : {
    4791         315 :   MOZ_ASSERT(IsOuterWindow());
    4792             : 
    4793         315 :   if (!mDocShell) {
    4794           0 :     return nullptr;
    4795             :   }
    4796             : 
    4797         630 :   nsCOMPtr<nsIDocShell> parent;
    4798         315 :   mDocShell->GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent));
    4799             : 
    4800         315 :   if (parent) {
    4801          26 :     nsCOMPtr<nsPIDOMWindowOuter> win = parent->GetWindow();
    4802          13 :     return win.forget();
    4803             :   }
    4804             : 
    4805         604 :   nsCOMPtr<nsPIDOMWindowOuter> win(AsOuter());
    4806         302 :   return win.forget();
    4807             : }
    4808             : 
    4809             : static nsresult
    4810         172 : GetTopImpl(nsGlobalWindow* aWin, nsPIDOMWindowOuter** aTop, bool aScriptable)
    4811             : {
    4812         172 :   *aTop = nullptr;
    4813             : 
    4814             :   // Walk up the parent chain.
    4815             : 
    4816         344 :   nsCOMPtr<nsPIDOMWindowOuter> prevParent = aWin->AsOuter();
    4817         344 :   nsCOMPtr<nsPIDOMWindowOuter> parent = aWin->AsOuter();
    4818         181 :   do {
    4819         181 :     if (!parent) {
    4820           0 :       break;
    4821             :     }
    4822             : 
    4823         181 :     prevParent = parent;
    4824             : 
    4825         362 :     nsCOMPtr<nsPIDOMWindowOuter> newParent;
    4826         181 :     if (aScriptable) {
    4827          87 :       newParent = parent->GetScriptableParent();
    4828             :     }
    4829             :     else {
    4830          94 :       newParent = parent->GetParent();
    4831             :     }
    4832             : 
    4833         181 :     parent = newParent;
    4834             : 
    4835             :   } while (parent != prevParent);
    4836             : 
    4837         172 :   if (parent) {
    4838         172 :     parent.swap(*aTop);
    4839             :   }
    4840             : 
    4841         344 :   return NS_OK;
    4842             : }
    4843             : 
    4844             : /**
    4845             :  * GetScriptableTop is called when script reads window.top.
    4846             :  *
    4847             :  * In contrast to GetRealTop, GetScriptableTop respects <iframe mozbrowser>
    4848             :  * boundaries.  If we encounter a window owned by an <iframe mozbrowser> while
    4849             :  * walking up the window hierarchy, we'll stop and return that window.
    4850             :  */
    4851             : nsPIDOMWindowOuter*
    4852         103 : nsGlobalWindow::GetScriptableTop()
    4853             : {
    4854         103 :   FORWARD_TO_OUTER(GetScriptableTop, (), nullptr);
    4855         160 :   nsCOMPtr<nsPIDOMWindowOuter> window;
    4856          80 :   GetTopImpl(this, getter_AddRefs(window), /* aScriptable = */ true);
    4857          80 :   return window.get();
    4858             : }
    4859             : 
    4860             : already_AddRefed<nsPIDOMWindowOuter>
    4861          92 : nsGlobalWindow::GetTop()
    4862             : {
    4863          92 :   MOZ_ASSERT(IsOuterWindow());
    4864         184 :   nsCOMPtr<nsPIDOMWindowOuter> window;
    4865          92 :   GetTopImpl(this, getter_AddRefs(window), /* aScriptable = */ false);
    4866         184 :   return window.forget();
    4867             : }
    4868             : 
    4869             : void
    4870           0 : nsGlobalWindow::GetContentOuter(JSContext* aCx,
    4871             :                                 JS::MutableHandle<JSObject*> aRetval,
    4872             :                                 CallerType aCallerType,
    4873             :                                 ErrorResult& aError)
    4874             : {
    4875           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    4876             : 
    4877             :   nsCOMPtr<nsPIDOMWindowOuter> content =
    4878           0 :     GetContentInternal(aError, aCallerType);
    4879           0 :   if (aError.Failed()) {
    4880           0 :     return;
    4881             :   }
    4882             : 
    4883           0 :   if (content) {
    4884           0 :     JS::Rooted<JS::Value> val(aCx);
    4885           0 :     aError = nsContentUtils::WrapNative(aCx, content, &val);
    4886           0 :     if (aError.Failed()) {
    4887           0 :       return;
    4888             :     }
    4889             : 
    4890           0 :     aRetval.set(&val.toObject());
    4891           0 :     return;
    4892             :   }
    4893             : 
    4894           0 :   aRetval.set(nullptr);
    4895           0 :   return;
    4896             : }
    4897             : 
    4898             : void
    4899           0 : nsGlobalWindow::GetContent(JSContext* aCx,
    4900             :                            JS::MutableHandle<JSObject*> aRetval,
    4901             :                            CallerType aCallerType,
    4902             :                            ErrorResult& aError)
    4903             : {
    4904           0 :   FORWARD_TO_OUTER_OR_THROW(GetContentOuter,
    4905             :                             (aCx, aRetval, aCallerType, aError), aError, );
    4906             : }
    4907             : 
    4908             : already_AddRefed<nsPIDOMWindowOuter>
    4909           0 : nsGlobalWindow::GetContentInternal(ErrorResult& aError, CallerType aCallerType)
    4910             : {
    4911           0 :   MOZ_ASSERT(IsOuterWindow());
    4912             : 
    4913             :   // First check for a named frame named "content"
    4914             :   nsCOMPtr<nsPIDOMWindowOuter> domWindow =
    4915           0 :     GetChildWindow(NS_LITERAL_STRING("content"));
    4916           0 :   if (domWindow) {
    4917           0 :     return domWindow.forget();
    4918             :   }
    4919             : 
    4920             :   // If we're contained in <iframe mozbrowser>, then GetContent is the same as
    4921             :   // window.top.
    4922           0 :   if (mDocShell && mDocShell->GetIsInMozBrowser()) {
    4923           0 :     return GetTopOuter();
    4924             :   }
    4925             : 
    4926           0 :   nsCOMPtr<nsIDocShellTreeItem> primaryContent;
    4927           0 :   if (aCallerType != CallerType::System) {
    4928             :     // If we're called by non-chrome code, make sure we don't return
    4929             :     // the primary content window if the calling tab is hidden. In
    4930             :     // such a case we return the same-type root in the hidden tab,
    4931             :     // which is "good enough", for now.
    4932           0 :     nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(mDocShell));
    4933             : 
    4934           0 :     if (baseWin) {
    4935           0 :       bool visible = false;
    4936           0 :       baseWin->GetVisibility(&visible);
    4937             : 
    4938           0 :       if (!visible) {
    4939           0 :         mDocShell->GetSameTypeRootTreeItem(getter_AddRefs(primaryContent));
    4940             :       }
    4941             :     }
    4942             :   }
    4943             : 
    4944           0 :   if (!primaryContent) {
    4945           0 :     nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
    4946           0 :     if (!treeOwner) {
    4947           0 :       aError.Throw(NS_ERROR_FAILURE);
    4948           0 :       return nullptr;
    4949             :     }
    4950             : 
    4951           0 :     treeOwner->GetPrimaryContentShell(getter_AddRefs(primaryContent));
    4952             :   }
    4953             : 
    4954           0 :   if (!primaryContent) {
    4955           0 :     return nullptr;
    4956             :   }
    4957             : 
    4958           0 :   domWindow = primaryContent->GetWindow();
    4959           0 :   return domWindow.forget();
    4960             : }
    4961             : 
    4962             : MozSelfSupport*
    4963           0 : nsGlobalWindow::GetMozSelfSupport(ErrorResult& aError)
    4964             : {
    4965           0 :   MOZ_ASSERT(IsInnerWindow());
    4966             : 
    4967           0 :   if (mMozSelfSupport) {
    4968           0 :     return mMozSelfSupport;
    4969             :   }
    4970             : 
    4971             :   // We're called from JS and want to use out existing JSContext (and,
    4972             :   // importantly, its compartment!) here.
    4973           0 :   AutoJSContext cx;
    4974           0 :   GlobalObject global(cx, FastGetGlobalJSObject());
    4975           0 :   mMozSelfSupport = MozSelfSupport::Constructor(global, cx, aError);
    4976           0 :   return mMozSelfSupport;
    4977             : }
    4978             : 
    4979             : nsresult
    4980           0 : nsGlobalWindow::GetPrompter(nsIPrompt** aPrompt)
    4981             : {
    4982           0 :   if (IsInnerWindow()) {
    4983           0 :     nsGlobalWindow* outer = GetOuterWindowInternal();
    4984           0 :     if (!outer) {
    4985           0 :       NS_WARNING("No outer window available!");
    4986           0 :       return NS_ERROR_NOT_INITIALIZED;
    4987             :     }
    4988           0 :     return outer->GetPrompter(aPrompt);
    4989             :   }
    4990             : 
    4991           0 :   if (!mDocShell)
    4992           0 :     return NS_ERROR_FAILURE;
    4993             : 
    4994           0 :   nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mDocShell));
    4995           0 :   NS_ENSURE_TRUE(prompter, NS_ERROR_NO_INTERFACE);
    4996             : 
    4997           0 :   prompter.forget(aPrompt);
    4998           0 :   return NS_OK;
    4999             : }
    5000             : 
    5001             : BarProp*
    5002           0 : nsGlobalWindow::GetMenubar(ErrorResult& aError)
    5003             : {
    5004           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5005             : 
    5006           0 :   if (!mMenubar) {
    5007           0 :     mMenubar = new MenubarProp(this);
    5008             :   }
    5009             : 
    5010           0 :   return mMenubar;
    5011             : }
    5012             : 
    5013             : BarProp*
    5014           5 : nsGlobalWindow::GetToolbar(ErrorResult& aError)
    5015             : {
    5016           5 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5017             : 
    5018           5 :   if (!mToolbar) {
    5019           1 :     mToolbar = new ToolbarProp(this);
    5020             :   }
    5021             : 
    5022           5 :   return mToolbar;
    5023             : }
    5024             : 
    5025             : BarProp*
    5026           0 : nsGlobalWindow::GetLocationbar(ErrorResult& aError)
    5027             : {
    5028           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5029             : 
    5030           0 :   if (!mLocationbar) {
    5031           0 :     mLocationbar = new LocationbarProp(this);
    5032             :   }
    5033           0 :   return mLocationbar;
    5034             : }
    5035             : 
    5036             : BarProp*
    5037           0 : nsGlobalWindow::GetPersonalbar(ErrorResult& aError)
    5038             : {
    5039           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5040             : 
    5041           0 :   if (!mPersonalbar) {
    5042           0 :     mPersonalbar = new PersonalbarProp(this);
    5043             :   }
    5044           0 :   return mPersonalbar;
    5045             : }
    5046             : 
    5047             : BarProp*
    5048           0 : nsGlobalWindow::GetStatusbar(ErrorResult& aError)
    5049             : {
    5050           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5051             : 
    5052           0 :   if (!mStatusbar) {
    5053           0 :     mStatusbar = new StatusbarProp(this);
    5054             :   }
    5055           0 :   return mStatusbar;
    5056             : }
    5057             : 
    5058             : BarProp*
    5059           0 : nsGlobalWindow::GetScrollbars(ErrorResult& aError)
    5060             : {
    5061           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5062             : 
    5063           0 :   if (!mScrollbars) {
    5064           0 :     mScrollbars = new ScrollbarsProp(this);
    5065             :   }
    5066             : 
    5067           0 :   return mScrollbars;
    5068             : }
    5069             : 
    5070             : bool
    5071           6 : nsGlobalWindow::GetClosedOuter()
    5072             : {
    5073           6 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5074             : 
    5075             :   // If someone called close(), or if we don't have a docshell, we're closed.
    5076           6 :   return mIsClosed || !mDocShell;
    5077             : }
    5078             : 
    5079             : bool
    5080           6 : nsGlobalWindow::GetClosed(ErrorResult& aError)
    5081             : {
    5082           6 :   FORWARD_TO_OUTER_OR_THROW(GetClosedOuter, (), aError, false);
    5083             : }
    5084             : 
    5085             : bool
    5086           0 : nsGlobalWindow::Closed()
    5087             : {
    5088           0 :   MOZ_ASSERT(IsOuterWindow());
    5089             : 
    5090           0 :   return GetClosedOuter();
    5091             : }
    5092             : 
    5093             : nsDOMWindowList*
    5094         384 : nsGlobalWindow::GetWindowList()
    5095             : {
    5096         384 :   MOZ_ASSERT(IsOuterWindow());
    5097             : 
    5098         384 :   if (!mFrames && mDocShell) {
    5099           2 :     mFrames = new nsDOMWindowList(mDocShell);
    5100             :   }
    5101             : 
    5102         384 :   return mFrames;
    5103             : }
    5104             : 
    5105             : already_AddRefed<nsIDOMWindowCollection>
    5106           0 : nsGlobalWindow::GetFrames()
    5107             : {
    5108           0 :   FORWARD_TO_OUTER(GetFrames, (), nullptr);
    5109             : 
    5110           0 :   nsCOMPtr<nsIDOMWindowCollection> frames = GetWindowList();
    5111           0 :   return frames.forget();
    5112             : }
    5113             : 
    5114             : already_AddRefed<nsPIDOMWindowOuter>
    5115           0 : nsGlobalWindow::IndexedGetterOuter(uint32_t aIndex)
    5116             : {
    5117           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5118             : 
    5119           0 :   nsDOMWindowList* windows = GetWindowList();
    5120           0 :   NS_ENSURE_TRUE(windows, nullptr);
    5121             : 
    5122           0 :   return windows->IndexedGetter(aIndex);
    5123             : }
    5124             : 
    5125             : already_AddRefed<nsPIDOMWindowOuter>
    5126           0 : nsGlobalWindow::IndexedGetter(uint32_t aIndex)
    5127             : {
    5128           0 :   FORWARD_TO_OUTER(IndexedGetterOuter, (aIndex), nullptr);
    5129           0 :   MOZ_CRASH();
    5130             : }
    5131             : 
    5132             : bool
    5133        3150 : nsGlobalWindow::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
    5134             :                           JS::Handle<jsid> aId,
    5135             :                           JS::MutableHandle<JS::PropertyDescriptor> aDesc)
    5136             : {
    5137        3150 :   MOZ_ASSERT(IsInnerWindow());
    5138             : 
    5139             :   // Note: Keep this in sync with MayResolve.
    5140             : 
    5141             :   // Note: The infallibleInit call in GlobalResolve depends on this check.
    5142        3150 :   if (!JSID_IS_STRING(aId)) {
    5143           0 :     return true;
    5144             :   }
    5145             : 
    5146             :   bool found;
    5147        3150 :   if (!WebIDLGlobalNameHash::DefineIfEnabled(aCx, aObj, aId, aDesc, &found)) {
    5148           0 :     return false;
    5149             :   }
    5150             : 
    5151        3150 :   if (found) {
    5152          20 :     return true;
    5153             :   }
    5154             : 
    5155        3130 :   nsresult rv = nsWindowSH::GlobalResolve(this, aCx, aObj, aId, aDesc);
    5156        3130 :   if (NS_FAILED(rv)) {
    5157           0 :     return Throw(aCx, rv);
    5158             :   }
    5159             : 
    5160        3130 :   return true;
    5161             : }
    5162             : 
    5163             : /* static */
    5164             : bool
    5165           8 : nsGlobalWindow::MayResolve(jsid aId)
    5166             : {
    5167             :   // Note: This function does not fail and may not have any side-effects.
    5168             :   // Note: Keep this in sync with DoResolve.
    5169           8 :   if (!JSID_IS_STRING(aId)) {
    5170           0 :     return false;
    5171             :   }
    5172             : 
    5173           8 :   if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_COMPONENTS)) {
    5174           0 :     return true;
    5175             :   }
    5176             : 
    5177          32 :   if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS) ||
    5178          24 :       aId == XPCJSRuntime::Get()->GetStringID(XPCJSContext::IDX_CONTROLLERS_CLASS)) {
    5179             :     // We only resolve .controllers/.Controllers in release builds and on non-chrome
    5180             :     // windows, but let's not worry about any of that stuff.
    5181           0 :     return true;
    5182             :   }
    5183             : 
    5184           8 :   if (WebIDLGlobalNameHash::MayResolve(aId)) {
    5185           8 :     return true;
    5186             :   }
    5187             : 
    5188           0 :   nsScriptNameSpaceManager *nameSpaceManager = PeekNameSpaceManager();
    5189           0 :   if (!nameSpaceManager) {
    5190             :     // Really shouldn't happen.  Fail safe.
    5191           0 :     return true;
    5192             :   }
    5193             : 
    5194           0 :   nsAutoString name;
    5195           0 :   AssignJSFlatString(name, JSID_TO_FLAT_STRING(aId));
    5196             : 
    5197           0 :   return nameSpaceManager->LookupName(name);
    5198             : }
    5199             : 
    5200             : void
    5201           0 : nsGlobalWindow::GetOwnPropertyNames(JSContext* aCx, JS::AutoIdVector& aNames,
    5202             :                                     bool aEnumerableOnly, ErrorResult& aRv)
    5203             : {
    5204           0 :   if (aEnumerableOnly) {
    5205             :     // The names we would return from here get defined on the window via one of
    5206             :     // two codepaths.  The ones coming from the WebIDLGlobalNameHash will end up
    5207             :     // in the DefineConstructor function in BindingUtils, which always defines
    5208             :     // things as non-enumerable.  The ones coming from the script namespace
    5209             :     // manager get defined by nsDOMClassInfo::PostCreatePrototype calling
    5210             :     // ResolvePrototype and using the resulting descriptot to define the
    5211             :     // property.  ResolvePrototype always passes 0 to the FillPropertyDescriptor
    5212             :     // for the property attributes, so all those are non-enumerable as well.
    5213             :     //
    5214             :     // So in the aEnumerableOnly case we have nothing to do.
    5215           0 :     return;
    5216             :   }
    5217             : 
    5218           0 :   MOZ_ASSERT(IsInnerWindow());
    5219             :   // "Components" is marked as enumerable but only resolved on demand :-/.
    5220             :   //aNames.AppendElement(NS_LITERAL_STRING("Components"));
    5221             : 
    5222           0 :   nsScriptNameSpaceManager* nameSpaceManager = GetNameSpaceManager();
    5223           0 :   if (nameSpaceManager) {
    5224           0 :     JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
    5225             : 
    5226             :     // There are actually two ways we can get called here: For normal
    5227             :     // enumeration or for Xray enumeration.  In the latter case, we want to
    5228             :     // return all possible WebIDL names, because we don't really support
    5229             :     // deleting these names off our Xray; trying to resolve them will just make
    5230             :     // them come back.  In the former case, we want to avoid returning deleted
    5231             :     // names.  But the JS engine already knows about the non-deleted
    5232             :     // already-resolved names, so we can just return the so-far-unresolved ones.
    5233             :     //
    5234             :     // We can tell which case we're in by whether aCx is in our wrapper's
    5235             :     // compartment.  If not, we're in the Xray case.
    5236             :     WebIDLGlobalNameHash::NameType nameType =
    5237           0 :       js::IsObjectInContextCompartment(wrapper, aCx) ?
    5238             :         WebIDLGlobalNameHash::UnresolvedNamesOnly :
    5239           0 :         WebIDLGlobalNameHash::AllNames;
    5240           0 :     if (!WebIDLGlobalNameHash::GetNames(aCx, wrapper, nameType, aNames)) {
    5241           0 :       aRv.NoteJSContextException(aCx);
    5242             :     }
    5243             : 
    5244           0 :     for (auto i = nameSpaceManager->GlobalNameIter(); !i.Done(); i.Next()) {
    5245           0 :       const GlobalNameMapEntry* entry = i.Get();
    5246           0 :       if (nsWindowSH::NameStructEnabled(aCx, this, entry->mKey,
    5247             :                                         entry->mGlobalName)) {
    5248             :         // Just append all of these; even if they get deleted our resolve hook
    5249             :         // just goes ahead and recreates them.
    5250           0 :         JSString* str = JS_AtomizeUCStringN(aCx,
    5251             :                                             entry->mKey.BeginReading(),
    5252           0 :                                             entry->mKey.Length());
    5253           0 :         if (!str || !aNames.append(NON_INTEGER_ATOM_TO_JSID(str))) {
    5254           0 :           aRv.NoteJSContextException(aCx);
    5255           0 :           return;
    5256             :         }
    5257             :       }
    5258             :     }
    5259             :   }
    5260             : }
    5261             : 
    5262             : /* static */ bool
    5263          28 : nsGlobalWindow::IsPrivilegedChromeWindow(JSContext* aCx, JSObject* aObj)
    5264             : {
    5265             :   // For now, have to deal with XPConnect objects here.
    5266          44 :   return xpc::WindowOrNull(aObj)->IsChromeWindow() &&
    5267          44 :          nsContentUtils::ObjectPrincipal(aObj) == nsContentUtils::GetSystemPrincipal();
    5268             : }
    5269             : 
    5270             : /* static */ bool
    5271           7 : nsGlobalWindow::IsShowModalDialogEnabled(JSContext*, JSObject*)
    5272             : {
    5273             :   static bool sAddedPrefCache = false;
    5274             :   static bool sIsDisabled;
    5275             :   static const char sShowModalDialogPref[] = "dom.disable_window_showModalDialog";
    5276             : 
    5277           7 :   if (!sAddedPrefCache) {
    5278           2 :     Preferences::AddBoolVarCache(&sIsDisabled, sShowModalDialogPref, false);
    5279           2 :     sAddedPrefCache = true;
    5280             :   }
    5281             : 
    5282           7 :   return !sIsDisabled && !XRE_IsContentProcess();
    5283             : }
    5284             : 
    5285             : /* static */ bool
    5286           7 : nsGlobalWindow::IsRequestIdleCallbackEnabled(JSContext* aCx, JSObject* aObj)
    5287             : {
    5288             :   // The requestIdleCallback should always be enabled for system code.
    5289           7 :   return nsContentUtils::RequestIdleCallbackEnabled() ||
    5290           7 :          nsContentUtils::IsSystemCaller(aCx);
    5291             : }
    5292             : 
    5293             : nsIDOMOfflineResourceList*
    5294           0 : nsGlobalWindow::GetApplicationCache(ErrorResult& aError)
    5295             : {
    5296           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5297             : 
    5298           0 :   if (!mApplicationCache) {
    5299           0 :     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(GetDocShell()));
    5300           0 :     if (!webNav || !mDoc) {
    5301           0 :       aError.Throw(NS_ERROR_FAILURE);
    5302           0 :       return nullptr;
    5303             :     }
    5304             : 
    5305           0 :     nsCOMPtr<nsIURI> uri;
    5306           0 :     aError = webNav->GetCurrentURI(getter_AddRefs(uri));
    5307           0 :     if (aError.Failed()) {
    5308           0 :       return nullptr;
    5309             :     }
    5310             : 
    5311           0 :     nsCOMPtr<nsIURI> manifestURI;
    5312           0 :     nsContentUtils::GetOfflineAppManifest(mDoc, getter_AddRefs(manifestURI));
    5313             : 
    5314             :     RefPtr<nsDOMOfflineResourceList> applicationCache =
    5315           0 :       new nsDOMOfflineResourceList(manifestURI, uri, mDoc->NodePrincipal(),
    5316           0 :                                    AsInner());
    5317             : 
    5318           0 :     applicationCache->Init();
    5319             : 
    5320           0 :     mApplicationCache = applicationCache;
    5321             :   }
    5322             : 
    5323           0 :   return mApplicationCache;
    5324             : }
    5325             : 
    5326             : already_AddRefed<nsIDOMOfflineResourceList>
    5327           0 : nsGlobalWindow::GetApplicationCache()
    5328             : {
    5329           0 :   FORWARD_TO_INNER(GetApplicationCache, (), nullptr);
    5330             : 
    5331           0 :   ErrorResult dummy;
    5332             :   nsCOMPtr<nsIDOMOfflineResourceList> applicationCache =
    5333           0 :     GetApplicationCache(dummy);
    5334           0 :   dummy.SuppressException();
    5335           0 :   return applicationCache.forget();
    5336             : }
    5337             : 
    5338             : Crypto*
    5339           0 : nsGlobalWindow::GetCrypto(ErrorResult& aError)
    5340             : {
    5341           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5342             : 
    5343           0 :   if (!mCrypto) {
    5344           0 :     mCrypto = new Crypto();
    5345           0 :     mCrypto->Init(this);
    5346             :   }
    5347           0 :   return mCrypto;
    5348             : }
    5349             : 
    5350             : mozilla::dom::U2F*
    5351           0 : nsGlobalWindow::GetU2f(ErrorResult& aError)
    5352             : {
    5353           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    5354             : 
    5355           0 :   if (!mU2F) {
    5356           0 :     RefPtr<U2F> u2f = new U2F();
    5357           0 :     u2f->Init(AsInner(), aError);
    5358           0 :     if (NS_WARN_IF(aError.Failed())) {
    5359           0 :       return nullptr;
    5360             :     }
    5361             : 
    5362           0 :     mU2F = u2f;
    5363             :   }
    5364           0 :   return mU2F;
    5365             : }
    5366             : 
    5367             : nsIControllers*
    5368          15 : nsGlobalWindow::GetControllersOuter(ErrorResult& aError)
    5369             : {
    5370          15 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5371             : 
    5372          15 :   if (!mControllers) {
    5373             :     nsresult rv;
    5374           2 :     mControllers = do_CreateInstance(kXULControllersCID, &rv);
    5375           2 :     if (NS_FAILED(rv)) {
    5376           0 :       aError.Throw(rv);
    5377           0 :       return nullptr;
    5378             :     }
    5379             : 
    5380             :     // Add in the default controller
    5381           4 :     nsCOMPtr<nsIController> controller = do_CreateInstance(
    5382           4 :                                NS_WINDOWCONTROLLER_CONTRACTID, &rv);
    5383           2 :     if (NS_FAILED(rv)) {
    5384           0 :       aError.Throw(rv);
    5385           0 :       return nullptr;
    5386             :     }
    5387             : 
    5388           2 :     mControllers->InsertControllerAt(0, controller);
    5389           4 :     nsCOMPtr<nsIControllerContext> controllerContext = do_QueryInterface(controller);
    5390           2 :     if (!controllerContext) {
    5391           0 :       aError.Throw(NS_ERROR_FAILURE);
    5392           0 :       return nullptr;
    5393             :     }
    5394             : 
    5395           2 :     controllerContext->SetCommandContext(static_cast<nsIDOMWindow*>(this));
    5396             :   }
    5397             : 
    5398          15 :   return mControllers;
    5399             : }
    5400             : 
    5401             : nsIControllers*
    5402          15 : nsGlobalWindow::GetControllers(ErrorResult& aError)
    5403             : {
    5404          15 :   FORWARD_TO_OUTER_OR_THROW(GetControllersOuter, (aError), aError, nullptr);
    5405             : }
    5406             : 
    5407             : nsresult
    5408          30 : nsGlobalWindow::GetControllers(nsIControllers** aResult)
    5409             : {
    5410          30 :   FORWARD_TO_INNER(GetControllers, (aResult), NS_ERROR_UNEXPECTED);
    5411             : 
    5412          30 :   ErrorResult rv;
    5413          30 :   nsCOMPtr<nsIControllers> controllers = GetControllers(rv);
    5414          15 :   controllers.forget(aResult);
    5415             : 
    5416          15 :   return rv.StealNSResult();
    5417             : }
    5418             : 
    5419             : nsPIDOMWindowOuter*
    5420          19 : nsGlobalWindow::GetSanitizedOpener(nsPIDOMWindowOuter* aOpener)
    5421             : {
    5422          19 :   if (!aOpener) {
    5423          19 :     return nullptr;
    5424             :   }
    5425             : 
    5426           0 :   nsGlobalWindow* win = nsGlobalWindow::Cast(aOpener);
    5427             : 
    5428             :   // First, ensure that we're not handing back a chrome window to content:
    5429           0 :   if (win->IsChromeWindow()) {
    5430           0 :     return nullptr;
    5431             :   }
    5432             : 
    5433             :   // We don't want to reveal the opener if the opener is a mail window,
    5434             :   // because opener can be used to spoof the contents of a message (bug 105050).
    5435             :   // So, we look in the opener's root docshell to see if it's a mail window.
    5436           0 :   nsCOMPtr<nsIDocShell> openerDocShell = aOpener->GetDocShell();
    5437             : 
    5438           0 :   if (openerDocShell) {
    5439           0 :     nsCOMPtr<nsIDocShellTreeItem> openerRootItem;
    5440           0 :     openerDocShell->GetRootTreeItem(getter_AddRefs(openerRootItem));
    5441           0 :     nsCOMPtr<nsIDocShell> openerRootDocShell(do_QueryInterface(openerRootItem));
    5442           0 :     if (openerRootDocShell) {
    5443             :       uint32_t appType;
    5444           0 :       nsresult rv = openerRootDocShell->GetAppType(&appType);
    5445           0 :       if (NS_SUCCEEDED(rv) && appType != nsIDocShell::APP_TYPE_MAIL) {
    5446           0 :         return aOpener;
    5447             :       }
    5448             :     }
    5449             :   }
    5450             : 
    5451           0 :   return nullptr;
    5452             : }
    5453             : 
    5454             : nsPIDOMWindowOuter*
    5455           0 : nsGlobalWindow::GetOpenerWindowOuter()
    5456             : {
    5457           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5458             : 
    5459           0 :   nsCOMPtr<nsPIDOMWindowOuter> opener = do_QueryReferent(mOpener);
    5460             : 
    5461           0 :   if (!opener) {
    5462           0 :     return nullptr;
    5463             :   }
    5464             : 
    5465             :   // First, check if we were called from a privileged chrome script
    5466           0 :   if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
    5467             :     // Catch the case where we're chrome but the opener is not...
    5468           0 :     if (GetPrincipal() == nsContentUtils::GetSystemPrincipal() &&
    5469           0 :         nsGlobalWindow::Cast(opener)->GetPrincipal() != nsContentUtils::GetSystemPrincipal()) {
    5470           0 :       return nullptr;
    5471             :     }
    5472           0 :     return opener;
    5473             :   }
    5474             : 
    5475           0 :   return GetSanitizedOpener(opener);
    5476             : }
    5477             : 
    5478             : nsPIDOMWindowOuter*
    5479           0 : nsGlobalWindow::GetOpenerWindow(ErrorResult& aError)
    5480             : {
    5481           0 :   FORWARD_TO_OUTER_OR_THROW(GetOpenerWindowOuter, (), aError, nullptr);
    5482             : }
    5483             : 
    5484             : void
    5485           0 : nsGlobalWindow::GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
    5486             :                           ErrorResult& aError)
    5487             : {
    5488           0 :   MOZ_ASSERT(IsInnerWindow());
    5489             : 
    5490           0 :   nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindow(aError);
    5491           0 :   if (aError.Failed() || !opener) {
    5492           0 :     aRetval.setNull();
    5493           0 :     return;
    5494             :   }
    5495             : 
    5496           0 :   aError = nsContentUtils::WrapNative(aCx, opener, aRetval);
    5497             : }
    5498             : 
    5499             : already_AddRefed<nsPIDOMWindowOuter>
    5500           0 : nsGlobalWindow::GetOpener()
    5501             : {
    5502           0 :   FORWARD_TO_OUTER(GetOpener, (), nullptr);
    5503             : 
    5504           0 :   nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpenerWindowOuter();
    5505           0 :   return opener.forget();
    5506             : }
    5507             : 
    5508             : void
    5509           0 : nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
    5510             :                           ErrorResult& aError)
    5511             : {
    5512             :   // Check if we were called from a privileged chrome script.  If not, and if
    5513             :   // aOpener is not null, just define aOpener on our inner window's JS object,
    5514             :   // wrapped into the current compartment so that for Xrays we define on the
    5515             :   // Xray expando object, but don't set it on the outer window, so that it'll
    5516             :   // get reset on navigation.  This is just like replaceable properties, but
    5517             :   // we're not quite readonly.
    5518           0 :   if (!aOpener.isNull() && !nsContentUtils::IsCallerChrome()) {
    5519           0 :     RedefineProperty(aCx, "opener", aOpener, aError);
    5520           0 :     return;
    5521             :   }
    5522             : 
    5523           0 :   if (!aOpener.isObjectOrNull()) {
    5524             :     // Chrome code trying to set some random value as opener
    5525           0 :     aError.Throw(NS_ERROR_INVALID_ARG);
    5526           0 :     return;
    5527             :   }
    5528             : 
    5529           0 :   nsPIDOMWindowInner* win = nullptr;
    5530           0 :   if (aOpener.isObject()) {
    5531           0 :     JSObject* unwrapped = js::CheckedUnwrap(&aOpener.toObject(),
    5532           0 :                                             /* stopAtWindowProxy = */ false);
    5533           0 :     if (!unwrapped) {
    5534           0 :       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
    5535           0 :       return;
    5536             :     }
    5537             : 
    5538           0 :     auto* globalWindow = xpc::WindowOrNull(unwrapped);
    5539           0 :     if (!globalWindow) {
    5540             :       // Wasn't a window
    5541           0 :       aError.Throw(NS_ERROR_INVALID_ARG);
    5542           0 :       return;
    5543             :     }
    5544             : 
    5545           0 :     win = globalWindow->AsInner();
    5546             :   }
    5547             : 
    5548           0 :   nsPIDOMWindowOuter* outer = nullptr;
    5549           0 :   if (win) {
    5550           0 :     if (!win->IsCurrentInnerWindow()) {
    5551           0 :       aError.Throw(NS_ERROR_FAILURE);
    5552           0 :       return;
    5553             :     }
    5554           0 :     outer = win->GetOuterWindow();
    5555             :   }
    5556             : 
    5557           0 :   SetOpenerWindow(outer, false);
    5558             : }
    5559             : 
    5560             : void
    5561           0 : nsGlobalWindow::GetStatusOuter(nsAString& aStatus)
    5562             : {
    5563           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5564             : 
    5565           0 :   aStatus = mStatus;
    5566           0 : }
    5567             : 
    5568             : void
    5569           0 : nsGlobalWindow::GetStatus(nsAString& aStatus, ErrorResult& aError)
    5570             : {
    5571           0 :   FORWARD_TO_OUTER_OR_THROW(GetStatusOuter, (aStatus), aError, );
    5572             : }
    5573             : 
    5574             : void
    5575           8 : nsGlobalWindow::SetStatusOuter(const nsAString& aStatus)
    5576             : {
    5577           8 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5578             : 
    5579           8 :   mStatus = aStatus;
    5580             : 
    5581             :   /*
    5582             :    * If caller is not chrome and dom.disable_window_status_change is true,
    5583             :    * prevent propagating window.status to the UI by exiting early
    5584             :    */
    5585             : 
    5586           8 :   if (!CanSetProperty("dom.disable_window_status_change")) {
    5587           0 :     return;
    5588             :   }
    5589             : 
    5590          16 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome = GetWebBrowserChrome();
    5591           8 :   if (browserChrome) {
    5592          16 :     browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,
    5593          16 :                              PromiseFlatString(aStatus).get());
    5594             :   }
    5595             : }
    5596             : 
    5597             : void
    5598           0 : nsGlobalWindow::SetStatus(const nsAString& aStatus, ErrorResult& aError)
    5599             : {
    5600           0 :   FORWARD_TO_OUTER_OR_THROW(SetStatusOuter, (aStatus), aError, );
    5601             : }
    5602             : 
    5603             : void
    5604           0 : nsGlobalWindow::GetNameOuter(nsAString& aName)
    5605             : {
    5606           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5607             : 
    5608           0 :   if (mDocShell) {
    5609           0 :     mDocShell->GetName(aName);
    5610             :   }
    5611           0 : }
    5612             : 
    5613             : void
    5614           0 : nsGlobalWindow::GetName(nsAString& aName, ErrorResult& aError)
    5615             : {
    5616           0 :   FORWARD_TO_OUTER_OR_THROW(GetNameOuter, (aName), aError, );
    5617             : }
    5618             : 
    5619             : void
    5620           0 : nsGlobalWindow::SetNameOuter(const nsAString& aName, mozilla::ErrorResult& aError)
    5621             : {
    5622           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5623             : 
    5624           0 :   if (mDocShell) {
    5625           0 :     aError = mDocShell->SetName(aName);
    5626             :   }
    5627           0 : }
    5628             : 
    5629             : void
    5630           0 : nsGlobalWindow::SetName(const nsAString& aName, mozilla::ErrorResult& aError)
    5631             : {
    5632           0 :   FORWARD_TO_OUTER_OR_THROW(SetNameOuter, (aName, aError), aError, );
    5633             : }
    5634             : 
    5635             : // Helper functions used by many methods below.
    5636             : int32_t
    5637           0 : nsGlobalWindow::DevToCSSIntPixels(int32_t px)
    5638             : {
    5639           0 :   if (!mDocShell)
    5640           0 :     return px; // assume 1:1
    5641             : 
    5642           0 :   RefPtr<nsPresContext> presContext;
    5643           0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    5644           0 :   if (!presContext)
    5645           0 :     return px;
    5646             : 
    5647           0 :   return presContext->DevPixelsToIntCSSPixels(px);
    5648             : }
    5649             : 
    5650             : int32_t
    5651           0 : nsGlobalWindow::CSSToDevIntPixels(int32_t px)
    5652             : {
    5653           0 :   if (!mDocShell)
    5654           0 :     return px; // assume 1:1
    5655             : 
    5656           0 :   RefPtr<nsPresContext> presContext;
    5657           0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    5658           0 :   if (!presContext)
    5659           0 :     return px;
    5660             : 
    5661           0 :   return presContext->CSSPixelsToDevPixels(px);
    5662             : }
    5663             : 
    5664             : nsIntSize
    5665           0 : nsGlobalWindow::DevToCSSIntPixels(nsIntSize px)
    5666             : {
    5667           0 :   if (!mDocShell)
    5668           0 :     return px; // assume 1:1
    5669             : 
    5670           0 :   RefPtr<nsPresContext> presContext;
    5671           0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    5672           0 :   if (!presContext)
    5673           0 :     return px;
    5674             : 
    5675           0 :   return nsIntSize(
    5676             :       presContext->DevPixelsToIntCSSPixels(px.width),
    5677           0 :       presContext->DevPixelsToIntCSSPixels(px.height));
    5678             : }
    5679             : 
    5680             : nsIntSize
    5681           0 : nsGlobalWindow::CSSToDevIntPixels(nsIntSize px)
    5682             : {
    5683           0 :   if (!mDocShell)
    5684           0 :     return px; // assume 1:1
    5685             : 
    5686           0 :   RefPtr<nsPresContext> presContext;
    5687           0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    5688           0 :   if (!presContext)
    5689           0 :     return px;
    5690             : 
    5691           0 :   return nsIntSize(
    5692             :     presContext->CSSPixelsToDevPixels(px.width),
    5693           0 :     presContext->CSSPixelsToDevPixels(px.height));
    5694             : }
    5695             : 
    5696             : nsresult
    5697           0 : nsGlobalWindow::GetInnerSize(CSSIntSize& aSize)
    5698             : {
    5699           0 :   MOZ_ASSERT(IsOuterWindow());
    5700             : 
    5701           0 :   EnsureSizeAndPositionUpToDate();
    5702             : 
    5703           0 :   NS_ENSURE_STATE(mDocShell);
    5704             : 
    5705           0 :   RefPtr<nsPresContext> presContext;
    5706           0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    5707           0 :   RefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
    5708             : 
    5709           0 :   if (!presContext || !presShell) {
    5710           0 :     aSize = CSSIntSize(0, 0);
    5711           0 :     return NS_OK;
    5712             :   }
    5713             : 
    5714             :   /*
    5715             :    * On platforms with resolution-based zooming, the CSS viewport
    5716             :    * and visual viewport may not be the same. The inner size should
    5717             :    * be the visual viewport, but we fall back to the CSS viewport
    5718             :    * if it is not set.
    5719             :    */
    5720           0 :   if (presShell->IsScrollPositionClampingScrollPortSizeSet()) {
    5721             :     aSize = CSSIntRect::FromAppUnitsRounded(
    5722           0 :       presShell->GetScrollPositionClampingScrollPortSize());
    5723             :   } else {
    5724           0 :     RefPtr<nsViewManager> viewManager = presShell->GetViewManager();
    5725           0 :     if (viewManager) {
    5726           0 :       viewManager->FlushDelayedResize(false);
    5727             :     }
    5728             : 
    5729             :     aSize = CSSIntRect::FromAppUnitsRounded(
    5730           0 :       presContext->GetVisibleArea().Size());
    5731             :   }
    5732           0 :   return NS_OK;
    5733             : }
    5734             : 
    5735             : int32_t
    5736           0 : nsGlobalWindow::GetInnerWidthOuter(ErrorResult& aError)
    5737             : {
    5738           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5739             : 
    5740           0 :   CSSIntSize size;
    5741           0 :   aError = GetInnerSize(size);
    5742           0 :   return size.width;
    5743             : }
    5744             : 
    5745             : int32_t
    5746           0 : nsGlobalWindow::GetInnerWidth(CallerType aCallerType, ErrorResult& aError)
    5747             : {
    5748             :   // We ignore aCallerType; we only have that argument because some other things
    5749             :   // called by GetReplaceableWindowCoord need it.  If this ever changes, fix
    5750             :   //   nsresult nsGlobalWindow::GetInnerWidth(int32_t* aInnerWidth)
    5751             :   // to actually take a useful CallerType and pass it in here.
    5752           0 :   FORWARD_TO_OUTER_OR_THROW(GetInnerWidthOuter, (aError), aError, 0);
    5753             : }
    5754             : 
    5755             : void
    5756           0 : nsGlobalWindow::GetInnerWidth(JSContext* aCx,
    5757             :                               JS::MutableHandle<JS::Value> aValue,
    5758             :                               CallerType aCallerType,
    5759             :                               ErrorResult& aError)
    5760             : {
    5761             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetInnerWidth, aValue,
    5762           0 :                             aCallerType, aError);
    5763           0 : }
    5764             : 
    5765             : nsresult
    5766           0 : nsGlobalWindow::GetInnerWidth(int32_t* aInnerWidth)
    5767             : {
    5768           0 :   FORWARD_TO_INNER(GetInnerWidth, (aInnerWidth), NS_ERROR_UNEXPECTED);
    5769             : 
    5770           0 :   ErrorResult rv;
    5771             :   // Callee doesn't care about the caller type, but play it safe.
    5772           0 :   *aInnerWidth = GetInnerWidth(CallerType::NonSystem, rv);
    5773             : 
    5774           0 :   return rv.StealNSResult();
    5775             : }
    5776             : 
    5777             : void
    5778           0 : nsGlobalWindow::SetInnerWidthOuter(int32_t aInnerWidth,
    5779             :                                    CallerType aCallerType,
    5780             :                                    ErrorResult& aError)
    5781             : {
    5782           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5783             : 
    5784           0 :   if (!mDocShell) {
    5785           0 :     aError.Throw(NS_ERROR_UNEXPECTED);
    5786           0 :     return;
    5787             :   }
    5788             : 
    5789           0 :   CheckSecurityWidthAndHeight(&aInnerWidth, nullptr, aCallerType);
    5790             : 
    5791           0 :   RefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
    5792             : 
    5793           0 :   if (presShell && presShell->GetIsViewportOverridden())
    5794             :   {
    5795           0 :     nscoord height = 0;
    5796             : 
    5797           0 :     RefPtr<nsPresContext> presContext;
    5798           0 :     presContext = presShell->GetPresContext();
    5799             : 
    5800           0 :     nsRect shellArea = presContext->GetVisibleArea();
    5801           0 :     height = shellArea.height;
    5802           0 :     SetCSSViewportWidthAndHeight(nsPresContext::CSSPixelsToAppUnits(aInnerWidth),
    5803           0 :                                  height);
    5804           0 :     return;
    5805             :   }
    5806             : 
    5807           0 :   int32_t height = 0;
    5808           0 :   int32_t unused  = 0;
    5809             : 
    5810           0 :   nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
    5811           0 :   docShellAsWin->GetSize(&unused, &height);
    5812           0 :   aError = SetDocShellWidthAndHeight(CSSToDevIntPixels(aInnerWidth), height);
    5813             : }
    5814             : 
    5815             : void
    5816           0 : nsGlobalWindow::SetInnerWidth(int32_t aInnerWidth, CallerType aCallerType,
    5817             :                               ErrorResult& aError)
    5818             : {
    5819           0 :   FORWARD_TO_OUTER_OR_THROW(SetInnerWidthOuter,
    5820             :                             (aInnerWidth, aCallerType, aError), aError, );
    5821             : }
    5822             : 
    5823             : void
    5824           0 : nsGlobalWindow::SetInnerWidth(JSContext* aCx, JS::Handle<JS::Value> aValue,
    5825             :                               CallerType aCallerType,
    5826             :                               ErrorResult& aError)
    5827             : {
    5828             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetInnerWidth,
    5829           0 :                             aValue, "innerWidth", aCallerType, aError);
    5830           0 : }
    5831             : 
    5832             : int32_t
    5833           0 : nsGlobalWindow::GetInnerHeightOuter(ErrorResult& aError)
    5834             : {
    5835           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5836             : 
    5837           0 :   CSSIntSize size;
    5838           0 :   aError = GetInnerSize(size);
    5839           0 :   return size.height;
    5840             : }
    5841             : 
    5842             : int32_t
    5843           0 : nsGlobalWindow::GetInnerHeight(CallerType aCallerType, ErrorResult& aError)
    5844             : {
    5845             :   // We ignore aCallerType; we only have that argument because some other things
    5846             :   // called by GetReplaceableWindowCoord need it.  If this ever changes, fix
    5847             :   //   nsresult nsGlobalWindow::GetInnerHeight(int32_t* aInnerWidth)
    5848             :   // to actually take a useful CallerType and pass it in here.
    5849           0 :   FORWARD_TO_OUTER_OR_THROW(GetInnerHeightOuter, (aError), aError, 0);
    5850             : }
    5851             : 
    5852             : void
    5853           0 : nsGlobalWindow::GetInnerHeight(JSContext* aCx,
    5854             :                               JS::MutableHandle<JS::Value> aValue,
    5855             :                               CallerType aCallerType,
    5856             :                               ErrorResult& aError)
    5857             : {
    5858             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetInnerHeight, aValue,
    5859           0 :                             aCallerType, aError);
    5860           0 : }
    5861             : 
    5862             : nsresult
    5863           0 : nsGlobalWindow::GetInnerHeight(int32_t* aInnerHeight)
    5864             : {
    5865           0 :   FORWARD_TO_INNER(GetInnerHeight, (aInnerHeight), NS_ERROR_UNEXPECTED);
    5866             : 
    5867           0 :   ErrorResult rv;
    5868             :   // Callee doesn't care about the caller type, but play it safe.
    5869           0 :   *aInnerHeight = GetInnerHeight(CallerType::NonSystem, rv);
    5870             : 
    5871           0 :   return rv.StealNSResult();
    5872             : }
    5873             : 
    5874             : void
    5875           0 : nsGlobalWindow::SetInnerHeightOuter(int32_t aInnerHeight,
    5876             :                                     CallerType aCallerType,
    5877             :                                     ErrorResult& aError)
    5878             : {
    5879           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5880             : 
    5881           0 :   if (!mDocShell) {
    5882           0 :     aError.Throw(NS_ERROR_UNEXPECTED);
    5883           0 :     return;
    5884             :   }
    5885             : 
    5886           0 :   RefPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
    5887             : 
    5888           0 :   if (presShell && presShell->GetIsViewportOverridden())
    5889             :   {
    5890           0 :     RefPtr<nsPresContext> presContext;
    5891           0 :     presContext = presShell->GetPresContext();
    5892             : 
    5893           0 :     nsRect shellArea = presContext->GetVisibleArea();
    5894           0 :     nscoord height = aInnerHeight;
    5895           0 :     nscoord width = shellArea.width;
    5896           0 :     CheckSecurityWidthAndHeight(nullptr, &height, aCallerType);
    5897           0 :     SetCSSViewportWidthAndHeight(width,
    5898           0 :                                  nsPresContext::CSSPixelsToAppUnits(height));
    5899           0 :     return;
    5900             :   }
    5901             : 
    5902           0 :   int32_t height = 0;
    5903           0 :   int32_t width  = 0;
    5904             : 
    5905           0 :   nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
    5906           0 :   docShellAsWin->GetSize(&width, &height);
    5907           0 :   CheckSecurityWidthAndHeight(nullptr, &aInnerHeight, aCallerType);
    5908           0 :   aError = SetDocShellWidthAndHeight(width, CSSToDevIntPixels(aInnerHeight));
    5909             : }
    5910             : 
    5911             : void
    5912           0 : nsGlobalWindow::SetInnerHeight(int32_t aInnerHeight,
    5913             :                                CallerType aCallerType,
    5914             :                                ErrorResult& aError)
    5915             : {
    5916           0 :   FORWARD_TO_OUTER_OR_THROW(SetInnerHeightOuter,
    5917             :                             (aInnerHeight, aCallerType, aError), aError, );
    5918             : }
    5919             : 
    5920             : void
    5921           0 : nsGlobalWindow::SetInnerHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
    5922             :                                CallerType aCallerType, ErrorResult& aError)
    5923             : {
    5924             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetInnerHeight,
    5925           0 :                             aValue, "innerHeight", aCallerType, aError);
    5926           0 : }
    5927             : 
    5928             : nsIntSize
    5929           0 : nsGlobalWindow::GetOuterSize(CallerType aCallerType, ErrorResult& aError)
    5930             : {
    5931           0 :   MOZ_ASSERT(IsOuterWindow());
    5932             : 
    5933           0 :   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
    5934           0 :     CSSIntSize size;
    5935           0 :     aError = GetInnerSize(size);
    5936           0 :     return nsIntSize(size.width, size.height);
    5937             :   }
    5938             : 
    5939           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    5940           0 :   if (!treeOwnerAsWin) {
    5941           0 :     aError.Throw(NS_ERROR_FAILURE);
    5942           0 :     return nsIntSize(0, 0);
    5943             :   }
    5944             : 
    5945           0 :   nsIntSize sizeDevPixels;
    5946           0 :   aError = treeOwnerAsWin->GetSize(&sizeDevPixels.width, &sizeDevPixels.height);
    5947           0 :   if (aError.Failed()) {
    5948           0 :     return nsIntSize();
    5949             :   }
    5950             : 
    5951           0 :   return DevToCSSIntPixels(sizeDevPixels);
    5952             : }
    5953             : 
    5954             : int32_t
    5955           0 : nsGlobalWindow::GetOuterWidthOuter(CallerType aCallerType, ErrorResult& aError)
    5956             : {
    5957           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5958           0 :   return GetOuterSize(aCallerType, aError).width;
    5959             : }
    5960             : 
    5961             : int32_t
    5962           0 : nsGlobalWindow::GetOuterWidth(CallerType aCallerType, ErrorResult& aError)
    5963             : {
    5964           0 :   FORWARD_TO_OUTER_OR_THROW(GetOuterWidthOuter, (aCallerType, aError),
    5965             :                             aError, 0);
    5966             : }
    5967             : 
    5968             : void
    5969           0 : nsGlobalWindow::GetOuterWidth(JSContext* aCx,
    5970             :                               JS::MutableHandle<JS::Value> aValue,
    5971             :                               CallerType aCallerType,
    5972             :                               ErrorResult& aError)
    5973             : {
    5974             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetOuterWidth, aValue,
    5975           0 :                             aCallerType, aError);
    5976           0 : }
    5977             : 
    5978             : int32_t
    5979           0 : nsGlobalWindow::GetOuterHeightOuter(CallerType aCallerType, ErrorResult& aError)
    5980             : {
    5981           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    5982           0 :   return GetOuterSize(aCallerType, aError).height;
    5983             : }
    5984             : 
    5985             : int32_t
    5986           0 : nsGlobalWindow::GetOuterHeight(CallerType aCallerType, ErrorResult& aError)
    5987             : {
    5988           0 :   FORWARD_TO_OUTER_OR_THROW(GetOuterHeightOuter, (aCallerType, aError),
    5989             :                             aError, 0);
    5990             : }
    5991             : 
    5992             : void
    5993           0 : nsGlobalWindow::GetOuterHeight(JSContext* aCx,
    5994             :                                JS::MutableHandle<JS::Value> aValue,
    5995             :                                CallerType aCallerType,
    5996             :                                ErrorResult& aError)
    5997             : {
    5998             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetOuterHeight, aValue,
    5999           0 :                             aCallerType, aError);
    6000           0 : }
    6001             : 
    6002             : void
    6003           0 : nsGlobalWindow::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
    6004             :                              CallerType aCallerType, ErrorResult& aError)
    6005             : {
    6006           0 :   MOZ_ASSERT(IsOuterWindow());
    6007             : 
    6008           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    6009           0 :   if (!treeOwnerAsWin) {
    6010           0 :     aError.Throw(NS_ERROR_FAILURE);
    6011           0 :     return;
    6012             :   }
    6013             : 
    6014           0 :   CheckSecurityWidthAndHeight(aIsWidth ? &aLengthCSSPixels : nullptr,
    6015             :                               aIsWidth ? nullptr : &aLengthCSSPixels,
    6016           0 :                               aCallerType);
    6017             : 
    6018             :   int32_t width, height;
    6019           0 :   aError = treeOwnerAsWin->GetSize(&width, &height);
    6020           0 :   if (aError.Failed()) {
    6021           0 :     return;
    6022             :   }
    6023             : 
    6024           0 :   int32_t lengthDevPixels = CSSToDevIntPixels(aLengthCSSPixels);
    6025           0 :   if (aIsWidth) {
    6026           0 :     width = lengthDevPixels;
    6027             :   } else {
    6028           0 :     height = lengthDevPixels;
    6029             :   }
    6030           0 :   aError = treeOwnerAsWin->SetSize(width, height, true);
    6031             : 
    6032           0 :   CheckForDPIChange();
    6033             : }
    6034             : 
    6035             : void
    6036           0 : nsGlobalWindow::SetOuterWidthOuter(int32_t aOuterWidth,
    6037             :                                    CallerType aCallerType,
    6038             :                                    ErrorResult& aError)
    6039             : {
    6040           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6041             : 
    6042           0 :   SetOuterSize(aOuterWidth, true, aCallerType, aError);
    6043           0 : }
    6044             : 
    6045             : void
    6046           0 : nsGlobalWindow::SetOuterWidth(int32_t aOuterWidth,
    6047             :                               CallerType aCallerType,
    6048             :                               ErrorResult& aError)
    6049             : {
    6050           0 :   FORWARD_TO_OUTER_OR_THROW(SetOuterWidthOuter,
    6051             :                             (aOuterWidth, aCallerType, aError), aError, );
    6052             : }
    6053             : 
    6054             : void
    6055           0 : nsGlobalWindow::SetOuterWidth(JSContext* aCx, JS::Handle<JS::Value> aValue,
    6056             :                               CallerType aCallerType,
    6057             :                               ErrorResult& aError)
    6058             : {
    6059             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetOuterWidth,
    6060           0 :                             aValue, "outerWidth", aCallerType, aError);
    6061           0 : }
    6062             : 
    6063             : void
    6064           0 : nsGlobalWindow::SetOuterHeightOuter(int32_t aOuterHeight,
    6065             :                                     CallerType aCallerType,
    6066             :                                     ErrorResult& aError)
    6067             : {
    6068           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6069             : 
    6070           0 :   SetOuterSize(aOuterHeight, false, aCallerType, aError);
    6071           0 : }
    6072             : 
    6073             : void
    6074           0 : nsGlobalWindow::SetOuterHeight(int32_t aOuterHeight,
    6075             :                                CallerType aCallerType,
    6076             :                                ErrorResult& aError)
    6077             : {
    6078           0 :   FORWARD_TO_OUTER_OR_THROW(SetOuterHeightOuter,
    6079             :                             (aOuterHeight, aCallerType, aError), aError, );
    6080             : }
    6081             : 
    6082             : void
    6083           0 : nsGlobalWindow::SetOuterHeight(JSContext* aCx, JS::Handle<JS::Value> aValue,
    6084             :                                CallerType aCallerType,
    6085             :                                ErrorResult& aError)
    6086             : {
    6087             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetOuterHeight,
    6088           0 :                             aValue, "outerHeight", aCallerType, aError);
    6089           0 : }
    6090             : 
    6091             : CSSIntPoint
    6092           0 : nsGlobalWindow::GetScreenXY(CallerType aCallerType, ErrorResult& aError)
    6093             : {
    6094           0 :   MOZ_ASSERT(IsOuterWindow());
    6095             : 
    6096             :   // When resisting fingerprinting, always return (0,0)
    6097           0 :   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
    6098           0 :     return CSSIntPoint(0, 0);
    6099             :   }
    6100             : 
    6101           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    6102           0 :   if (!treeOwnerAsWin) {
    6103           0 :     aError.Throw(NS_ERROR_FAILURE);
    6104           0 :     return CSSIntPoint(0, 0);
    6105             :   }
    6106             : 
    6107           0 :   int32_t x = 0, y = 0;
    6108           0 :   aError = treeOwnerAsWin->GetPosition(&x, &y); // LayoutDevice px values
    6109             : 
    6110           0 :   RefPtr<nsPresContext> presContext;
    6111           0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    6112           0 :   if (!presContext) {
    6113           0 :     return CSSIntPoint(x, y);
    6114             :   }
    6115             : 
    6116             :   // Find the global desktop coordinate of the top-left of the screen.
    6117             :   // We'll use this as a "fake origin" when converting to CSS px units,
    6118             :   // to avoid overlapping coordinates in cases such as a hi-dpi screen
    6119             :   // placed to the right of a lo-dpi screen on Windows. (Instead, there
    6120             :   // may be "gaps" in the resulting CSS px coordinates in some cases.)
    6121           0 :   nsDeviceContext *dc = presContext->DeviceContext();
    6122           0 :   nsRect screenRect;
    6123           0 :   dc->GetRect(screenRect);
    6124             :   LayoutDeviceRect screenRectDev =
    6125           0 :     LayoutDevicePixel::FromAppUnits(screenRect, dc->AppUnitsPerDevPixel());
    6126             : 
    6127           0 :   DesktopToLayoutDeviceScale scale = dc->GetDesktopToDeviceScale();
    6128           0 :   DesktopRect screenRectDesk = screenRectDev / scale;
    6129             : 
    6130             :   CSSPoint cssPt =
    6131           0 :     LayoutDevicePoint(x - screenRectDev.x, y - screenRectDev.y) /
    6132           0 :     presContext->CSSToDevPixelScale();
    6133           0 :   cssPt.x += screenRectDesk.x;
    6134           0 :   cssPt.y += screenRectDesk.y;
    6135             : 
    6136           0 :   return CSSIntPoint(NSToIntRound(cssPt.x), NSToIntRound(cssPt.y));
    6137             : }
    6138             : 
    6139             : int32_t
    6140           0 : nsGlobalWindow::GetScreenXOuter(CallerType aCallerType, ErrorResult& aError)
    6141             : {
    6142           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6143             : 
    6144           0 :   return GetScreenXY(aCallerType, aError).x;
    6145             : }
    6146             : 
    6147             : int32_t
    6148           0 : nsGlobalWindow::GetScreenX(CallerType aCallerType, ErrorResult& aError)
    6149             : {
    6150           0 :   FORWARD_TO_OUTER_OR_THROW(GetScreenXOuter, (aCallerType, aError), aError, 0);
    6151             : }
    6152             : 
    6153             : void
    6154           0 : nsGlobalWindow::GetScreenX(JSContext* aCx,
    6155             :                            JS::MutableHandle<JS::Value> aValue,
    6156             :                            CallerType aCallerType,
    6157             :                            ErrorResult& aError)
    6158             : {
    6159             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetScreenX, aValue,
    6160           0 :                             aCallerType, aError);
    6161           0 : }
    6162             : 
    6163             : nsRect
    6164           8 : nsGlobalWindow::GetInnerScreenRect()
    6165             : {
    6166           8 :   MOZ_ASSERT(IsOuterWindow());
    6167             : 
    6168           8 :   if (!mDocShell) {
    6169           0 :     return nsRect();
    6170             :   }
    6171             : 
    6172           8 :   EnsureSizeAndPositionUpToDate();
    6173             : 
    6174           8 :   if (!mDocShell) {
    6175           0 :     return nsRect();
    6176             :   }
    6177             : 
    6178          16 :   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
    6179           8 :   if (!presShell) {
    6180           0 :     return nsRect();
    6181             :   }
    6182           8 :   nsIFrame* rootFrame = presShell->GetRootFrame();
    6183           8 :   if (!rootFrame) {
    6184           0 :     return nsRect();
    6185             :   }
    6186             : 
    6187           8 :   return rootFrame->GetScreenRectInAppUnits();
    6188             : }
    6189             : 
    6190             : float
    6191           4 : nsGlobalWindow::GetMozInnerScreenXOuter(CallerType aCallerType)
    6192             : {
    6193           4 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6194             : 
    6195             :   // When resisting fingerprinting, always return 0.
    6196           4 :   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
    6197           0 :     return 0.0;
    6198             :   }
    6199             : 
    6200           8 :   nsRect r = GetInnerScreenRect();
    6201           4 :   return nsPresContext::AppUnitsToFloatCSSPixels(r.x);
    6202             : }
    6203             : 
    6204             : float
    6205           4 : nsGlobalWindow::GetMozInnerScreenX(CallerType aCallerType, ErrorResult& aError)
    6206             : {
    6207           4 :   FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenXOuter, (aCallerType), aError, 0);
    6208             : }
    6209             : 
    6210             : float
    6211           4 : nsGlobalWindow::GetMozInnerScreenYOuter(CallerType aCallerType)
    6212             : {
    6213           4 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6214             : 
    6215             :   // Return 0 to prevent fingerprinting.
    6216           4 :   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
    6217           0 :     return 0.0;
    6218             :   }
    6219             : 
    6220           8 :   nsRect r = GetInnerScreenRect();
    6221           4 :   return nsPresContext::AppUnitsToFloatCSSPixels(r.y);
    6222             : }
    6223             : 
    6224             : float
    6225           4 : nsGlobalWindow::GetMozInnerScreenY(CallerType aCallerType, ErrorResult& aError)
    6226             : {
    6227           4 :   FORWARD_TO_OUTER_OR_THROW(GetMozInnerScreenYOuter, (aCallerType), aError, 0);
    6228             : }
    6229             : 
    6230             : float
    6231           1 : nsGlobalWindow::GetDevicePixelRatioOuter(CallerType aCallerType)
    6232             : {
    6233           1 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6234             : 
    6235           1 :   if (!mDocShell) {
    6236           0 :     return 1.0;
    6237             :   }
    6238             : 
    6239           2 :   RefPtr<nsPresContext> presContext;
    6240           1 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    6241           1 :   if (!presContext) {
    6242           0 :     return 1.0;
    6243             :   }
    6244             : 
    6245           1 :   if (nsContentUtils::ResistFingerprinting(aCallerType)) {
    6246           0 :     return 1.0;
    6247             :   }
    6248             : 
    6249           1 :   float overrideDPPX = presContext->GetOverrideDPPX();
    6250             : 
    6251           1 :   if (overrideDPPX > 0) {
    6252           0 :     return overrideDPPX;
    6253             :   }
    6254             : 
    6255           2 :   return float(nsPresContext::AppUnitsPerCSSPixel())/
    6256           2 :       presContext->AppUnitsPerDevPixel();
    6257             : }
    6258             : 
    6259             : float
    6260           1 : nsGlobalWindow::GetDevicePixelRatio(CallerType aCallerType, ErrorResult& aError)
    6261             : {
    6262           1 :   FORWARD_TO_OUTER_OR_THROW(GetDevicePixelRatioOuter, (aCallerType), aError, 0.0);
    6263             : }
    6264             : 
    6265             : float
    6266           0 : nsPIDOMWindowOuter::GetDevicePixelRatio(CallerType aCallerType)
    6267             : {
    6268           0 :   return nsGlobalWindow::Cast(this)->GetDevicePixelRatioOuter(aCallerType);
    6269             : }
    6270             : 
    6271             : uint64_t
    6272           0 : nsGlobalWindow::GetMozPaintCountOuter()
    6273             : {
    6274           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6275             : 
    6276           0 :   if (!mDocShell) {
    6277           0 :     return 0;
    6278             :   }
    6279             : 
    6280           0 :   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
    6281           0 :   return presShell ? presShell->GetPaintCount() : 0;
    6282             : }
    6283             : 
    6284             : uint64_t
    6285           0 : nsGlobalWindow::GetMozPaintCount(ErrorResult& aError)
    6286             : {
    6287           0 :   FORWARD_TO_OUTER_OR_THROW(GetMozPaintCountOuter, (), aError, 0);
    6288             : }
    6289             : 
    6290             : int32_t
    6291           4 : nsGlobalWindow::RequestAnimationFrame(FrameRequestCallback& aCallback,
    6292             :                                       ErrorResult& aError)
    6293             : {
    6294           4 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    6295             : 
    6296           4 :   if (!mDoc) {
    6297           0 :     return 0;
    6298             :   }
    6299             : 
    6300           4 :   if (GetWrapperPreserveColor()) {
    6301           4 :     js::NotifyAnimationActivity(GetWrapperPreserveColor());
    6302             :   }
    6303             : 
    6304             :   int32_t handle;
    6305           4 :   aError = mDoc->ScheduleFrameRequestCallback(aCallback, &handle);
    6306           4 :   return handle;
    6307             : }
    6308             : 
    6309             : void
    6310           0 : nsGlobalWindow::CancelAnimationFrame(int32_t aHandle, ErrorResult& aError)
    6311             : {
    6312           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    6313             : 
    6314           0 :   if (!mDoc) {
    6315           0 :     return;
    6316             :   }
    6317             : 
    6318           0 :   mDoc->CancelFrameRequestCallback(aHandle);
    6319             : }
    6320             : 
    6321             : already_AddRefed<MediaQueryList>
    6322           3 : nsGlobalWindow::MatchMediaOuter(const nsAString& aMediaQueryList)
    6323             : {
    6324           3 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6325             : 
    6326           3 :   if (!mDoc) {
    6327           0 :     return nullptr;
    6328             :   }
    6329             : 
    6330           3 :   return mDoc->MatchMedia(aMediaQueryList);
    6331             : }
    6332             : 
    6333             : already_AddRefed<MediaQueryList>
    6334           3 : nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
    6335             :                            ErrorResult& aError)
    6336             : {
    6337             :   // FIXME: This whole forward-to-outer and then get a pres
    6338             :   // shell/context off the docshell dance is sort of silly; it'd make
    6339             :   // more sense to forward to the inner, but it's what everyone else
    6340             :   // (GetSelection, GetScrollXY, etc.) does around here.
    6341           3 :   FORWARD_TO_OUTER_OR_THROW(MatchMediaOuter, (aMediaQueryList), aError, nullptr);
    6342             : }
    6343             : 
    6344             : void
    6345           0 : nsGlobalWindow::SetScreenXOuter(int32_t aScreenX,
    6346             :                                 CallerType aCallerType,
    6347             :                                 ErrorResult& aError)
    6348             : {
    6349           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6350             : 
    6351           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    6352           0 :   if (!treeOwnerAsWin) {
    6353           0 :     aError.Throw(NS_ERROR_FAILURE);
    6354           0 :     return;
    6355             :   }
    6356             : 
    6357             :   int32_t x, y;
    6358           0 :   aError = treeOwnerAsWin->GetPosition(&x, &y);
    6359           0 :   if (aError.Failed()) {
    6360           0 :     return;
    6361             :   }
    6362             : 
    6363           0 :   CheckSecurityLeftAndTop(&aScreenX, nullptr, aCallerType);
    6364           0 :   x = CSSToDevIntPixels(aScreenX);
    6365             : 
    6366           0 :   aError = treeOwnerAsWin->SetPosition(x, y);
    6367             : 
    6368           0 :   CheckForDPIChange();
    6369             : }
    6370             : 
    6371             : void
    6372           0 : nsGlobalWindow::SetScreenX(int32_t aScreenX,
    6373             :                            CallerType aCallerType,
    6374             :                            ErrorResult& aError)
    6375             : {
    6376           0 :   FORWARD_TO_OUTER_OR_THROW(SetScreenXOuter,
    6377             :                             (aScreenX, aCallerType, aError), aError, );
    6378             : }
    6379             : 
    6380             : void
    6381           0 : nsGlobalWindow::SetScreenX(JSContext* aCx, JS::Handle<JS::Value> aValue,
    6382             :                            CallerType aCallerType, ErrorResult& aError)
    6383             : {
    6384             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetScreenX,
    6385           0 :                             aValue, "screenX", aCallerType, aError);
    6386           0 : }
    6387             : 
    6388             : int32_t
    6389           0 : nsGlobalWindow::GetScreenYOuter(CallerType aCallerType, ErrorResult& aError)
    6390             : {
    6391           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6392             : 
    6393           0 :   return GetScreenXY(aCallerType, aError).y;
    6394             : }
    6395             : 
    6396             : int32_t
    6397           0 : nsGlobalWindow::GetScreenY(CallerType aCallerType, ErrorResult& aError)
    6398             : {
    6399           0 :   FORWARD_TO_OUTER_OR_THROW(GetScreenYOuter, (aCallerType, aError), aError, 0);
    6400             : }
    6401             : 
    6402             : void
    6403           0 : nsGlobalWindow::GetScreenY(JSContext* aCx,
    6404             :                            JS::MutableHandle<JS::Value> aValue,
    6405             :                            CallerType aCallerType, ErrorResult& aError)
    6406             : {
    6407             :   GetReplaceableWindowCoord(aCx, &nsGlobalWindow::GetScreenY, aValue,
    6408           0 :                             aCallerType, aError);
    6409           0 : }
    6410             : 
    6411             : void
    6412           0 : nsGlobalWindow::SetScreenYOuter(int32_t aScreenY,
    6413             :                                 CallerType aCallerType,
    6414             :                                 ErrorResult& aError)
    6415             : {
    6416           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6417             : 
    6418           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    6419           0 :   if (!treeOwnerAsWin) {
    6420           0 :     aError.Throw(NS_ERROR_FAILURE);
    6421           0 :     return;
    6422             :   }
    6423             : 
    6424             :   int32_t x, y;
    6425           0 :   aError = treeOwnerAsWin->GetPosition(&x, &y);
    6426           0 :   if (aError.Failed()) {
    6427           0 :     return;
    6428             :   }
    6429             : 
    6430           0 :   CheckSecurityLeftAndTop(nullptr, &aScreenY, aCallerType);
    6431           0 :   y = CSSToDevIntPixels(aScreenY);
    6432             : 
    6433           0 :   aError = treeOwnerAsWin->SetPosition(x, y);
    6434             : 
    6435           0 :   CheckForDPIChange();
    6436             : }
    6437             : 
    6438             : void
    6439           0 : nsGlobalWindow::SetScreenY(int32_t aScreenY,
    6440             :                            CallerType aCallerType,
    6441             :                            ErrorResult& aError)
    6442             : {
    6443           0 :   FORWARD_TO_OUTER_OR_THROW(SetScreenYOuter,
    6444             :                             (aScreenY, aCallerType, aError), aError, );
    6445             : }
    6446             : 
    6447             : void
    6448           0 : nsGlobalWindow::SetScreenY(JSContext* aCx, JS::Handle<JS::Value> aValue,
    6449             :                            CallerType aCallerType,
    6450             :                            ErrorResult& aError)
    6451             : {
    6452             :   SetReplaceableWindowCoord(aCx, &nsGlobalWindow::SetScreenY,
    6453           0 :                             aValue, "screenY", aCallerType, aError);
    6454           0 : }
    6455             : 
    6456             : // NOTE: Arguments to this function should have values scaled to
    6457             : // CSS pixels, not device pixels.
    6458             : void
    6459           0 : nsGlobalWindow::CheckSecurityWidthAndHeight(int32_t* aWidth, int32_t* aHeight,
    6460             :                                             CallerType aCallerType)
    6461             : {
    6462           0 :   MOZ_ASSERT(IsOuterWindow());
    6463             : 
    6464             : #ifdef MOZ_XUL
    6465           0 :   if (aCallerType != CallerType::System) {
    6466             :     // if attempting to resize the window, hide any open popups
    6467           0 :     nsContentUtils::HidePopupsInDocument(mDoc);
    6468             :   }
    6469             : #endif
    6470             : 
    6471             :   // This one is easy. Just ensure the variable is greater than 100;
    6472           0 :   if ((aWidth && *aWidth < 100) || (aHeight && *aHeight < 100)) {
    6473             :     // Check security state for use in determing window dimensions
    6474             : 
    6475           0 :     if (aCallerType != CallerType::System) {
    6476             :       //sec check failed
    6477           0 :       if (aWidth && *aWidth < 100) {
    6478           0 :         *aWidth = 100;
    6479             :       }
    6480           0 :       if (aHeight && *aHeight < 100) {
    6481           0 :         *aHeight = 100;
    6482             :       }
    6483             :     }
    6484             :   }
    6485           0 : }
    6486             : 
    6487             : // NOTE: Arguments to this function should have values in device pixels
    6488             : nsresult
    6489           0 : nsGlobalWindow::SetDocShellWidthAndHeight(int32_t aInnerWidth, int32_t aInnerHeight)
    6490             : {
    6491           0 :   MOZ_ASSERT(IsOuterWindow());
    6492             : 
    6493           0 :   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
    6494             : 
    6495           0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    6496           0 :   mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
    6497           0 :   NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
    6498             : 
    6499           0 :   NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(mDocShell, aInnerWidth, aInnerHeight),
    6500             :                     NS_ERROR_FAILURE);
    6501             : 
    6502           0 :   return NS_OK;
    6503             : }
    6504             : 
    6505             : // NOTE: Arguments to this function should have values in app units
    6506             : void
    6507           0 : nsGlobalWindow::SetCSSViewportWidthAndHeight(nscoord aInnerWidth, nscoord aInnerHeight)
    6508             : {
    6509           0 :   MOZ_ASSERT(IsOuterWindow());
    6510             : 
    6511           0 :   RefPtr<nsPresContext> presContext;
    6512           0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    6513             : 
    6514           0 :   nsRect shellArea = presContext->GetVisibleArea();
    6515           0 :   shellArea.height = aInnerHeight;
    6516           0 :   shellArea.width = aInnerWidth;
    6517             : 
    6518           0 :   presContext->SetVisibleArea(shellArea);
    6519           0 : }
    6520             : 
    6521             : // NOTE: Arguments to this function should have values scaled to
    6522             : // CSS pixels, not device pixels.
    6523             : void
    6524           0 : nsGlobalWindow::CheckSecurityLeftAndTop(int32_t* aLeft, int32_t* aTop,
    6525             :                                         CallerType aCallerType)
    6526             : {
    6527           0 :   MOZ_ASSERT(IsOuterWindow());
    6528             : 
    6529             :   // This one is harder. We have to get the screen size and window dimensions.
    6530             : 
    6531             :   // Check security state for use in determing window dimensions
    6532             : 
    6533           0 :   if (aCallerType != CallerType::System) {
    6534             : #ifdef MOZ_XUL
    6535             :     // if attempting to move the window, hide any open popups
    6536           0 :     nsContentUtils::HidePopupsInDocument(mDoc);
    6537             : #endif
    6538             : 
    6539           0 :     if (nsGlobalWindow* rootWindow = nsGlobalWindow::Cast(GetPrivateRoot())) {
    6540           0 :       rootWindow->FlushPendingNotifications(FlushType::Layout);
    6541             :     }
    6542             : 
    6543           0 :     nsCOMPtr<nsIBaseWindow> treeOwner = GetTreeOwnerWindow();
    6544             : 
    6545           0 :     nsCOMPtr<nsIDOMScreen> screen = GetScreen();
    6546             : 
    6547           0 :     if (treeOwner && screen) {
    6548             :       int32_t screenLeft, screenTop, screenWidth, screenHeight;
    6549             :       int32_t winLeft, winTop, winWidth, winHeight;
    6550             : 
    6551             :       // Get the window size
    6552           0 :       treeOwner->GetPositionAndSize(&winLeft, &winTop, &winWidth, &winHeight);
    6553             : 
    6554             :       // convert those values to CSS pixels
    6555             :       // XXX four separate retrievals of the prescontext
    6556           0 :       winLeft   = DevToCSSIntPixels(winLeft);
    6557           0 :       winTop    = DevToCSSIntPixels(winTop);
    6558           0 :       winWidth  = DevToCSSIntPixels(winWidth);
    6559           0 :       winHeight = DevToCSSIntPixels(winHeight);
    6560             : 
    6561             :       // Get the screen dimensions
    6562             :       // XXX This should use nsIScreenManager once it's fully fleshed out.
    6563           0 :       screen->GetAvailLeft(&screenLeft);
    6564           0 :       screen->GetAvailWidth(&screenWidth);
    6565           0 :       screen->GetAvailHeight(&screenHeight);
    6566             : #if defined(XP_MACOSX)
    6567             :       /* The mac's coordinate system is different from the assumed Windows'
    6568             :          system. It offsets by the height of the menubar so that a window
    6569             :          placed at (0,0) will be entirely visible. Unfortunately that
    6570             :          correction is made elsewhere (in Widget) and the meaning of
    6571             :          the Avail... coordinates is overloaded. Here we allow a window
    6572             :          to be placed at (0,0) because it does make sense to do so.
    6573             :       */
    6574             :       screen->GetTop(&screenTop);
    6575             : #else
    6576           0 :       screen->GetAvailTop(&screenTop);
    6577             : #endif
    6578             : 
    6579           0 :       if (aLeft) {
    6580           0 :         if (screenLeft+screenWidth < *aLeft+winWidth)
    6581           0 :           *aLeft = screenLeft+screenWidth - winWidth;
    6582           0 :         if (screenLeft > *aLeft)
    6583           0 :           *aLeft = screenLeft;
    6584             :       }
    6585           0 :       if (aTop) {
    6586           0 :         if (screenTop+screenHeight < *aTop+winHeight)
    6587           0 :           *aTop = screenTop+screenHeight - winHeight;
    6588           0 :         if (screenTop > *aTop)
    6589           0 :           *aTop = screenTop;
    6590             :       }
    6591             :     } else {
    6592           0 :       if (aLeft)
    6593           0 :         *aLeft = 0;
    6594           0 :       if (aTop)
    6595           0 :         *aTop = 0;
    6596             :     }
    6597             :   }
    6598           0 : }
    6599             : 
    6600             : int32_t
    6601           0 : nsGlobalWindow::GetScrollBoundaryOuter(Side aSide)
    6602             : {
    6603           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6604             : 
    6605           0 :   FlushPendingNotifications(FlushType::Layout);
    6606           0 :   if (nsIScrollableFrame *sf = GetScrollFrame()) {
    6607             :     return nsPresContext::
    6608           0 :       AppUnitsToIntCSSPixels(sf->GetScrollRange().Edge(aSide));
    6609             :   }
    6610           0 :   return 0;
    6611             : }
    6612             : 
    6613             : int32_t
    6614           0 : nsGlobalWindow::GetScrollMinX(ErrorResult& aError)
    6615             : {
    6616           0 :   MOZ_ASSERT(IsInnerWindow());
    6617           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, 0);
    6618             : }
    6619             : 
    6620             : int32_t
    6621           0 : nsGlobalWindow::GetScrollMinY(ErrorResult& aError)
    6622             : {
    6623           0 :   MOZ_ASSERT(IsInnerWindow());
    6624           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideTop), aError, 0);
    6625             : }
    6626             : 
    6627             : int32_t
    6628           0 : nsGlobalWindow::GetScrollMaxX(ErrorResult& aError)
    6629             : {
    6630           0 :   MOZ_ASSERT(IsInnerWindow());
    6631           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideRight), aError, 0);
    6632             : }
    6633             : 
    6634             : int32_t
    6635           0 : nsGlobalWindow::GetScrollMaxY(ErrorResult& aError)
    6636             : {
    6637           0 :   MOZ_ASSERT(IsInnerWindow());
    6638           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideBottom), aError, 0);
    6639             : }
    6640             : 
    6641             : CSSPoint
    6642           0 : nsGlobalWindow::GetScrollXY(bool aDoFlush)
    6643             : {
    6644           0 :   MOZ_ASSERT(IsOuterWindow());
    6645             : 
    6646           0 :   if (aDoFlush) {
    6647           0 :     FlushPendingNotifications(FlushType::Layout);
    6648             :   } else {
    6649           0 :     EnsureSizeAndPositionUpToDate();
    6650             :   }
    6651             : 
    6652           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    6653           0 :   if (!sf) {
    6654           0 :     return CSSIntPoint(0, 0);
    6655             :   }
    6656             : 
    6657           0 :   nsPoint scrollPos = sf->GetScrollPosition();
    6658           0 :   if (scrollPos != nsPoint(0,0) && !aDoFlush) {
    6659             :     // Oh, well.  This is the expensive case -- the window is scrolled and we
    6660             :     // didn't actually flush yet.  Repeat, but with a flush, since the content
    6661             :     // may get shorter and hence our scroll position may decrease.
    6662           0 :     return GetScrollXY(true);
    6663             :   }
    6664             : 
    6665           0 :   return CSSPoint::FromAppUnits(scrollPos);
    6666             : }
    6667             : 
    6668             : double
    6669           0 : nsGlobalWindow::GetScrollXOuter()
    6670             : {
    6671           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6672           0 :   return GetScrollXY(false).x;
    6673             : }
    6674             : 
    6675             : double
    6676           0 : nsGlobalWindow::GetScrollX(ErrorResult& aError)
    6677             : {
    6678           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollXOuter, (), aError, 0);
    6679             : }
    6680             : 
    6681             : double
    6682           0 : nsGlobalWindow::GetScrollYOuter()
    6683             : {
    6684           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6685           0 :   return GetScrollXY(false).y;
    6686             : }
    6687             : 
    6688             : double
    6689           0 : nsGlobalWindow::GetScrollY(ErrorResult& aError)
    6690             : {
    6691           0 :   FORWARD_TO_OUTER_OR_THROW(GetScrollYOuter, (), aError, 0);
    6692             : }
    6693             : 
    6694             : uint32_t
    6695         768 : nsGlobalWindow::Length()
    6696             : {
    6697         768 :   FORWARD_TO_OUTER(Length, (), 0);
    6698             : 
    6699         384 :   nsDOMWindowList* windows = GetWindowList();
    6700             : 
    6701         384 :   return windows ? windows->GetLength() : 0;
    6702             : }
    6703             : 
    6704             : already_AddRefed<nsPIDOMWindowOuter>
    6705          12 : nsGlobalWindow::GetTopOuter()
    6706             : {
    6707          12 :   MOZ_ASSERT(IsOuterWindow());
    6708             : 
    6709          24 :   nsCOMPtr<nsPIDOMWindowOuter> top = GetScriptableTop();
    6710          24 :   return top.forget();
    6711             : }
    6712             : 
    6713             : already_AddRefed<nsPIDOMWindowOuter>
    6714          12 : nsGlobalWindow::GetTop(mozilla::ErrorResult& aError)
    6715             : {
    6716          12 :   FORWARD_TO_OUTER_OR_THROW(GetTopOuter, (), aError, nullptr);
    6717             : }
    6718             : 
    6719             : nsPIDOMWindowOuter*
    6720          80 : nsGlobalWindow::GetChildWindow(const nsAString& aName)
    6721             : {
    6722         160 :   nsCOMPtr<nsIDocShell> docShell(GetDocShell());
    6723          80 :   NS_ENSURE_TRUE(docShell, nullptr);
    6724             : 
    6725         160 :   nsCOMPtr<nsIDocShellTreeItem> child;
    6726         160 :   docShell->FindChildWithName(aName, false, true, nullptr, nullptr,
    6727         160 :                               getter_AddRefs(child));
    6728             : 
    6729          80 :   return child ? child->GetWindow() : nullptr;
    6730             : }
    6731             : 
    6732             : bool
    6733           1 : nsGlobalWindow::DispatchCustomEvent(const nsAString& aEventName)
    6734             : {
    6735           1 :   MOZ_ASSERT(IsOuterWindow());
    6736             : 
    6737           1 :   bool defaultActionEnabled = true;
    6738           1 :   nsContentUtils::DispatchTrustedEvent(mDoc, ToSupports(this), aEventName,
    6739           1 :                                        true, true, &defaultActionEnabled);
    6740             : 
    6741           1 :   return defaultActionEnabled;
    6742             : }
    6743             : 
    6744             : bool
    6745           0 : nsGlobalWindow::DispatchResizeEvent(const CSSIntSize& aSize)
    6746             : {
    6747           0 :   MOZ_ASSERT(IsOuterWindow());
    6748             : 
    6749           0 :   ErrorResult res;
    6750             :   RefPtr<Event> domEvent =
    6751           0 :     mDoc->CreateEvent(NS_LITERAL_STRING("CustomEvent"), CallerType::System,
    6752           0 :                       res);
    6753           0 :   if (res.Failed()) {
    6754           0 :     return false;
    6755             :   }
    6756             : 
    6757             :   // We don't init the AutoJSAPI with ourselves because we don't want it
    6758             :   // reporting errors to our onerror handlers.
    6759           0 :   AutoJSAPI jsapi;
    6760           0 :   jsapi.Init();
    6761           0 :   JSContext* cx = jsapi.cx();
    6762           0 :   JSAutoCompartment ac(cx, GetWrapperPreserveColor());
    6763             : 
    6764           0 :   DOMWindowResizeEventDetail detail;
    6765           0 :   detail.mWidth = aSize.width;
    6766           0 :   detail.mHeight = aSize.height;
    6767           0 :   JS::Rooted<JS::Value> detailValue(cx);
    6768           0 :   if (!ToJSValue(cx, detail, &detailValue)) {
    6769           0 :     return false;
    6770             :   }
    6771             : 
    6772           0 :   CustomEvent* customEvent = static_cast<CustomEvent*>(domEvent.get());
    6773           0 :   customEvent->InitCustomEvent(cx,
    6774           0 :                                NS_LITERAL_STRING("DOMWindowResize"),
    6775             :                                /* aCanBubble = */ true,
    6776             :                                /* aCancelable = */ true,
    6777             :                                detailValue,
    6778           0 :                                res);
    6779           0 :   if (res.Failed()) {
    6780           0 :     return false;
    6781             :   }
    6782             : 
    6783           0 :   domEvent->SetTrusted(true);
    6784           0 :   domEvent->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
    6785             : 
    6786           0 :   nsCOMPtr<EventTarget> target = do_QueryInterface(GetOuterWindow());
    6787           0 :   domEvent->SetTarget(target);
    6788             : 
    6789           0 :   bool defaultActionEnabled = true;
    6790           0 :   target->DispatchEvent(domEvent, &defaultActionEnabled);
    6791             : 
    6792           0 :   return defaultActionEnabled;
    6793             : }
    6794             : 
    6795             : void
    6796           0 : nsGlobalWindow::RefreshCompartmentPrincipal()
    6797             : {
    6798           0 :   MOZ_ASSERT(IsInnerWindow());
    6799             : 
    6800           0 :   JS_SetCompartmentPrincipals(js::GetObjectCompartment(GetWrapperPreserveColor()),
    6801           0 :                               nsJSPrincipals::get(mDoc->NodePrincipal()));
    6802           0 : }
    6803             : 
    6804             : static already_AddRefed<nsIDocShellTreeItem>
    6805           0 : GetCallerDocShellTreeItem()
    6806             : {
    6807           0 :   nsCOMPtr<nsIWebNavigation> callerWebNav = do_GetInterface(GetEntryGlobal());
    6808           0 :   nsCOMPtr<nsIDocShellTreeItem> callerItem = do_QueryInterface(callerWebNav);
    6809             : 
    6810           0 :   return callerItem.forget();
    6811             : }
    6812             : 
    6813             : bool
    6814           0 : nsGlobalWindow::WindowExists(const nsAString& aName,
    6815             :                              bool aForceNoOpener,
    6816             :                              bool aLookForCallerOnJSStack)
    6817             : {
    6818           0 :   NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
    6819           0 :   NS_PRECONDITION(mDocShell, "Must have docshell");
    6820             : 
    6821           0 :   if (aForceNoOpener) {
    6822           0 :     return aName.LowerCaseEqualsLiteral("_self") ||
    6823           0 :            aName.LowerCaseEqualsLiteral("_top") ||
    6824           0 :            aName.LowerCaseEqualsLiteral("_parent");
    6825             :   }
    6826             : 
    6827           0 :   nsCOMPtr<nsIDocShellTreeItem> caller;
    6828           0 :   if (aLookForCallerOnJSStack) {
    6829           0 :     caller = GetCallerDocShellTreeItem();
    6830             :   }
    6831             : 
    6832           0 :   if (!caller) {
    6833           0 :     caller = mDocShell;
    6834             :   }
    6835             : 
    6836           0 :   nsCOMPtr<nsIDocShellTreeItem> namedItem;
    6837           0 :   mDocShell->FindItemWithName(aName, nullptr, caller,
    6838             :                               /* aSkipTabGroup = */ false,
    6839           0 :                               getter_AddRefs(namedItem));
    6840           0 :   return namedItem != nullptr;
    6841             : }
    6842             : 
    6843             : already_AddRefed<nsIWidget>
    6844          18 : nsGlobalWindow::GetMainWidget()
    6845             : {
    6846          18 :   FORWARD_TO_OUTER(GetMainWidget, (), nullptr);
    6847             : 
    6848          22 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    6849             : 
    6850          22 :   nsCOMPtr<nsIWidget> widget;
    6851             : 
    6852          11 :   if (treeOwnerAsWin) {
    6853          11 :     treeOwnerAsWin->GetMainWidget(getter_AddRefs(widget));
    6854             :   }
    6855             : 
    6856          11 :   return widget.forget();
    6857             : }
    6858             : 
    6859             : nsIWidget*
    6860           0 : nsGlobalWindow::GetNearestWidget() const
    6861             : {
    6862           0 :   nsIDocShell* docShell = GetDocShell();
    6863           0 :   NS_ENSURE_TRUE(docShell, nullptr);
    6864           0 :   nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
    6865           0 :   NS_ENSURE_TRUE(presShell, nullptr);
    6866           0 :   nsIFrame* rootFrame = presShell->GetRootFrame();
    6867           0 :   NS_ENSURE_TRUE(rootFrame, nullptr);
    6868           0 :   return rootFrame->GetView()->GetNearestWidget(nullptr);
    6869             : }
    6870             : 
    6871             : void
    6872           0 : nsGlobalWindow::SetFullScreenOuter(bool aFullScreen, mozilla::ErrorResult& aError)
    6873             : {
    6874           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    6875             : 
    6876           0 :   aError = SetFullscreenInternal(FullscreenReason::ForFullscreenMode, aFullScreen);
    6877           0 : }
    6878             : 
    6879             : void
    6880           0 : nsGlobalWindow::SetFullScreen(bool aFullScreen, mozilla::ErrorResult& aError)
    6881             : {
    6882           0 :   FORWARD_TO_OUTER_OR_THROW(SetFullScreenOuter, (aFullScreen, aError), aError, /* void */);
    6883             : }
    6884             : 
    6885             : nsresult
    6886           0 : nsGlobalWindow::SetFullScreen(bool aFullScreen)
    6887             : {
    6888           0 :   FORWARD_TO_OUTER(SetFullScreen, (aFullScreen), NS_ERROR_NOT_INITIALIZED);
    6889             : 
    6890           0 :   return SetFullscreenInternal(FullscreenReason::ForFullscreenMode, aFullScreen);
    6891             : }
    6892             : 
    6893             : static void
    6894           0 : FinishDOMFullscreenChange(nsIDocument* aDoc, bool aInDOMFullscreen)
    6895             : {
    6896           0 :   if (aInDOMFullscreen) {
    6897             :     // Ask the document to handle any pending DOM fullscreen change.
    6898           0 :     if (!nsIDocument::HandlePendingFullscreenRequests(aDoc)) {
    6899             :       // If we don't end up having anything in fullscreen,
    6900             :       // async request exiting fullscreen.
    6901           0 :       nsIDocument::AsyncExitFullscreen(aDoc);
    6902             :     }
    6903             :   } else {
    6904             :     // If the window is leaving fullscreen state, also ask the document
    6905             :     // to exit from DOM Fullscreen.
    6906           0 :     nsIDocument::ExitFullscreenInDocTree(aDoc);
    6907             :   }
    6908           0 : }
    6909             : 
    6910             : struct FullscreenTransitionDuration
    6911             : {
    6912             :   // The unit of the durations is millisecond
    6913             :   uint16_t mFadeIn = 0;
    6914             :   uint16_t mFadeOut = 0;
    6915           0 :   bool IsSuppressed() const
    6916             :   {
    6917           0 :     return mFadeIn == 0 && mFadeOut == 0;
    6918             :   }
    6919             : };
    6920             : 
    6921             : static void
    6922           0 : GetFullscreenTransitionDuration(bool aEnterFullscreen,
    6923             :                                 FullscreenTransitionDuration* aDuration)
    6924             : {
    6925             :   const char* pref = aEnterFullscreen ?
    6926             :     "full-screen-api.transition-duration.enter" :
    6927           0 :     "full-screen-api.transition-duration.leave";
    6928           0 :   nsAdoptingCString prefValue = Preferences::GetCString(pref);
    6929           0 :   if (!prefValue.IsEmpty()) {
    6930           0 :     sscanf(prefValue.get(), "%hu%hu",
    6931           0 :            &aDuration->mFadeIn, &aDuration->mFadeOut);
    6932             :   }
    6933           0 : }
    6934             : 
    6935             : class FullscreenTransitionTask : public Runnable
    6936             : {
    6937             : public:
    6938           0 :   FullscreenTransitionTask(const FullscreenTransitionDuration& aDuration,
    6939             :                            nsGlobalWindow* aWindow,
    6940             :                            bool aFullscreen,
    6941             :                            nsIWidget* aWidget,
    6942             :                            nsIScreen* aScreen,
    6943             :                            nsISupports* aTransitionData)
    6944           0 :     : mozilla::Runnable("FullscreenTransitionTask")
    6945             :     , mWindow(aWindow)
    6946             :     , mWidget(aWidget)
    6947             :     , mScreen(aScreen)
    6948             :     , mTransitionData(aTransitionData)
    6949             :     , mDuration(aDuration)
    6950             :     , mStage(eBeforeToggle)
    6951           0 :     , mFullscreen(aFullscreen)
    6952             :   {
    6953           0 :   }
    6954             : 
    6955             :   NS_IMETHOD Run() override;
    6956             : 
    6957             : private:
    6958           0 :   ~FullscreenTransitionTask() override
    6959           0 :   {
    6960           0 :   }
    6961             : 
    6962             :   /**
    6963             :    * The flow of fullscreen transition:
    6964             :    *
    6965             :    *         parent process         |         child process
    6966             :    * ----------------------------------------------------------------
    6967             :    *
    6968             :    *                                    | request/exit fullscreen
    6969             :    *                              <-----|
    6970             :    *         BeforeToggle stage |
    6971             :    *                            |
    6972             :    *  ToggleFullscreen stage *1 |----->
    6973             :    *                                    | HandleFullscreenRequests
    6974             :    *                                    |
    6975             :    *                              <-----| MozAfterPaint event
    6976             :    *       AfterToggle stage *2 |
    6977             :    *                            |
    6978             :    *                  End stage |
    6979             :    *
    6980             :    * Note we also start a timer at *1 so that if we don't get MozAfterPaint
    6981             :    * from the child process in time, we continue going to *2.
    6982             :    */
    6983             :   enum Stage {
    6984             :     // BeforeToggle stage happens before we enter or leave fullscreen
    6985             :     // state. In this stage, the task triggers the pre-toggle fullscreen
    6986             :     // transition on the widget.
    6987             :     eBeforeToggle,
    6988             :     // ToggleFullscreen stage actually executes the fullscreen toggle,
    6989             :     // and wait for the next paint on the content to continue.
    6990             :     eToggleFullscreen,
    6991             :     // AfterToggle stage happens after we toggle the fullscreen state.
    6992             :     // In this stage, the task triggers the post-toggle fullscreen
    6993             :     // transition on the widget.
    6994             :     eAfterToggle,
    6995             :     // End stage is triggered after the final transition finishes.
    6996             :     eEnd
    6997             :   };
    6998             : 
    6999             :   class Observer final : public nsIObserver
    7000             :   {
    7001             :   public:
    7002             :     NS_DECL_ISUPPORTS
    7003             :     NS_DECL_NSIOBSERVER
    7004             : 
    7005           0 :     explicit Observer(FullscreenTransitionTask* aTask)
    7006           0 :       : mTask(aTask) { }
    7007             : 
    7008             :   private:
    7009           0 :     ~Observer() = default;
    7010             : 
    7011             :     RefPtr<FullscreenTransitionTask> mTask;
    7012             :   };
    7013             : 
    7014             :   static const char* const kPaintedTopic;
    7015             : 
    7016             :   RefPtr<nsGlobalWindow> mWindow;
    7017             :   nsCOMPtr<nsIWidget> mWidget;
    7018             :   nsCOMPtr<nsIScreen> mScreen;
    7019             :   nsCOMPtr<nsITimer> mTimer;
    7020             :   nsCOMPtr<nsISupports> mTransitionData;
    7021             : 
    7022             :   TimeStamp mFullscreenChangeStartTime;
    7023             :   FullscreenTransitionDuration mDuration;
    7024             :   Stage mStage;
    7025             :   bool mFullscreen;
    7026             : };
    7027             : 
    7028             : const char* const
    7029             : FullscreenTransitionTask::kPaintedTopic = "fullscreen-painted";
    7030             : 
    7031             : NS_IMETHODIMP
    7032           0 : FullscreenTransitionTask::Run()
    7033             : {
    7034           0 :   Stage stage = mStage;
    7035           0 :   mStage = Stage(mStage + 1);
    7036           0 :   if (MOZ_UNLIKELY(mWidget->Destroyed())) {
    7037             :     // If the widget has been destroyed before we get here, don't try to
    7038             :     // do anything more. Just let it go and release ourselves.
    7039           0 :     NS_WARNING("The widget to fullscreen has been destroyed");
    7040           0 :     return NS_OK;
    7041             :   }
    7042           0 :   if (stage == eBeforeToggle) {
    7043           0 :     profiler_add_marker("Fullscreen transition start");
    7044           0 :     mWidget->PerformFullscreenTransition(nsIWidget::eBeforeFullscreenToggle,
    7045           0 :                                          mDuration.mFadeIn, mTransitionData,
    7046           0 :                                          this);
    7047           0 :   } else if (stage == eToggleFullscreen) {
    7048           0 :     profiler_add_marker("Fullscreen toggle start");
    7049           0 :     mFullscreenChangeStartTime = TimeStamp::Now();
    7050           0 :     if (MOZ_UNLIKELY(mWindow->mFullScreen != mFullscreen)) {
    7051             :       // This could happen in theory if several fullscreen requests in
    7052             :       // different direction happen continuously in a short time. We
    7053             :       // need to ensure the fullscreen state matches our target here,
    7054             :       // otherwise the widget would change the window state as if we
    7055             :       // toggle for Fullscreen Mode instead of Fullscreen API.
    7056           0 :       NS_WARNING("The fullscreen state of the window does not match");
    7057           0 :       mWindow->mFullScreen = mFullscreen;
    7058             :     }
    7059             :     // Toggle the fullscreen state on the widget
    7060           0 :     if (!mWindow->SetWidgetFullscreen(FullscreenReason::ForFullscreenAPI,
    7061           0 :                                       mFullscreen, mWidget, mScreen)) {
    7062             :       // Fail to setup the widget, call FinishFullscreenChange to
    7063             :       // complete fullscreen change directly.
    7064           0 :       mWindow->FinishFullscreenChange(mFullscreen);
    7065             :     }
    7066             :     // Set observer for the next content paint.
    7067           0 :     nsCOMPtr<nsIObserver> observer = new Observer(this);
    7068           0 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    7069           0 :     obs->AddObserver(observer, kPaintedTopic, false);
    7070             :     // There are several edge cases where we may never get the paint
    7071             :     // notification, including:
    7072             :     // 1. the window/tab is closed before the next paint;
    7073             :     // 2. the user has switched to another tab before we get here.
    7074             :     // Completely fixing those cases seems to be tricky, and since they
    7075             :     // should rarely happen, it probably isn't worth to fix. Hence we
    7076             :     // simply add a timeout here to ensure we never hang forever.
    7077             :     // In addition, if the page is complicated or the machine is less
    7078             :     // powerful, layout could take a long time, in which case, staying
    7079             :     // in black screen for that long could hurt user experience even
    7080             :     // more than exposing an intermediate state.
    7081           0 :     mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
    7082             :     uint32_t timeout =
    7083           0 :       Preferences::GetUint("full-screen-api.transition.timeout", 1000);
    7084           0 :     mTimer->Init(observer, timeout, nsITimer::TYPE_ONE_SHOT);
    7085           0 :   } else if (stage == eAfterToggle) {
    7086           0 :     Telemetry::AccumulateTimeDelta(Telemetry::FULLSCREEN_TRANSITION_BLACK_MS,
    7087           0 :                                    mFullscreenChangeStartTime);
    7088           0 :     mWidget->PerformFullscreenTransition(nsIWidget::eAfterFullscreenToggle,
    7089           0 :                                          mDuration.mFadeOut, mTransitionData,
    7090           0 :                                          this);
    7091           0 :   } else if (stage == eEnd) {
    7092           0 :     profiler_add_marker("Fullscreen transition end");
    7093             :   }
    7094           0 :   return NS_OK;
    7095             : }
    7096             : 
    7097           0 : NS_IMPL_ISUPPORTS(FullscreenTransitionTask::Observer, nsIObserver)
    7098             : 
    7099             : NS_IMETHODIMP
    7100           0 : FullscreenTransitionTask::Observer::Observe(nsISupports* aSubject,
    7101             :                                             const char* aTopic,
    7102             :                                             const char16_t* aData)
    7103             : {
    7104           0 :   bool shouldContinue = false;
    7105           0 :   if (strcmp(aTopic, FullscreenTransitionTask::kPaintedTopic) == 0) {
    7106           0 :     nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(aSubject));
    7107           0 :     nsCOMPtr<nsIWidget> widget = win ?
    7108           0 :       nsGlobalWindow::Cast(win)->GetMainWidget() : nullptr;
    7109           0 :     if (widget == mTask->mWidget) {
    7110             :       // The paint notification arrives first. Cancel the timer.
    7111           0 :       mTask->mTimer->Cancel();
    7112           0 :       shouldContinue = true;
    7113           0 :       profiler_add_marker("Fullscreen toggle end");
    7114             :     }
    7115             :   } else {
    7116             : #ifdef DEBUG
    7117           0 :     MOZ_ASSERT(strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC) == 0,
    7118             :                "Should only get fullscreen-painted or timer-callback");
    7119           0 :     nsCOMPtr<nsITimer> timer(do_QueryInterface(aSubject));
    7120           0 :     MOZ_ASSERT(timer && timer == mTask->mTimer,
    7121             :                "Should only trigger this with the timer the task created");
    7122             : #endif
    7123           0 :     shouldContinue = true;
    7124           0 :     profiler_add_marker("Fullscreen toggle timeout");
    7125             :   }
    7126           0 :   if (shouldContinue) {
    7127           0 :     nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
    7128           0 :     obs->RemoveObserver(this, kPaintedTopic);
    7129           0 :     mTask->mTimer = nullptr;
    7130           0 :     mTask->Run();
    7131             :   }
    7132           0 :   return NS_OK;
    7133             : }
    7134             : 
    7135             : static bool
    7136           0 : MakeWidgetFullscreen(nsGlobalWindow* aWindow, FullscreenReason aReason,
    7137             :                      bool aFullscreen)
    7138             : {
    7139           0 :   nsCOMPtr<nsIWidget> widget = aWindow->GetMainWidget();
    7140           0 :   if (!widget) {
    7141           0 :     return false;
    7142             :   }
    7143             : 
    7144           0 :   FullscreenTransitionDuration duration;
    7145           0 :   bool performTransition = false;
    7146           0 :   nsCOMPtr<nsISupports> transitionData;
    7147           0 :   if (aReason == FullscreenReason::ForFullscreenAPI) {
    7148           0 :     GetFullscreenTransitionDuration(aFullscreen, &duration);
    7149           0 :     if (!duration.IsSuppressed()) {
    7150           0 :       performTransition = widget->
    7151           0 :         PrepareForFullscreenTransition(getter_AddRefs(transitionData));
    7152             :     }
    7153             :   }
    7154             :   // We pass nullptr as the screen to SetWidgetFullscreen
    7155             :   // and FullscreenTransitionTask, as we do not wish to override
    7156             :   // the default screen selection behavior.  The screen containing
    7157             :   // most of the widget will be selected.
    7158           0 :   if (!performTransition) {
    7159           0 :     return aWindow->SetWidgetFullscreen(aReason, aFullscreen, widget, nullptr);
    7160             :   }
    7161             :   nsCOMPtr<nsIRunnable> task =
    7162             :     new FullscreenTransitionTask(duration, aWindow, aFullscreen,
    7163           0 :                                  widget, nullptr, transitionData);
    7164           0 :   task->Run();
    7165           0 :   return true;
    7166             : }
    7167             : 
    7168             : nsresult
    7169           0 : nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
    7170             :                                       bool aFullScreen)
    7171             : {
    7172           0 :   MOZ_ASSERT(IsOuterWindow());
    7173           0 :   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript(),
    7174             :              "Requires safe to run script as it "
    7175             :              "may call FinishDOMFullscreenChange");
    7176             : 
    7177           0 :   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
    7178             : 
    7179           0 :   MOZ_ASSERT(aReason != FullscreenReason::ForForceExitFullscreen || !aFullScreen,
    7180             :              "FullscreenReason::ForForceExitFullscreen can "
    7181             :              "only be used with exiting fullscreen");
    7182             : 
    7183             :   // Only chrome can change our fullscreen mode. Otherwise, the state
    7184             :   // can only be changed for DOM fullscreen.
    7185           0 :   if (aReason == FullscreenReason::ForFullscreenMode &&
    7186           0 :       !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
    7187           0 :     return NS_OK;
    7188             :   }
    7189             : 
    7190             :   // SetFullScreen needs to be called on the root window, so get that
    7191             :   // via the DocShell tree, and if we are not already the root,
    7192             :   // call SetFullScreen on that window instead.
    7193           0 :   nsCOMPtr<nsIDocShellTreeItem> rootItem;
    7194           0 :   mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
    7195           0 :   nsCOMPtr<nsPIDOMWindowOuter> window = rootItem ? rootItem->GetWindow() : nullptr;
    7196           0 :   if (!window)
    7197           0 :     return NS_ERROR_FAILURE;
    7198           0 :   if (rootItem != mDocShell)
    7199           0 :     return window->SetFullscreenInternal(aReason, aFullScreen);
    7200             : 
    7201             :   // make sure we don't try to set full screen on a non-chrome window,
    7202             :   // which might happen in embedding world
    7203           0 :   if (mDocShell->ItemType() != nsIDocShellTreeItem::typeChrome)
    7204           0 :     return NS_ERROR_FAILURE;
    7205             : 
    7206             :   // If we are already in full screen mode, just return.
    7207           0 :   if (mFullScreen == aFullScreen)
    7208           0 :     return NS_OK;
    7209             : 
    7210             :   // Note that although entering DOM fullscreen could also cause
    7211             :   // consequential calls to this method, those calls will be skipped
    7212             :   // at the condition above.
    7213           0 :   if (aReason == FullscreenReason::ForFullscreenMode) {
    7214           0 :     if (!aFullScreen && !mFullscreenMode) {
    7215             :       // If we are exiting fullscreen mode, but we actually didn't
    7216             :       // entered fullscreen mode, the fullscreen state was only for
    7217             :       // the Fullscreen API. Change the reason here so that we can
    7218             :       // perform transition for it.
    7219           0 :       aReason = FullscreenReason::ForFullscreenAPI;
    7220             :     } else {
    7221           0 :       mFullscreenMode = aFullScreen;
    7222             :     }
    7223             :   } else {
    7224             :     // If we are exiting from DOM fullscreen while we initially make
    7225             :     // the window fullscreen because of fullscreen mode, don't restore
    7226             :     // the window. But we still need to exit the DOM fullscreen state.
    7227           0 :     if (!aFullScreen && mFullscreenMode) {
    7228           0 :       FinishDOMFullscreenChange(mDoc, false);
    7229           0 :       return NS_OK;
    7230             :     }
    7231             :   }
    7232             : 
    7233             :   // Prevent chrome documents which are still loading from resizing
    7234             :   // the window after we set fullscreen mode.
    7235           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    7236           0 :   nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(treeOwnerAsWin));
    7237           0 :   if (aFullScreen && xulWin) {
    7238           0 :     xulWin->SetIntrinsicallySized(false);
    7239             :   }
    7240             : 
    7241             :   // Set this before so if widget sends an event indicating its
    7242             :   // gone full screen, the state trap above works.
    7243           0 :   mFullScreen = aFullScreen;
    7244             : 
    7245             :   // Sometimes we don't want the top-level widget to actually go fullscreen,
    7246             :   // for example in the B2G desktop client, we don't want the emulated screen
    7247             :   // dimensions to appear to increase when entering fullscreen mode; we just
    7248             :   // want the content to fill the entire client area of the emulator window.
    7249           0 :   if (!Preferences::GetBool("full-screen-api.ignore-widgets", false)) {
    7250           0 :     if (MakeWidgetFullscreen(this, aReason, aFullScreen)) {
    7251             :       // The rest of code for switching fullscreen is in nsGlobalWindow::
    7252             :       // FinishFullscreenChange() which will be called after sizemodechange
    7253             :       // event is dispatched.
    7254           0 :       return NS_OK;
    7255             :     }
    7256             :   }
    7257             : 
    7258           0 :   FinishFullscreenChange(aFullScreen);
    7259           0 :   return NS_OK;
    7260             : }
    7261             : 
    7262             : bool
    7263           0 : nsGlobalWindow::SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
    7264             :                                     nsIWidget* aWidget, nsIScreen* aScreen)
    7265             : {
    7266           0 :   MOZ_ASSERT(IsOuterWindow());
    7267           0 :   MOZ_ASSERT(this == GetTopInternal(), "Only topmost window should call this");
    7268           0 :   MOZ_ASSERT(!AsOuter()->GetFrameElementInternal(), "Content window should not call this");
    7269           0 :   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
    7270             : 
    7271           0 :   if (!NS_WARN_IF(!IsChromeWindow())) {
    7272           0 :     auto chromeWin = static_cast<nsGlobalChromeWindow*>(this);
    7273           0 :     if (!NS_WARN_IF(chromeWin->mFullscreenPresShell)) {
    7274           0 :       if (nsIPresShell* shell = mDocShell->GetPresShell()) {
    7275           0 :         if (nsRefreshDriver* rd = shell->GetRefreshDriver()) {
    7276           0 :           chromeWin->mFullscreenPresShell = do_GetWeakReference(shell);
    7277           0 :           MOZ_ASSERT(chromeWin->mFullscreenPresShell);
    7278           0 :           rd->SetIsResizeSuppressed();
    7279           0 :           rd->Freeze();
    7280             :         }
    7281             :       }
    7282             :     }
    7283             :   }
    7284           0 :   nsresult rv = aReason == FullscreenReason::ForFullscreenMode ?
    7285             :     // If we enter fullscreen for fullscreen mode, we want
    7286             :     // the native system behavior.
    7287           0 :     aWidget->MakeFullScreenWithNativeTransition(aIsFullscreen, aScreen) :
    7288           0 :     aWidget->MakeFullScreen(aIsFullscreen, aScreen);
    7289           0 :   return NS_SUCCEEDED(rv);
    7290             : }
    7291             : 
    7292             : /* virtual */ void
    7293           0 : nsGlobalWindow::FinishFullscreenChange(bool aIsFullscreen)
    7294             : {
    7295           0 :   MOZ_ASSERT(IsOuterWindow());
    7296             : 
    7297           0 :   if (aIsFullscreen != mFullScreen) {
    7298           0 :     NS_WARNING("Failed to toggle fullscreen state of the widget");
    7299             :     // We failed to make the widget enter fullscreen.
    7300             :     // Stop further changes and restore the state.
    7301           0 :     if (!aIsFullscreen) {
    7302           0 :       mFullScreen = false;
    7303           0 :       mFullscreenMode = false;
    7304             :     } else {
    7305           0 :       MOZ_ASSERT_UNREACHABLE("Failed to exit fullscreen?");
    7306             :       mFullScreen = true;
    7307             :       // We don't know how code can reach here. Not sure
    7308             :       // what value should be set for fullscreen mode.
    7309             :       mFullscreenMode = false;
    7310             :     }
    7311           0 :     return;
    7312             :   }
    7313             : 
    7314             :   // Note that we must call this to toggle the DOM fullscreen state
    7315             :   // of the document before dispatching the "fullscreen" event, so
    7316             :   // that the chrome can distinguish between browser fullscreen mode
    7317             :   // and DOM fullscreen.
    7318           0 :   FinishDOMFullscreenChange(mDoc, mFullScreen);
    7319             : 
    7320             :   // dispatch a "fullscreen" DOM event so that XUL apps can
    7321             :   // respond visually if we are kicked into full screen mode
    7322           0 :   DispatchCustomEvent(NS_LITERAL_STRING("fullscreen"));
    7323             : 
    7324           0 :   if (!NS_WARN_IF(!IsChromeWindow())) {
    7325           0 :     auto chromeWin = static_cast<nsGlobalChromeWindow*>(this);
    7326           0 :     if (nsCOMPtr<nsIPresShell> shell =
    7327           0 :         do_QueryReferent(chromeWin->mFullscreenPresShell)) {
    7328           0 :       if (nsRefreshDriver* rd = shell->GetRefreshDriver()) {
    7329           0 :         rd->Thaw();
    7330             :       }
    7331           0 :       chromeWin->mFullscreenPresShell = nullptr;
    7332             :     }
    7333             :   }
    7334             : 
    7335           0 :   if (!mWakeLock && mFullScreen) {
    7336             :     RefPtr<power::PowerManagerService> pmService =
    7337           0 :       power::PowerManagerService::GetInstance();
    7338           0 :     if (!pmService) {
    7339           0 :       return;
    7340             :     }
    7341             : 
    7342             :     // XXXkhuey using the inner here, do we need to do something if it changes?
    7343           0 :     ErrorResult rv;
    7344           0 :     mWakeLock = pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"),
    7345           0 :                                        AsOuter()->GetCurrentInnerWindow(), rv);
    7346           0 :     NS_WARNING_ASSERTION(!rv.Failed(), "Failed to lock the wakelock");
    7347           0 :     rv.SuppressException();
    7348           0 :   } else if (mWakeLock && !mFullScreen) {
    7349           0 :     ErrorResult rv;
    7350           0 :     mWakeLock->Unlock(rv);
    7351           0 :     mWakeLock = nullptr;
    7352           0 :     rv.SuppressException();
    7353             :   }
    7354             : }
    7355             : 
    7356             : bool
    7357           5 : nsGlobalWindow::FullScreen() const
    7358             : {
    7359           5 :   MOZ_ASSERT(IsOuterWindow());
    7360             : 
    7361           5 :   NS_ENSURE_TRUE(mDocShell, mFullScreen);
    7362             : 
    7363             :   // Get the fullscreen value of the root window, to always have the value
    7364             :   // accurate, even when called from content.
    7365          10 :   nsCOMPtr<nsIDocShellTreeItem> rootItem;
    7366           5 :   mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
    7367           5 :   if (rootItem == mDocShell) {
    7368           5 :     if (!XRE_IsContentProcess()) {
    7369             :       // We are the root window. Return our internal value.
    7370           5 :       return mFullScreen;
    7371             :     }
    7372           0 :     if (nsCOMPtr<nsIWidget> widget = GetNearestWidget()) {
    7373             :       // We are in content process, figure out the value from
    7374             :       // the sizemode of the puppet widget.
    7375           0 :       return widget->SizeMode() == nsSizeMode_Fullscreen;
    7376             :     }
    7377           0 :     return false;
    7378             :   }
    7379             : 
    7380           0 :   nsCOMPtr<nsPIDOMWindowOuter> window = rootItem->GetWindow();
    7381           0 :   NS_ENSURE_TRUE(window, mFullScreen);
    7382             : 
    7383           0 :   return nsGlobalWindow::Cast(window)->FullScreen();
    7384             : }
    7385             : 
    7386             : bool
    7387           5 : nsGlobalWindow::GetFullScreenOuter()
    7388             : {
    7389           5 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    7390           5 :   return FullScreen();
    7391             : }
    7392             : 
    7393             : bool
    7394           5 : nsGlobalWindow::GetFullScreen(ErrorResult& aError)
    7395             : {
    7396           5 :   FORWARD_TO_OUTER_OR_THROW(GetFullScreenOuter, (), aError, false);
    7397             : }
    7398             : 
    7399             : bool
    7400           8 : nsGlobalWindow::GetFullScreen()
    7401             : {
    7402           8 :   FORWARD_TO_INNER(GetFullScreen, (), false);
    7403             : 
    7404           8 :   ErrorResult dummy;
    7405           4 :   bool fullscreen = GetFullScreen(dummy);
    7406           4 :   dummy.SuppressException();
    7407           4 :   return fullscreen;
    7408             : }
    7409             : 
    7410             : void
    7411           1 : nsGlobalWindow::Dump(const nsAString& aStr)
    7412             : {
    7413           1 :   if (!nsContentUtils::DOMWindowDumpEnabled()) {
    7414           0 :     return;
    7415             :   }
    7416             : 
    7417           1 :   char *cstr = ToNewUTF8String(aStr);
    7418             : 
    7419             : #if defined(XP_MACOSX)
    7420             :   // have to convert \r to \n so that printing to the console works
    7421             :   char *c = cstr, *cEnd = cstr + strlen(cstr);
    7422             :   while (c < cEnd) {
    7423             :     if (*c == '\r')
    7424             :       *c = '\n';
    7425             :     c++;
    7426             :   }
    7427             : #endif
    7428             : 
    7429           1 :   if (cstr) {
    7430           1 :     MOZ_LOG(nsContentUtils::DOMDumpLog(), LogLevel::Debug, ("[Window.Dump] %s", cstr));
    7431             : #ifdef XP_WIN
    7432             :     PrintToDebugger(cstr);
    7433             : #endif
    7434             : #ifdef ANDROID
    7435             :     __android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
    7436             : #endif
    7437           1 :     FILE *fp = gDumpFile ? gDumpFile : stdout;
    7438           1 :     fputs(cstr, fp);
    7439           1 :     fflush(fp);
    7440           1 :     free(cstr);
    7441             :   }
    7442             : }
    7443             : 
    7444             : void
    7445           0 : nsGlobalWindow::EnsureReflowFlushAndPaint()
    7446             : {
    7447           0 :   MOZ_ASSERT(IsOuterWindow());
    7448           0 :   NS_ASSERTION(mDocShell, "EnsureReflowFlushAndPaint() called with no "
    7449             :                "docshell!");
    7450             : 
    7451           0 :   if (!mDocShell)
    7452           0 :     return;
    7453             : 
    7454           0 :   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
    7455             : 
    7456           0 :   if (!presShell)
    7457           0 :     return;
    7458             : 
    7459             :   // Flush pending reflows.
    7460           0 :   if (mDoc) {
    7461           0 :     mDoc->FlushPendingNotifications(FlushType::Layout);
    7462             :   }
    7463             : 
    7464             :   // Unsuppress painting.
    7465           0 :   presShell->UnsuppressPainting();
    7466             : }
    7467             : 
    7468             : // static
    7469             : void
    7470           0 : nsGlobalWindow::MakeScriptDialogTitle(nsAString& aOutTitle,
    7471             :                                       nsIPrincipal* aSubjectPrincipal)
    7472             : {
    7473           0 :   MOZ_ASSERT(aSubjectPrincipal);
    7474             : 
    7475           0 :   aOutTitle.Truncate();
    7476             : 
    7477             :   // Try to get a host from the running principal -- this will do the
    7478             :   // right thing for javascript: and data: documents.
    7479             : 
    7480           0 :   nsCOMPtr<nsIURI> uri;
    7481           0 :   nsresult rv = aSubjectPrincipal->GetURI(getter_AddRefs(uri));
    7482             :   // Note - The check for the current JSContext here isn't necessarily sensical.
    7483             :   // It's just designed to preserve existing behavior during a mass-conversion
    7484             :   // patch.
    7485           0 :   if (NS_SUCCEEDED(rv) && uri && nsContentUtils::GetCurrentJSContext()) {
    7486             :     // remove user:pass for privacy and spoof prevention
    7487             : 
    7488           0 :     nsCOMPtr<nsIURIFixup> fixup(do_GetService(NS_URIFIXUP_CONTRACTID));
    7489           0 :     if (fixup) {
    7490           0 :       nsCOMPtr<nsIURI> fixedURI;
    7491           0 :       rv = fixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
    7492           0 :       if (NS_SUCCEEDED(rv) && fixedURI) {
    7493           0 :         nsAutoCString host;
    7494           0 :         fixedURI->GetHost(host);
    7495             : 
    7496           0 :         if (!host.IsEmpty()) {
    7497             :           // if this URI has a host we'll show it. For other
    7498             :           // schemes (e.g. file:) we fall back to the localized
    7499             :           // generic string
    7500             : 
    7501           0 :           nsAutoCString prepath;
    7502           0 :           fixedURI->GetPrePath(prepath);
    7503             : 
    7504           0 :           NS_ConvertUTF8toUTF16 ucsPrePath(prepath);
    7505           0 :           const char16_t *formatStrings[] = { ucsPrePath.get() };
    7506           0 :           nsXPIDLString tempString;
    7507             :           nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    7508             :                                                 "ScriptDlgHeading",
    7509             :                                                 formatStrings,
    7510           0 :                                                 tempString);
    7511           0 :           aOutTitle = tempString;
    7512             :         }
    7513             :       }
    7514             :     }
    7515             :   }
    7516             : 
    7517           0 :   if (aOutTitle.IsEmpty()) {
    7518             :     // We didn't find a host so use the generic heading
    7519           0 :     nsXPIDLString tempString;
    7520             :     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    7521             :                                        "ScriptDlgGenericHeading",
    7522           0 :                                        tempString);
    7523           0 :     aOutTitle = tempString;
    7524             :   }
    7525             : 
    7526             :   // Just in case
    7527           0 :   if (aOutTitle.IsEmpty()) {
    7528           0 :     NS_WARNING("could not get ScriptDlgGenericHeading string from string bundle");
    7529           0 :     aOutTitle.AssignLiteral("[Script]");
    7530             :   }
    7531           0 : }
    7532             : 
    7533             : bool
    7534           0 : nsGlobalWindow::CanMoveResizeWindows(CallerType aCallerType)
    7535             : {
    7536           0 :   MOZ_ASSERT(IsOuterWindow());
    7537             : 
    7538             :   // When called from chrome, we can avoid the following checks.
    7539           0 :   if (aCallerType != CallerType::System) {
    7540             :     // Don't allow scripts to move or resize windows that were not opened by a
    7541             :     // script.
    7542           0 :     if (!mHadOriginalOpener) {
    7543           0 :       return false;
    7544             :     }
    7545             : 
    7546           0 :     if (!CanSetProperty("dom.disable_window_move_resize")) {
    7547           0 :       return false;
    7548             :     }
    7549             : 
    7550             :     // Ignore the request if we have more than one tab in the window.
    7551           0 :     uint32_t itemCount = 0;
    7552           0 :     if (XRE_IsContentProcess()) {
    7553           0 :       nsCOMPtr<nsIDocShell> docShell = GetDocShell();
    7554           0 :       if (docShell) {
    7555           0 :         nsCOMPtr<nsITabChild> child = docShell->GetTabChild();
    7556           0 :         if (child) {
    7557           0 :           child->SendGetTabCount(&itemCount);
    7558             :         }
    7559             :       }
    7560             :     } else {
    7561           0 :       nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
    7562           0 :       if (!treeOwner || NS_FAILED(treeOwner->GetTabCount(&itemCount))) {
    7563           0 :         itemCount = 0;
    7564             :       }
    7565             :     }
    7566           0 :     if (itemCount > 1) {
    7567           0 :       return false;
    7568             :     }
    7569             :   }
    7570             : 
    7571           0 :   if (mDocShell) {
    7572             :     bool allow;
    7573           0 :     nsresult rv = mDocShell->GetAllowWindowControl(&allow);
    7574           0 :     if (NS_SUCCEEDED(rv) && !allow)
    7575           0 :       return false;
    7576             :   }
    7577             : 
    7578           0 :   if (gMouseDown && !gDragServiceDisabled) {
    7579             :     nsCOMPtr<nsIDragService> ds =
    7580           0 :       do_GetService("@mozilla.org/widget/dragservice;1");
    7581           0 :     if (ds) {
    7582           0 :       gDragServiceDisabled = true;
    7583           0 :       ds->Suppress();
    7584             :     }
    7585             :   }
    7586           0 :   return true;
    7587             : }
    7588             : 
    7589             : bool
    7590           0 : nsGlobalWindow::AlertOrConfirm(bool aAlert,
    7591             :                                const nsAString& aMessage,
    7592             :                                nsIPrincipal& aSubjectPrincipal,
    7593             :                                ErrorResult& aError)
    7594             : {
    7595             :   // XXX This method is very similar to nsGlobalWindow::Prompt, make
    7596             :   // sure any modifications here don't need to happen over there!
    7597           0 :   MOZ_ASSERT(IsOuterWindow());
    7598             : 
    7599           0 :   if (!AreDialogsEnabled()) {
    7600             :     // Just silently return.  In the case of alert(), the return value is
    7601             :     // ignored.  In the case of confirm(), returning false is the same thing as
    7602             :     // would happen if the user cancels.
    7603           0 :     return false;
    7604             :   }
    7605             : 
    7606             :   // Reset popup state while opening a modal dialog, and firing events
    7607             :   // about the dialog, to prevent the current state from being active
    7608             :   // the whole time a modal dialog is open.
    7609           0 :   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    7610             : 
    7611             :   // Before bringing up the window, unsuppress painting and flush
    7612             :   // pending reflows.
    7613           0 :   EnsureReflowFlushAndPaint();
    7614             : 
    7615           0 :   nsAutoString title;
    7616           0 :   MakeScriptDialogTitle(title, &aSubjectPrincipal);
    7617             : 
    7618             :   // Remove non-terminating null characters from the
    7619             :   // string. See bug #310037.
    7620           0 :   nsAutoString final;
    7621           0 :   nsContentUtils::StripNullChars(aMessage, final);
    7622             : 
    7623             :   nsresult rv;
    7624             :   nsCOMPtr<nsIPromptFactory> promptFac =
    7625           0 :     do_GetService("@mozilla.org/prompter;1", &rv);
    7626           0 :   if (NS_FAILED(rv)) {
    7627           0 :     aError.Throw(rv);
    7628           0 :     return false;
    7629             :   }
    7630             : 
    7631           0 :   nsCOMPtr<nsIPrompt> prompt;
    7632           0 :   aError = promptFac->GetPrompt(AsOuter(), NS_GET_IID(nsIPrompt),
    7633           0 :                                 getter_AddRefs(prompt));
    7634           0 :   if (aError.Failed()) {
    7635           0 :     return false;
    7636             :   }
    7637             : 
    7638             :   // Always allow tab modal prompts for alert and confirm.
    7639           0 :   if (nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt)) {
    7640           0 :     promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), true);
    7641             :   }
    7642             : 
    7643           0 :   bool result = false;
    7644           0 :   nsAutoSyncOperation sync(mDoc);
    7645           0 :   if (ShouldPromptToBlockDialogs()) {
    7646           0 :     bool disallowDialog = false;
    7647           0 :     nsXPIDLString label;
    7648             :     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    7649           0 :                                        "ScriptDialogLabel", label);
    7650             : 
    7651           0 :     aError = aAlert ?
    7652           0 :                prompt->AlertCheck(title.get(), final.get(), label.get(),
    7653           0 :                                   &disallowDialog) :
    7654           0 :                prompt->ConfirmCheck(title.get(), final.get(), label.get(),
    7655           0 :                                     &disallowDialog, &result);
    7656             : 
    7657           0 :     if (disallowDialog)
    7658           0 :       DisableDialogs();
    7659             :   } else {
    7660           0 :     aError = aAlert ?
    7661           0 :                prompt->Alert(title.get(), final.get()) :
    7662           0 :                prompt->Confirm(title.get(), final.get(), &result);
    7663             :   }
    7664             : 
    7665           0 :   return result;
    7666             : }
    7667             : 
    7668             : void
    7669           0 : nsGlobalWindow::Alert(nsIPrincipal& aSubjectPrincipal,
    7670             :                       ErrorResult& aError)
    7671             : {
    7672           0 :   MOZ_ASSERT(IsInnerWindow());
    7673           0 :   Alert(EmptyString(), aSubjectPrincipal, aError);
    7674           0 : }
    7675             : 
    7676             : void
    7677           0 : nsGlobalWindow::AlertOuter(const nsAString& aMessage,
    7678             :                            nsIPrincipal& aSubjectPrincipal,
    7679             :                            ErrorResult& aError)
    7680             : {
    7681           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    7682           0 :   AlertOrConfirm(/* aAlert = */ true, aMessage, aSubjectPrincipal, aError);
    7683           0 : }
    7684             : 
    7685             : void
    7686           0 : nsGlobalWindow::Alert(const nsAString& aMessage,
    7687             :                       nsIPrincipal& aSubjectPrincipal,
    7688             :                       ErrorResult& aError)
    7689             : {
    7690           0 :   FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError),
    7691             :                             aError, );
    7692             : }
    7693             : 
    7694             : bool
    7695           0 : nsGlobalWindow::ConfirmOuter(const nsAString& aMessage,
    7696             :                              nsIPrincipal& aSubjectPrincipal,
    7697             :                              ErrorResult& aError)
    7698             : {
    7699           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    7700             : 
    7701             :   return AlertOrConfirm(/* aAlert = */ false, aMessage, aSubjectPrincipal,
    7702           0 :                         aError);
    7703             : }
    7704             : 
    7705             : bool
    7706           0 : nsGlobalWindow::Confirm(const nsAString& aMessage,
    7707             :                         nsIPrincipal& aSubjectPrincipal,
    7708             :                         ErrorResult& aError)
    7709             : {
    7710           0 :   FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError),
    7711             :                             aError, false);
    7712             : }
    7713             : 
    7714             : already_AddRefed<Promise>
    7715           0 : nsGlobalWindow::Fetch(const RequestOrUSVString& aInput,
    7716             :                       const RequestInit& aInit,
    7717             :                       CallerType aCallerType, ErrorResult& aRv)
    7718             : {
    7719           0 :   return FetchRequest(this, aInput, aInit, aCallerType, aRv);
    7720             : }
    7721             : 
    7722             : void
    7723           0 : nsGlobalWindow::PromptOuter(const nsAString& aMessage,
    7724             :                             const nsAString& aInitial,
    7725             :                             nsAString& aReturn,
    7726             :                             nsIPrincipal& aSubjectPrincipal,
    7727             :                             ErrorResult& aError)
    7728             : {
    7729             :   // XXX This method is very similar to nsGlobalWindow::AlertOrConfirm, make
    7730             :   // sure any modifications here don't need to happen over there!
    7731           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    7732             : 
    7733           0 :   SetDOMStringToNull(aReturn);
    7734             : 
    7735           0 :   if (!AreDialogsEnabled()) {
    7736             :     // Return null, as if the user just canceled the prompt.
    7737           0 :     return;
    7738             :   }
    7739             : 
    7740             :   // Reset popup state while opening a modal dialog, and firing events
    7741             :   // about the dialog, to prevent the current state from being active
    7742             :   // the whole time a modal dialog is open.
    7743           0 :   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    7744             : 
    7745             :   // Before bringing up the window, unsuppress painting and flush
    7746             :   // pending reflows.
    7747           0 :   EnsureReflowFlushAndPaint();
    7748             : 
    7749           0 :   nsAutoString title;
    7750           0 :   MakeScriptDialogTitle(title, &aSubjectPrincipal);
    7751             : 
    7752             :   // Remove non-terminating null characters from the
    7753             :   // string. See bug #310037.
    7754           0 :   nsAutoString fixedMessage, fixedInitial;
    7755           0 :   nsContentUtils::StripNullChars(aMessage, fixedMessage);
    7756           0 :   nsContentUtils::StripNullChars(aInitial, fixedInitial);
    7757             : 
    7758             :   nsresult rv;
    7759             :   nsCOMPtr<nsIPromptFactory> promptFac =
    7760           0 :     do_GetService("@mozilla.org/prompter;1", &rv);
    7761           0 :   if (NS_FAILED(rv)) {
    7762           0 :     aError.Throw(rv);
    7763           0 :     return;
    7764             :   }
    7765             : 
    7766           0 :   nsCOMPtr<nsIPrompt> prompt;
    7767           0 :   aError = promptFac->GetPrompt(AsOuter(), NS_GET_IID(nsIPrompt),
    7768           0 :                                 getter_AddRefs(prompt));
    7769           0 :   if (aError.Failed()) {
    7770           0 :     return;
    7771             :   }
    7772             : 
    7773             :   // Always allow tab modal prompts for prompt.
    7774           0 :   if (nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt)) {
    7775           0 :     promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), true);
    7776             :   }
    7777             : 
    7778             :   // Pass in the default value, if any.
    7779           0 :   char16_t *inoutValue = ToNewUnicode(fixedInitial);
    7780           0 :   bool disallowDialog = false;
    7781             : 
    7782           0 :   nsXPIDLString label;
    7783           0 :   if (ShouldPromptToBlockDialogs()) {
    7784             :     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    7785           0 :                                        "ScriptDialogLabel", label);
    7786             :   }
    7787             : 
    7788           0 :   nsAutoSyncOperation sync(mDoc);
    7789             :   bool ok;
    7790           0 :   aError = prompt->Prompt(title.get(), fixedMessage.get(),
    7791           0 :                           &inoutValue, label.get(), &disallowDialog, &ok);
    7792             : 
    7793           0 :   if (disallowDialog) {
    7794           0 :     DisableDialogs();
    7795             :   }
    7796             : 
    7797           0 :   if (aError.Failed()) {
    7798           0 :     return;
    7799             :   }
    7800             : 
    7801           0 :   nsAdoptingString outValue(inoutValue);
    7802             : 
    7803           0 :   if (ok && outValue) {
    7804           0 :     aReturn.Assign(outValue);
    7805             :   }
    7806             : }
    7807             : 
    7808             : void
    7809           0 : nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
    7810             :                        nsAString& aReturn,
    7811             :                        nsIPrincipal& aSubjectPrincipal,
    7812             :                        ErrorResult& aError)
    7813             : {
    7814           0 :   FORWARD_TO_OUTER_OR_THROW(PromptOuter,
    7815             :                             (aMessage, aInitial, aReturn, aSubjectPrincipal,
    7816             :                              aError),
    7817             :                             aError, );
    7818             : }
    7819             : 
    7820             : void
    7821           0 : nsGlobalWindow::FocusOuter(ErrorResult& aError)
    7822             : {
    7823           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    7824             : 
    7825           0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    7826           0 :   if (!fm) {
    7827           0 :     return;
    7828             :   }
    7829             : 
    7830           0 :   nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
    7831             : 
    7832           0 :   bool isVisible = false;
    7833           0 :   if (baseWin) {
    7834           0 :     baseWin->GetVisibility(&isVisible);
    7835             :   }
    7836             : 
    7837           0 :   if (!isVisible) {
    7838             :     // A hidden tab is being focused, ignore this call.
    7839           0 :     return;
    7840             :   }
    7841             : 
    7842           0 :   nsCOMPtr<nsPIDOMWindowInner> caller = do_QueryInterface(GetEntryGlobal());
    7843           0 :   nsPIDOMWindowOuter* callerOuter = caller ? caller->GetOuterWindow() : nullptr;
    7844           0 :   nsCOMPtr<nsPIDOMWindowOuter> opener = GetOpener();
    7845             : 
    7846             :   // Enforce dom.disable_window_flip (for non-chrome), but still allow the
    7847             :   // window which opened us to raise us at times when popups are allowed
    7848             :   // (bugs 355482 and 369306).
    7849           0 :   bool canFocus = CanSetProperty("dom.disable_window_flip") ||
    7850           0 :                     (opener == callerOuter &&
    7851           0 :                      RevisePopupAbuseLevel(gPopupControlState) < openAbused);
    7852             : 
    7853           0 :   nsCOMPtr<mozIDOMWindowProxy> activeDOMWindow;
    7854           0 :   fm->GetActiveWindow(getter_AddRefs(activeDOMWindow));
    7855             : 
    7856           0 :   nsCOMPtr<nsIDocShellTreeItem> rootItem;
    7857           0 :   mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
    7858           0 :   nsCOMPtr<nsPIDOMWindowOuter> rootWin = rootItem ? rootItem->GetWindow() : nullptr;
    7859           0 :   auto* activeWindow = nsPIDOMWindowOuter::From(activeDOMWindow);
    7860           0 :   bool isActive = (rootWin == activeWindow);
    7861             : 
    7862           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    7863           0 :   if (treeOwnerAsWin && (canFocus || isActive)) {
    7864           0 :     bool isEnabled = true;
    7865           0 :     if (NS_SUCCEEDED(treeOwnerAsWin->GetEnabled(&isEnabled)) && !isEnabled) {
    7866           0 :       NS_WARNING( "Should not try to set the focus on a disabled window" );
    7867           0 :       return;
    7868             :     }
    7869             : 
    7870             :     // XXXndeakin not sure what this is for or if it should go somewhere else
    7871           0 :     nsCOMPtr<nsIEmbeddingSiteWindow> embeddingWin(do_GetInterface(treeOwnerAsWin));
    7872           0 :     if (embeddingWin)
    7873           0 :       embeddingWin->SetFocus();
    7874             :   }
    7875             : 
    7876           0 :   if (!mDocShell) {
    7877           0 :     return;
    7878             :   }
    7879             : 
    7880           0 :   nsCOMPtr<nsIPresShell> presShell;
    7881             :   // Don't look for a presshell if we're a root chrome window that's got
    7882             :   // about:blank loaded.  We don't want to focus our widget in that case.
    7883             :   // XXXbz should we really be checking for IsInitialDocument() instead?
    7884           0 :   bool lookForPresShell = true;
    7885           0 :   if (mDocShell->ItemType() == nsIDocShellTreeItem::typeChrome &&
    7886           0 :       GetPrivateRoot() == AsOuter() && mDoc) {
    7887           0 :     nsIURI* ourURI = mDoc->GetDocumentURI();
    7888           0 :     if (ourURI) {
    7889           0 :       lookForPresShell = !NS_IsAboutBlank(ourURI);
    7890             :     }
    7891             :   }
    7892             : 
    7893           0 :   if (lookForPresShell) {
    7894           0 :     mDocShell->GetEldestPresShell(getter_AddRefs(presShell));
    7895             :   }
    7896             : 
    7897           0 :   nsCOMPtr<nsIDocShellTreeItem> parentDsti;
    7898           0 :   mDocShell->GetParent(getter_AddRefs(parentDsti));
    7899             : 
    7900             :   // set the parent's current focus to the frame containing this window.
    7901             :   nsCOMPtr<nsPIDOMWindowOuter> parent =
    7902           0 :     parentDsti ? parentDsti->GetWindow() : nullptr;
    7903           0 :   if (parent) {
    7904           0 :     nsCOMPtr<nsIDocument> parentdoc = parent->GetDoc();
    7905           0 :     if (!parentdoc) {
    7906           0 :       return;
    7907             :     }
    7908             : 
    7909           0 :     nsIContent* frame = parentdoc->FindContentForSubDocument(mDoc);
    7910           0 :     nsCOMPtr<nsIDOMElement> frameElement = do_QueryInterface(frame);
    7911           0 :     if (frameElement) {
    7912           0 :       uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
    7913           0 :       if (canFocus)
    7914           0 :         flags |= nsIFocusManager::FLAG_RAISE;
    7915           0 :       aError = fm->SetFocus(frameElement, flags);
    7916             :     }
    7917           0 :     return;
    7918             :   }
    7919             : 
    7920           0 :   if (canFocus) {
    7921             :     // if there is no parent, this must be a toplevel window, so raise the
    7922             :     // window if canFocus is true. If this is a child process, the raise
    7923             :     // window request will get forwarded to the parent by the puppet widget.
    7924           0 :     aError = fm->SetActiveWindow(AsOuter());
    7925             :   }
    7926             : }
    7927             : 
    7928             : void
    7929           0 : nsGlobalWindow::Focus(ErrorResult& aError)
    7930             : {
    7931           0 :   FORWARD_TO_OUTER_OR_THROW(FocusOuter, (aError), aError, );
    7932             : }
    7933             : 
    7934             : nsresult
    7935           0 : nsGlobalWindow::Focus()
    7936             : {
    7937           0 :   FORWARD_TO_INNER(Focus, (), NS_ERROR_UNEXPECTED);
    7938             : 
    7939           0 :   ErrorResult rv;
    7940           0 :   Focus(rv);
    7941             : 
    7942           0 :   return rv.StealNSResult();
    7943             : }
    7944             : 
    7945             : void
    7946           0 : nsGlobalWindow::BlurOuter()
    7947             : {
    7948           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    7949             : 
    7950             :   // If dom.disable_window_flip == true, then content should not be allowed
    7951             :   // to call this function (this would allow popunders, bug 369306)
    7952           0 :   if (!CanSetProperty("dom.disable_window_flip")) {
    7953           0 :     return;
    7954             :   }
    7955             : 
    7956             :   // If embedding apps don't implement nsIEmbeddingSiteWindow, we
    7957             :   // shouldn't throw exceptions to web content.
    7958             : 
    7959           0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
    7960           0 :   nsCOMPtr<nsIEmbeddingSiteWindow> siteWindow(do_GetInterface(treeOwner));
    7961           0 :   if (siteWindow) {
    7962             :     // This method call may cause mDocShell to become nullptr.
    7963           0 :     siteWindow->Blur();
    7964             : 
    7965             :     // if the root is focused, clear the focus
    7966           0 :     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    7967           0 :     if (fm && mDoc) {
    7968           0 :       nsCOMPtr<nsIDOMElement> element;
    7969           0 :       fm->GetFocusedElementForWindow(AsOuter(), false, nullptr, getter_AddRefs(element));
    7970           0 :       nsCOMPtr<nsIContent> content = do_QueryInterface(element);
    7971           0 :       if (content == mDoc->GetRootElement()) {
    7972           0 :         fm->ClearFocus(AsOuter());
    7973             :       }
    7974             :     }
    7975             :   }
    7976             : }
    7977             : 
    7978             : void
    7979           0 : nsGlobalWindow::Blur(ErrorResult& aError)
    7980             : {
    7981           0 :   FORWARD_TO_OUTER_OR_THROW(BlurOuter, (), aError, );
    7982             : }
    7983             : 
    7984             : void
    7985           0 : nsGlobalWindow::BackOuter(ErrorResult& aError)
    7986             : {
    7987           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    7988             : 
    7989           0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    7990           0 :   if (!webNav) {
    7991           0 :     aError.Throw(NS_ERROR_FAILURE);
    7992           0 :     return;
    7993             :   }
    7994             : 
    7995           0 :   aError = webNav->GoBack();
    7996             : }
    7997             : 
    7998             : void
    7999           0 : nsGlobalWindow::Back(ErrorResult& aError)
    8000             : {
    8001           0 :   FORWARD_TO_OUTER_OR_THROW(BackOuter, (aError), aError, );
    8002             : }
    8003             : 
    8004             : void
    8005           0 : nsGlobalWindow::ForwardOuter(ErrorResult& aError)
    8006             : {
    8007           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8008             : 
    8009           0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    8010           0 :   if (!webNav) {
    8011           0 :     aError.Throw(NS_ERROR_FAILURE);
    8012           0 :     return;
    8013             :   }
    8014             : 
    8015           0 :   aError = webNav->GoForward();
    8016             : }
    8017             : 
    8018             : void
    8019           0 : nsGlobalWindow::Forward(ErrorResult& aError)
    8020             : {
    8021           0 :   FORWARD_TO_OUTER_OR_THROW(ForwardOuter, (aError), aError, );
    8022             : }
    8023             : 
    8024             : void
    8025           0 : nsGlobalWindow::HomeOuter(nsIPrincipal& aSubjectPrincipal, ErrorResult& aError)
    8026             : {
    8027           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8028             : 
    8029           0 :   if (!mDocShell) {
    8030           0 :     return;
    8031             :   }
    8032             : 
    8033             :   nsAdoptingString homeURL =
    8034           0 :     Preferences::GetLocalizedString(PREF_BROWSER_STARTUP_HOMEPAGE);
    8035             : 
    8036           0 :   if (homeURL.IsEmpty()) {
    8037             :     // if all else fails, use this
    8038             : #ifdef DEBUG_seth
    8039             :     printf("all else failed.  using %s as the home page\n", DEFAULT_HOME_PAGE);
    8040             : #endif
    8041           0 :     CopyASCIItoUTF16(DEFAULT_HOME_PAGE, homeURL);
    8042             :   }
    8043             : 
    8044             : #ifdef MOZ_PHOENIX
    8045             :   {
    8046             :     // Firefox lets the user specify multiple home pages to open in
    8047             :     // individual tabs by separating them with '|'. Since we don't
    8048             :     // have the machinery in place to easily open new tabs from here,
    8049             :     // simply truncate the homeURL at the first '|' character to
    8050             :     // prevent any possibilities of leaking the users list of home
    8051             :     // pages to the first home page.
    8052             :     //
    8053             :     // Once bug https://bugzilla.mozilla.org/show_bug.cgi?id=221445 is
    8054             :     // fixed we can revisit this.
    8055           0 :     int32_t firstPipe = homeURL.FindChar('|');
    8056             : 
    8057           0 :     if (firstPipe > 0) {
    8058           0 :       homeURL.Truncate(firstPipe);
    8059             :     }
    8060             :   }
    8061             : #endif
    8062             : 
    8063           0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    8064           0 :   if (!webNav) {
    8065           0 :     aError.Throw(NS_ERROR_FAILURE);
    8066           0 :     return;
    8067             :   }
    8068             : 
    8069           0 :   aError = webNav->LoadURI(homeURL.get(),
    8070             :                            nsIWebNavigation::LOAD_FLAGS_NONE,
    8071             :                            nullptr,
    8072             :                            nullptr,
    8073             :                            nullptr,
    8074           0 :                            &aSubjectPrincipal);
    8075             : }
    8076             : 
    8077             : void
    8078           0 : nsGlobalWindow::Home(nsIPrincipal& aSubjectPrincipal, ErrorResult& aError)
    8079             : {
    8080           0 :   FORWARD_TO_OUTER_OR_THROW(HomeOuter, (aSubjectPrincipal, aError), aError, );
    8081             : }
    8082             : 
    8083             : void
    8084           0 : nsGlobalWindow::StopOuter(ErrorResult& aError)
    8085             : {
    8086           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8087             : 
    8088           0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    8089           0 :   if (webNav) {
    8090           0 :     aError = webNav->Stop(nsIWebNavigation::STOP_ALL);
    8091             :   }
    8092           0 : }
    8093             : 
    8094             : void
    8095           0 : nsGlobalWindow::Stop(ErrorResult& aError)
    8096             : {
    8097           0 :   FORWARD_TO_OUTER_OR_THROW(StopOuter, (aError), aError, );
    8098             : }
    8099             : 
    8100             : void
    8101           0 : nsGlobalWindow::PrintOuter(ErrorResult& aError)
    8102             : {
    8103           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8104             : 
    8105             : #ifdef NS_PRINTING
    8106           0 :   if (Preferences::GetBool("dom.disable_window_print", false)) {
    8107           0 :     aError.Throw(NS_ERROR_NOT_AVAILABLE);
    8108           0 :     return;
    8109             :   }
    8110             : 
    8111           0 :   if (!AreDialogsEnabled()) {
    8112             :     // We probably want to keep throwing here; silently doing nothing is a bit
    8113             :     // weird given the typical use cases of print().
    8114           0 :     aError.Throw(NS_ERROR_NOT_AVAILABLE);
    8115           0 :     return;
    8116             :   }
    8117             : 
    8118           0 :   if (ShouldPromptToBlockDialogs() && !ConfirmDialogIfNeeded()) {
    8119           0 :     aError.Throw(NS_ERROR_NOT_AVAILABLE);
    8120           0 :     return;
    8121             :   }
    8122             : 
    8123           0 :   nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint;
    8124           0 :   if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint),
    8125             :                                 getter_AddRefs(webBrowserPrint)))) {
    8126           0 :     nsAutoSyncOperation sync(GetCurrentInnerWindowInternal() ?
    8127           0 :                                GetCurrentInnerWindowInternal()->mDoc.get() :
    8128           0 :                                nullptr);
    8129             : 
    8130             :     nsCOMPtr<nsIPrintSettingsService> printSettingsService =
    8131           0 :       do_GetService("@mozilla.org/gfx/printsettings-service;1");
    8132             : 
    8133           0 :     nsCOMPtr<nsIPrintSettings> printSettings;
    8134           0 :     if (printSettingsService) {
    8135             :       bool printSettingsAreGlobal =
    8136           0 :         Preferences::GetBool("print.use_global_printsettings", false);
    8137             : 
    8138           0 :       if (printSettingsAreGlobal) {
    8139           0 :         printSettingsService->GetGlobalPrintSettings(getter_AddRefs(printSettings));
    8140             : 
    8141           0 :         nsXPIDLString printerName;
    8142           0 :         printSettings->GetPrinterName(getter_Copies(printerName));
    8143             : 
    8144           0 :         bool shouldGetDefaultPrinterName = printerName.IsEmpty();
    8145             : #ifdef MOZ_X11
    8146             :         // In Linux, GTK backend does not support per printer settings.
    8147             :         // Calling GetDefaultPrinterName causes a sandbox violation (see Bug 1329216).
    8148             :         // The printer name is not needed anywhere else on Linux before it gets to the parent.
    8149             :         // In the parent, we will then query the default printer name if no name is set.
    8150             :         // Unless we are in the parent, we will skip this part.
    8151           0 :         if (!XRE_IsParentProcess()) {
    8152           0 :           shouldGetDefaultPrinterName = false;
    8153             :         }
    8154             : #endif
    8155           0 :         if (shouldGetDefaultPrinterName) {
    8156           0 :           printSettingsService->GetDefaultPrinterName(getter_Copies(printerName));
    8157           0 :           printSettings->SetPrinterName(printerName);
    8158             :         }
    8159           0 :         printSettingsService->InitPrintSettingsFromPrinter(printerName, printSettings);
    8160           0 :         printSettingsService->InitPrintSettingsFromPrefs(printSettings,
    8161             :                                                          true,
    8162           0 :                                                          nsIPrintSettings::kInitSaveAll);
    8163             :       } else {
    8164           0 :         printSettingsService->GetNewPrintSettings(getter_AddRefs(printSettings));
    8165             :       }
    8166             : 
    8167           0 :       EnterModalState();
    8168           0 :       webBrowserPrint->Print(printSettings, nullptr);
    8169           0 :       LeaveModalState();
    8170             : 
    8171             :       bool savePrintSettings =
    8172           0 :         Preferences::GetBool("print.save_print_settings", false);
    8173           0 :       if (printSettingsAreGlobal && savePrintSettings) {
    8174           0 :         printSettingsService->
    8175           0 :           SavePrintSettingsToPrefs(printSettings,
    8176             :                                    true,
    8177           0 :                                    nsIPrintSettings::kInitSaveAll);
    8178           0 :         printSettingsService->
    8179           0 :           SavePrintSettingsToPrefs(printSettings,
    8180             :                                    false,
    8181           0 :                                    nsIPrintSettings::kInitSavePrinterName);
    8182             :       }
    8183             :     } else {
    8184           0 :       webBrowserPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings));
    8185           0 :       webBrowserPrint->Print(printSettings, nullptr);
    8186             :     }
    8187             :   }
    8188             : #endif //NS_PRINTING
    8189             : }
    8190             : 
    8191             : void
    8192           0 : nsGlobalWindow::Print(ErrorResult& aError)
    8193             : {
    8194           0 :   FORWARD_TO_OUTER_OR_THROW(PrintOuter, (aError), aError, );
    8195             : }
    8196             : 
    8197             : void
    8198           0 : nsGlobalWindow::MoveToOuter(int32_t aXPos, int32_t aYPos,
    8199             :                             CallerType aCallerType, ErrorResult& aError)
    8200             : {
    8201           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8202             :   /*
    8203             :    * If caller is not chrome and the user has not explicitly exempted the site,
    8204             :    * prevent window.moveTo() by exiting early
    8205             :    */
    8206             : 
    8207           0 :   if (!CanMoveResizeWindows(aCallerType) || IsFrame()) {
    8208           0 :     return;
    8209             :   }
    8210             : 
    8211           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    8212           0 :   if (!treeOwnerAsWin) {
    8213           0 :     aError.Throw(NS_ERROR_FAILURE);
    8214           0 :     return;
    8215             :   }
    8216             : 
    8217             :   nsCOMPtr<nsIScreenManager> screenMgr =
    8218           0 :     do_GetService("@mozilla.org/gfx/screenmanager;1");
    8219           0 :   nsCOMPtr<nsIScreen> screen;
    8220           0 :   if (screenMgr) {
    8221           0 :     CSSIntSize size;
    8222           0 :     GetInnerSize(size);
    8223           0 :     screenMgr->ScreenForRect(aXPos, aYPos, size.width, size.height,
    8224           0 :                              getter_AddRefs(screen));
    8225             :   }
    8226             : 
    8227           0 :   if (screen) {
    8228             :     // On secondary displays, the "CSS px" coordinates are offset so that they
    8229             :     // share their origin with global desktop pixels, to avoid ambiguities in
    8230             :     // the coordinate space when there are displays with different DPIs.
    8231             :     // (See the corresponding code in GetScreenXY() above.)
    8232             :     int32_t screenLeftDeskPx, screenTopDeskPx, w, h;
    8233           0 :     screen->GetRectDisplayPix(&screenLeftDeskPx, &screenTopDeskPx, &w, &h);
    8234           0 :     CSSIntPoint cssPos(aXPos - screenLeftDeskPx, aYPos - screenTopDeskPx);
    8235           0 :     CheckSecurityLeftAndTop(&cssPos.x, &cssPos.y, aCallerType);
    8236             : 
    8237             :     double scale;
    8238           0 :     screen->GetDefaultCSSScaleFactor(&scale);
    8239           0 :     LayoutDevicePoint devPos = cssPos * CSSToLayoutDeviceScale(scale);
    8240             : 
    8241           0 :     screen->GetContentsScaleFactor(&scale);
    8242           0 :     DesktopPoint deskPos = devPos / DesktopToLayoutDeviceScale(scale);
    8243           0 :     aError = treeOwnerAsWin->SetPositionDesktopPix(screenLeftDeskPx + deskPos.x,
    8244           0 :                                                    screenTopDeskPx + deskPos.y);
    8245             :   } else {
    8246             :     // We couldn't find a screen? Just assume a 1:1 mapping.
    8247           0 :     CSSIntPoint cssPos(aXPos, aXPos);
    8248           0 :     CheckSecurityLeftAndTop(&cssPos.x, &cssPos.y, aCallerType);
    8249           0 :     LayoutDevicePoint devPos = cssPos * CSSToLayoutDeviceScale(1.0);
    8250           0 :     aError = treeOwnerAsWin->SetPosition(devPos.x, devPos.y);
    8251             :   }
    8252             : 
    8253           0 :   CheckForDPIChange();
    8254             : }
    8255             : 
    8256             : void
    8257           0 : nsGlobalWindow::MoveTo(int32_t aXPos, int32_t aYPos,
    8258             :                        CallerType aCallerType, ErrorResult& aError)
    8259             : {
    8260           0 :   FORWARD_TO_OUTER_OR_THROW(MoveToOuter,
    8261             :                             (aXPos, aYPos, aCallerType, aError), aError, );
    8262             : }
    8263             : 
    8264             : void
    8265           0 : nsGlobalWindow::MoveByOuter(int32_t aXDif, int32_t aYDif,
    8266             :                             CallerType aCallerType, ErrorResult& aError)
    8267             : {
    8268           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8269             : 
    8270             :   /*
    8271             :    * If caller is not chrome and the user has not explicitly exempted the site,
    8272             :    * prevent window.moveBy() by exiting early
    8273             :    */
    8274             : 
    8275           0 :   if (!CanMoveResizeWindows(aCallerType) || IsFrame()) {
    8276           0 :     return;
    8277             :   }
    8278             : 
    8279           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    8280           0 :   if (!treeOwnerAsWin) {
    8281           0 :     aError.Throw(NS_ERROR_FAILURE);
    8282           0 :     return;
    8283             :   }
    8284             : 
    8285             :   // To do this correctly we have to convert what we get from GetPosition
    8286             :   // into CSS pixels, add the arguments, do the security check, and
    8287             :   // then convert back to device pixels for the call to SetPosition.
    8288             : 
    8289             :   int32_t x, y;
    8290           0 :   aError = treeOwnerAsWin->GetPosition(&x, &y);
    8291           0 :   if (aError.Failed()) {
    8292           0 :     return;
    8293             :   }
    8294             : 
    8295             :   // mild abuse of a "size" object so we don't need more helper functions
    8296           0 :   nsIntSize cssPos(DevToCSSIntPixels(nsIntSize(x, y)));
    8297             : 
    8298           0 :   cssPos.width += aXDif;
    8299           0 :   cssPos.height += aYDif;
    8300             : 
    8301           0 :   CheckSecurityLeftAndTop(&cssPos.width, &cssPos.height, aCallerType);
    8302             : 
    8303           0 :   nsIntSize newDevPos(CSSToDevIntPixels(cssPos));
    8304             : 
    8305           0 :   aError = treeOwnerAsWin->SetPosition(newDevPos.width, newDevPos.height);
    8306             : 
    8307           0 :   CheckForDPIChange();
    8308             : }
    8309             : 
    8310             : void
    8311           0 : nsGlobalWindow::MoveBy(int32_t aXDif, int32_t aYDif,
    8312             :                        CallerType aCallerType, ErrorResult& aError)
    8313             : {
    8314           0 :   FORWARD_TO_OUTER_OR_THROW(MoveByOuter,
    8315             :                             (aXDif, aYDif, aCallerType, aError), aError, );
    8316             : }
    8317             : 
    8318             : nsresult
    8319           0 : nsGlobalWindow::MoveBy(int32_t aXDif, int32_t aYDif)
    8320             : {
    8321           0 :   FORWARD_TO_OUTER(MoveBy, (aXDif, aYDif), NS_ERROR_UNEXPECTED);
    8322             : 
    8323           0 :   ErrorResult rv;
    8324           0 :   MoveByOuter(aXDif, aYDif, CallerType::System, rv);
    8325             : 
    8326           0 :   return rv.StealNSResult();
    8327             : }
    8328             : 
    8329             : void
    8330           0 : nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight,
    8331             :                               CallerType aCallerType,
    8332             :                               ErrorResult& aError)
    8333             : {
    8334           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8335             : 
    8336             :   /*
    8337             :    * If caller is a browser-element then dispatch a resize event to
    8338             :    * the embedder.
    8339             :    */
    8340           0 :   if (mDocShell && mDocShell->GetIsMozBrowser()) {
    8341           0 :     CSSIntSize size(aWidth, aHeight);
    8342           0 :     if (!DispatchResizeEvent(size)) {
    8343             :       // The embedder chose to prevent the default action for this
    8344             :       // event, so let's not resize this window after all...
    8345           0 :       return;
    8346             :     }
    8347             :   }
    8348             : 
    8349             :   /*
    8350             :    * If caller is not chrome and the user has not explicitly exempted the site,
    8351             :    * prevent window.resizeTo() by exiting early
    8352             :    */
    8353             : 
    8354           0 :   if (!CanMoveResizeWindows(aCallerType) || IsFrame()) {
    8355           0 :     return;
    8356             :   }
    8357             : 
    8358           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    8359           0 :   if (!treeOwnerAsWin) {
    8360           0 :     aError.Throw(NS_ERROR_FAILURE);
    8361           0 :     return;
    8362             :   }
    8363             : 
    8364           0 :   nsIntSize cssSize(aWidth, aHeight);
    8365           0 :   CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerType);
    8366             : 
    8367           0 :   nsIntSize devSz(CSSToDevIntPixels(cssSize));
    8368             : 
    8369           0 :   aError = treeOwnerAsWin->SetSize(devSz.width, devSz.height, true);
    8370             : 
    8371           0 :   CheckForDPIChange();
    8372             : }
    8373             : 
    8374             : void
    8375           0 : nsGlobalWindow::ResizeTo(int32_t aWidth, int32_t aHeight,
    8376             :                          CallerType aCallerType, ErrorResult& aError)
    8377             : {
    8378           0 :   FORWARD_TO_OUTER_OR_THROW(ResizeToOuter,
    8379             :                             (aWidth, aHeight, aCallerType, aError), aError, );
    8380             : }
    8381             : 
    8382             : void
    8383           0 : nsGlobalWindow::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
    8384             :                               CallerType aCallerType, ErrorResult& aError)
    8385             : {
    8386           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8387             : 
    8388             :   /*
    8389             :    * If caller is a browser-element then dispatch a resize event to
    8390             :    * parent.
    8391             :    */
    8392           0 :   if (mDocShell && mDocShell->GetIsMozBrowser()) {
    8393           0 :     CSSIntSize size;
    8394           0 :     if (NS_FAILED(GetInnerSize(size))) {
    8395           0 :       return;
    8396             :     }
    8397             : 
    8398           0 :     size.width += aWidthDif;
    8399           0 :     size.height += aHeightDif;
    8400             : 
    8401           0 :     if (!DispatchResizeEvent(size)) {
    8402             :       // The embedder chose to prevent the default action for this
    8403             :       // event, so let's not resize this window after all...
    8404           0 :       return;
    8405             :     }
    8406             :   }
    8407             : 
    8408             :   /*
    8409             :    * If caller is not chrome and the user has not explicitly exempted the site,
    8410             :    * prevent window.resizeBy() by exiting early
    8411             :    */
    8412             : 
    8413           0 :   if (!CanMoveResizeWindows(aCallerType) || IsFrame()) {
    8414           0 :     return;
    8415             :   }
    8416             : 
    8417           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    8418           0 :   if (!treeOwnerAsWin) {
    8419           0 :     aError.Throw(NS_ERROR_FAILURE);
    8420           0 :     return;
    8421             :   }
    8422             : 
    8423             :   int32_t width, height;
    8424           0 :   aError = treeOwnerAsWin->GetSize(&width, &height);
    8425           0 :   if (aError.Failed()) {
    8426           0 :     return;
    8427             :   }
    8428             : 
    8429             :   // To do this correctly we have to convert what we got from GetSize
    8430             :   // into CSS pixels, add the arguments, do the security check, and
    8431             :   // then convert back to device pixels for the call to SetSize.
    8432             : 
    8433           0 :   nsIntSize cssSize(DevToCSSIntPixels(nsIntSize(width, height)));
    8434             : 
    8435           0 :   cssSize.width += aWidthDif;
    8436           0 :   cssSize.height += aHeightDif;
    8437             : 
    8438           0 :   CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerType);
    8439             : 
    8440           0 :   nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
    8441             : 
    8442           0 :   aError = treeOwnerAsWin->SetSize(newDevSize.width, newDevSize.height, true);
    8443             : 
    8444           0 :   CheckForDPIChange();
    8445             : }
    8446             : 
    8447             : void
    8448           0 : nsGlobalWindow::ResizeBy(int32_t aWidthDif, int32_t aHeightDif,
    8449             :                          CallerType aCallerType, ErrorResult& aError)
    8450             : {
    8451           0 :   FORWARD_TO_OUTER_OR_THROW(ResizeByOuter,
    8452             :                             (aWidthDif, aHeightDif, aCallerType, aError),
    8453             :                             aError, );
    8454             : }
    8455             : 
    8456             : void
    8457           0 : nsGlobalWindow::SizeToContentOuter(CallerType aCallerType, ErrorResult& aError)
    8458             : {
    8459           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8460             : 
    8461           0 :   if (!mDocShell) {
    8462           0 :     return;
    8463             :   }
    8464             : 
    8465             :   /*
    8466             :    * If caller is not chrome and the user has not explicitly exempted the site,
    8467             :    * prevent window.sizeToContent() by exiting early
    8468             :    */
    8469             : 
    8470           0 :   if (!CanMoveResizeWindows(aCallerType) || IsFrame()) {
    8471           0 :     return;
    8472             :   }
    8473             : 
    8474             :   // The content viewer does a check to make sure that it's a content
    8475             :   // viewer for a toplevel docshell.
    8476           0 :   nsCOMPtr<nsIContentViewer> cv;
    8477           0 :   mDocShell->GetContentViewer(getter_AddRefs(cv));
    8478           0 :   if (!cv) {
    8479           0 :     aError.Throw(NS_ERROR_FAILURE);
    8480           0 :     return;
    8481             :   }
    8482             : 
    8483             :   int32_t width, height;
    8484           0 :   aError = cv->GetContentSize(&width, &height);
    8485           0 :   if (aError.Failed()) {
    8486           0 :     return;
    8487             :   }
    8488             : 
    8489             :   // Make sure the new size is following the CheckSecurityWidthAndHeight
    8490             :   // rules.
    8491           0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
    8492           0 :   if (!treeOwner) {
    8493           0 :     aError.Throw(NS_ERROR_FAILURE);
    8494           0 :     return;
    8495             :   }
    8496             : 
    8497           0 :   nsIntSize cssSize(DevToCSSIntPixels(nsIntSize(width, height)));
    8498           0 :   CheckSecurityWidthAndHeight(&cssSize.width, &cssSize.height, aCallerType);
    8499             : 
    8500           0 :   nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
    8501             : 
    8502           0 :   aError = treeOwner->SizeShellTo(mDocShell, newDevSize.width,
    8503           0 :                                   newDevSize.height);
    8504             : }
    8505             : 
    8506             : void
    8507           0 : nsGlobalWindow::SizeToContent(CallerType aCallerType, ErrorResult& aError)
    8508             : {
    8509           0 :   FORWARD_TO_OUTER_OR_THROW(SizeToContentOuter, (aCallerType, aError),
    8510             :                             aError, );
    8511             : }
    8512             : 
    8513             : already_AddRefed<nsPIWindowRoot>
    8514          35 : nsGlobalWindow::GetTopWindowRoot()
    8515             : {
    8516          35 :   nsPIDOMWindowOuter* piWin = GetPrivateRoot();
    8517          35 :   if (!piWin) {
    8518           0 :     return nullptr;
    8519             :   }
    8520             : 
    8521          70 :   nsCOMPtr<nsPIWindowRoot> window = do_QueryInterface(piWin->GetChromeEventHandler());
    8522          35 :   return window.forget();
    8523             : }
    8524             : 
    8525             : void
    8526           0 : nsGlobalWindow::Scroll(double aXScroll, double aYScroll)
    8527             : {
    8528             :   // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
    8529           0 :   auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
    8530           0 :                                          mozilla::ToZeroIfNonfinite(aYScroll));
    8531           0 :   ScrollTo(scrollPos, ScrollOptions());
    8532           0 : }
    8533             : 
    8534             : void
    8535           0 : nsGlobalWindow::ScrollTo(double aXScroll, double aYScroll)
    8536             : {
    8537             :   // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
    8538           0 :   auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
    8539           0 :                                          mozilla::ToZeroIfNonfinite(aYScroll));
    8540           0 :   ScrollTo(scrollPos, ScrollOptions());
    8541           0 : }
    8542             : 
    8543             : void
    8544           0 : nsGlobalWindow::ScrollTo(const ScrollToOptions& aOptions)
    8545             : {
    8546             :   // When scrolling to a non-zero offset, we need to determine whether that
    8547             :   // position is within our scrollable range, so we need updated layout
    8548             :   // information which requires a layout flush, otherwise all we need is to
    8549             :   // flush frames to be able to access our scrollable frame here.
    8550           0 :   FlushType flushType = ((aOptions.mLeft.WasPassed() &&
    8551           0 :                           aOptions.mLeft.Value() > 0) ||
    8552           0 :                          (aOptions.mTop.WasPassed() &&
    8553           0 :                           aOptions.mTop.Value() > 0)) ?
    8554             :                           FlushType::Layout :
    8555           0 :                           FlushType::Frames;
    8556           0 :   FlushPendingNotifications(flushType);
    8557           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    8558             : 
    8559           0 :   if (sf) {
    8560           0 :     CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
    8561           0 :     if (aOptions.mLeft.WasPassed()) {
    8562           0 :       scrollPos.x = mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
    8563             :     }
    8564           0 :     if (aOptions.mTop.WasPassed()) {
    8565           0 :       scrollPos.y = mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
    8566             :     }
    8567             : 
    8568           0 :     ScrollTo(scrollPos, aOptions);
    8569             :   }
    8570           0 : }
    8571             : 
    8572             : void
    8573           0 : nsGlobalWindow::Scroll(const ScrollToOptions& aOptions)
    8574             : {
    8575           0 :   ScrollTo(aOptions);
    8576           0 : }
    8577             : 
    8578             : void
    8579           0 : nsGlobalWindow::ScrollTo(const CSSIntPoint& aScroll,
    8580             :                          const ScrollOptions& aOptions)
    8581             : {
    8582             :   // When scrolling to a non-zero offset, we need to determine whether that
    8583             :   // position is within our scrollable range, so we need updated layout
    8584             :   // information which requires a layout flush, otherwise all we need is to
    8585             :   // flush frames to be able to access our scrollable frame here.
    8586           0 :   FlushType flushType = (aScroll.x || aScroll.y) ?
    8587             :                           FlushType::Layout :
    8588           0 :                           FlushType::Frames;
    8589           0 :   FlushPendingNotifications(flushType);
    8590           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    8591             : 
    8592           0 :   if (sf) {
    8593             :     // Here we calculate what the max pixel value is that we can
    8594             :     // scroll to, we do this by dividing maxint with the pixel to
    8595             :     // twips conversion factor, and subtracting 4, the 4 comes from
    8596             :     // experimenting with this value, anything less makes the view
    8597             :     // code not scroll correctly, I have no idea why. -- jst
    8598           0 :     const int32_t maxpx = nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
    8599             : 
    8600           0 :     CSSIntPoint scroll(aScroll);
    8601           0 :     if (scroll.x > maxpx) {
    8602           0 :       scroll.x = maxpx;
    8603             :     }
    8604             : 
    8605           0 :     if (scroll.y > maxpx) {
    8606           0 :       scroll.y = maxpx;
    8607             :     }
    8608             : 
    8609           0 :     bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
    8610             : 
    8611           0 :     sf->ScrollToCSSPixels(scroll, smoothScroll
    8612             :                             ? nsIScrollableFrame::SMOOTH_MSD
    8613           0 :                             : nsIScrollableFrame::INSTANT);
    8614             :   }
    8615           0 : }
    8616             : 
    8617             : void
    8618           0 : nsGlobalWindow::ScrollBy(double aXScrollDif, double aYScrollDif)
    8619             : {
    8620           0 :   FlushPendingNotifications(FlushType::Layout);
    8621           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    8622             : 
    8623           0 :   if (sf) {
    8624             :     // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
    8625           0 :     auto scrollDif = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScrollDif),
    8626           0 :                                            mozilla::ToZeroIfNonfinite(aYScrollDif));
    8627             :     // It seems like it would make more sense for ScrollBy to use
    8628             :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    8629             :     // Perhaps Web content does too.
    8630           0 :     ScrollTo(sf->GetScrollPositionCSSPixels() + scrollDif, ScrollOptions());
    8631             :   }
    8632           0 : }
    8633             : 
    8634             : void
    8635           0 : nsGlobalWindow::ScrollBy(const ScrollToOptions& aOptions)
    8636             : {
    8637           0 :   FlushPendingNotifications(FlushType::Layout);
    8638           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    8639             : 
    8640           0 :   if (sf) {
    8641           0 :     CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
    8642           0 :     if (aOptions.mLeft.WasPassed()) {
    8643           0 :       scrollPos.x += mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
    8644             :     }
    8645           0 :     if (aOptions.mTop.WasPassed()) {
    8646           0 :       scrollPos.y += mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
    8647             :     }
    8648             : 
    8649           0 :     ScrollTo(scrollPos, aOptions);
    8650             :   }
    8651           0 : }
    8652             : 
    8653             : void
    8654           0 : nsGlobalWindow::ScrollByLines(int32_t numLines,
    8655             :                               const ScrollOptions& aOptions)
    8656             : {
    8657           0 :   MOZ_ASSERT(IsInnerWindow());
    8658             : 
    8659           0 :   FlushPendingNotifications(FlushType::Layout);
    8660           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    8661           0 :   if (sf) {
    8662             :     // It seems like it would make more sense for ScrollByLines to use
    8663             :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    8664             :     // Perhaps Web content does too.
    8665           0 :     bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
    8666             : 
    8667           0 :     sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES,
    8668             :                  smoothScroll
    8669             :                    ? nsIScrollableFrame::SMOOTH_MSD
    8670           0 :                    : nsIScrollableFrame::INSTANT);
    8671             :   }
    8672           0 : }
    8673             : 
    8674             : void
    8675           0 : nsGlobalWindow::ScrollByPages(int32_t numPages,
    8676             :                               const ScrollOptions& aOptions)
    8677             : {
    8678           0 :   MOZ_ASSERT(IsInnerWindow());
    8679             : 
    8680           0 :   FlushPendingNotifications(FlushType::Layout);
    8681           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    8682           0 :   if (sf) {
    8683             :     // It seems like it would make more sense for ScrollByPages to use
    8684             :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    8685             :     // Perhaps Web content does too.
    8686           0 :     bool smoothScroll = sf->GetScrollbarStyles().IsSmoothScroll(aOptions.mBehavior);
    8687             : 
    8688           0 :     sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
    8689             :                  smoothScroll
    8690             :                    ? nsIScrollableFrame::SMOOTH_MSD
    8691           0 :                    : nsIScrollableFrame::INSTANT);
    8692             :   }
    8693           0 : }
    8694             : 
    8695             : void
    8696           0 : nsGlobalWindow::MozScrollSnap()
    8697             : {
    8698           0 :   MOZ_ASSERT(IsInnerWindow());
    8699             : 
    8700           0 :   FlushPendingNotifications(FlushType::Layout);
    8701           0 :   nsIScrollableFrame *sf = GetScrollFrame();
    8702           0 :   if (sf) {
    8703           0 :     sf->ScrollSnap();
    8704             :   }
    8705           0 : }
    8706             : 
    8707             : void
    8708           3 : nsGlobalWindow::ClearTimeout(int32_t aHandle)
    8709             : {
    8710           3 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    8711             : 
    8712           3 :   if (aHandle > 0) {
    8713           1 :     mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
    8714             :   }
    8715           3 : }
    8716             : 
    8717             : void
    8718           0 : nsGlobalWindow::ClearInterval(int32_t aHandle)
    8719             : {
    8720           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
    8721             : 
    8722           0 :   if (aHandle > 0) {
    8723           0 :     mTimeoutManager->ClearTimeout(aHandle, Timeout::Reason::eTimeoutOrInterval);
    8724             :   }
    8725           0 : }
    8726             : 
    8727             : void
    8728           0 : nsGlobalWindow::SetResizable(bool aResizable) const
    8729             : {
    8730             :   // nop
    8731           0 : }
    8732             : 
    8733             : void
    8734           0 : nsGlobalWindow::CaptureEvents()
    8735             : {
    8736           0 :   if (mDoc) {
    8737           0 :     mDoc->WarnOnceAbout(nsIDocument::eUseOfCaptureEvents);
    8738             :   }
    8739           0 : }
    8740             : 
    8741             : void
    8742           0 : nsGlobalWindow::ReleaseEvents()
    8743             : {
    8744           0 :   if (mDoc) {
    8745           0 :     mDoc->WarnOnceAbout(nsIDocument::eUseOfReleaseEvents);
    8746             :   }
    8747           0 : }
    8748             : 
    8749             : static
    8750           0 : bool IsPopupBlocked(nsIDocument* aDoc)
    8751             : {
    8752             :   nsCOMPtr<nsIPopupWindowManager> pm =
    8753           0 :     do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
    8754             : 
    8755           0 :   if (!pm) {
    8756           0 :     return false;
    8757             :   }
    8758             : 
    8759           0 :   if (!aDoc) {
    8760           0 :     return true;
    8761             :   }
    8762             : 
    8763           0 :   uint32_t permission = nsIPopupWindowManager::ALLOW_POPUP;
    8764           0 :   pm->TestPermission(aDoc->NodePrincipal(), &permission);
    8765           0 :   return permission == nsIPopupWindowManager::DENY_POPUP;
    8766             : }
    8767             : 
    8768             : void
    8769           0 : nsGlobalWindow::FirePopupBlockedEvent(nsIDocument* aDoc,
    8770             :                                       nsIURI* aPopupURI,
    8771             :                                       const nsAString& aPopupWindowName,
    8772             :                                       const nsAString& aPopupWindowFeatures)
    8773             : {
    8774           0 :   MOZ_ASSERT(aDoc);
    8775             : 
    8776             :   // Fire a "DOMPopupBlocked" event so that the UI can hear about
    8777             :   // blocked popups.
    8778           0 :   PopupBlockedEventInit init;
    8779           0 :   init.mBubbles = true;
    8780           0 :   init.mCancelable = true;
    8781           0 :   init.mRequestingWindow = this;
    8782           0 :   init.mPopupWindowURI = aPopupURI;
    8783           0 :   init.mPopupWindowName = aPopupWindowName;
    8784           0 :   init.mPopupWindowFeatures = aPopupWindowFeatures;
    8785             : 
    8786             :   RefPtr<PopupBlockedEvent> event =
    8787           0 :     PopupBlockedEvent::Constructor(aDoc,
    8788           0 :                                    NS_LITERAL_STRING("DOMPopupBlocked"),
    8789           0 :                                    init);
    8790             : 
    8791           0 :   event->SetTrusted(true);
    8792             : 
    8793             :   bool defaultActionEnabled;
    8794           0 :   aDoc->DispatchEvent(event, &defaultActionEnabled);
    8795           0 : }
    8796             : 
    8797             : // static
    8798             : bool
    8799           8 : nsGlobalWindow::CanSetProperty(const char *aPrefName)
    8800             : {
    8801             :   // Chrome can set any property.
    8802           8 :   if (nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
    8803           8 :     return true;
    8804             :   }
    8805             : 
    8806             :   // If the pref is set to true, we can not set the property
    8807             :   // and vice versa.
    8808           0 :   return !Preferences::GetBool(aPrefName, true);
    8809             : }
    8810             : 
    8811             : bool
    8812           0 : nsGlobalWindow::PopupWhitelisted()
    8813             : {
    8814           0 :   if (!IsPopupBlocked(mDoc))
    8815           0 :     return true;
    8816             : 
    8817           0 :   nsCOMPtr<nsPIDOMWindowOuter> parent = GetParent();
    8818           0 :   if (parent == AsOuter())
    8819             :   {
    8820           0 :     return false;
    8821             :   }
    8822             : 
    8823           0 :   return nsGlobalWindow::Cast(parent)->PopupWhitelisted();
    8824             : }
    8825             : 
    8826             : /*
    8827             :  * Examine the current document state to see if we're in a way that is
    8828             :  * typically abused by web designers. The window.open code uses this
    8829             :  * routine to determine whether to allow the new window.
    8830             :  * Returns a value from the PopupControlState enum.
    8831             :  */
    8832             : PopupControlState
    8833           0 : nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl)
    8834             : {
    8835           0 :   MOZ_ASSERT(IsOuterWindow());
    8836             : 
    8837           0 :   NS_ASSERTION(mDocShell, "Must have docshell");
    8838             : 
    8839           0 :   if (mDocShell->ItemType() != nsIDocShellTreeItem::typeContent) {
    8840           0 :     return openAllowed;
    8841             :   }
    8842             : 
    8843           0 :   PopupControlState abuse = aControl;
    8844           0 :   switch (abuse) {
    8845             :   case openControlled:
    8846             :   case openAbused:
    8847             :   case openOverridden:
    8848           0 :     if (PopupWhitelisted())
    8849           0 :       abuse = PopupControlState(abuse - 1);
    8850           0 :     break;
    8851           0 :   case openAllowed: break;
    8852             :   default:
    8853           0 :     NS_WARNING("Strange PopupControlState!");
    8854             :   }
    8855             : 
    8856             :   // limit the number of simultaneously open popups
    8857           0 :   if (abuse == openAbused || abuse == openControlled) {
    8858           0 :     int32_t popupMax = Preferences::GetInt("dom.popup_maximum", -1);
    8859           0 :     if (popupMax >= 0 && gOpenPopupSpamCount >= popupMax)
    8860           0 :       abuse = openOverridden;
    8861             :   }
    8862             : 
    8863           0 :   return abuse;
    8864             : }
    8865             : 
    8866             : /* If a window open is blocked, fire the appropriate DOM events. */
    8867             : void
    8868           0 : nsGlobalWindow::FireAbuseEvents(const nsAString &aPopupURL,
    8869             :                                 const nsAString &aPopupWindowName,
    8870             :                                 const nsAString &aPopupWindowFeatures)
    8871             : {
    8872             :   // fetch the URI of the window requesting the opened window
    8873             : 
    8874           0 :   nsCOMPtr<nsPIDOMWindowOuter> window = GetTop();
    8875           0 :   if (!window) {
    8876           0 :     return;
    8877             :   }
    8878             : 
    8879           0 :   nsCOMPtr<nsIDocument> topDoc = window->GetDoc();
    8880           0 :   nsCOMPtr<nsIURI> popupURI;
    8881             : 
    8882             :   // build the URI of the would-have-been popup window
    8883             :   // (see nsWindowWatcher::URIfromURL)
    8884             : 
    8885             :   // first, fetch the opener's base URI
    8886             : 
    8887           0 :   nsIURI *baseURL = nullptr;
    8888             : 
    8889           0 :   nsCOMPtr<nsIDocument> doc = GetEntryDocument();
    8890           0 :   if (doc)
    8891           0 :     baseURL = doc->GetDocBaseURI();
    8892             : 
    8893             :   // use the base URI to build what would have been the popup's URI
    8894           0 :   nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID));
    8895           0 :   if (ios)
    8896           0 :     ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), nullptr, baseURL,
    8897           0 :                 getter_AddRefs(popupURI));
    8898             : 
    8899             :   // fire an event chock full of informative URIs
    8900           0 :   FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName,
    8901           0 :                         aPopupWindowFeatures);
    8902             : }
    8903             : 
    8904             : already_AddRefed<nsPIDOMWindowOuter>
    8905           0 : nsGlobalWindow::OpenOuter(const nsAString& aUrl, const nsAString& aName,
    8906             :                           const nsAString& aOptions, ErrorResult& aError)
    8907             : {
    8908           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    8909           0 :   nsCOMPtr<nsPIDOMWindowOuter> window;
    8910           0 :   aError = OpenJS(aUrl, aName, aOptions, getter_AddRefs(window));
    8911           0 :   return window.forget();
    8912             : }
    8913             : 
    8914             : 
    8915             : already_AddRefed<nsPIDOMWindowOuter>
    8916           0 : nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
    8917             :                      const nsAString& aOptions, ErrorResult& aError)
    8918             : {
    8919           0 :   FORWARD_TO_OUTER_OR_THROW(OpenOuter, (aUrl, aName, aOptions, aError), aError,
    8920             :                             nullptr);
    8921             : }
    8922             : 
    8923             : nsresult
    8924           0 : nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
    8925             :                      const nsAString& aOptions, nsIDocShellLoadInfo* aLoadInfo,
    8926             :                      bool aForceNoOpener, nsPIDOMWindowOuter **_retval)
    8927             : {
    8928           0 :   FORWARD_TO_OUTER(Open, (aUrl, aName, aOptions, aLoadInfo, aForceNoOpener,
    8929             :                           _retval),
    8930             :                    NS_ERROR_NOT_INITIALIZED);
    8931           0 :   return OpenInternal(aUrl, aName, aOptions,
    8932             :                       false,          // aDialog
    8933             :                       false,          // aContentModal
    8934             :                       true,           // aCalledNoScript
    8935             :                       false,          // aDoJSFixups
    8936             :                       true,           // aNavigate
    8937             :                       nullptr, nullptr,  // No args
    8938             :                       aLoadInfo,
    8939             :                       aForceNoOpener,
    8940           0 :                       _retval);
    8941             : }
    8942             : 
    8943             : nsresult
    8944           0 : nsGlobalWindow::OpenJS(const nsAString& aUrl, const nsAString& aName,
    8945             :                        const nsAString& aOptions, nsPIDOMWindowOuter **_retval)
    8946             : {
    8947           0 :   MOZ_ASSERT(IsOuterWindow());
    8948             :   return OpenInternal(aUrl, aName, aOptions,
    8949             :                       false,          // aDialog
    8950             :                       false,          // aContentModal
    8951             :                       false,          // aCalledNoScript
    8952             :                       true,           // aDoJSFixups
    8953             :                       true,           // aNavigate
    8954             :                       nullptr, nullptr,  // No args
    8955             :                       nullptr,        // aLoadInfo
    8956             :                       false,          // aForceNoOpener
    8957           0 :                       _retval);
    8958             : }
    8959             : 
    8960             : // like Open, but attaches to the new window any extra parameters past
    8961             : // [features] as a JS property named "arguments"
    8962             : nsresult
    8963           0 : nsGlobalWindow::OpenDialog(const nsAString& aUrl, const nsAString& aName,
    8964             :                            const nsAString& aOptions,
    8965             :                            nsISupports* aExtraArgument,
    8966             :                            nsPIDOMWindowOuter** _retval)
    8967             : {
    8968           0 :   MOZ_ASSERT(IsOuterWindow());
    8969             :   return OpenInternal(aUrl, aName, aOptions,
    8970             :                       true,                    // aDialog
    8971             :                       false,                   // aContentModal
    8972             :                       true,                    // aCalledNoScript
    8973             :                       false,                   // aDoJSFixups
    8974             :                       true,                    // aNavigate
    8975             :                       nullptr, aExtraArgument, // Arguments
    8976             :                       nullptr,                 // aLoadInfo
    8977             :                       false,                   // aForceNoOpener
    8978           0 :                       _retval);
    8979             : }
    8980             : 
    8981             : // Like Open, but passes aNavigate=false.
    8982             : /* virtual */ nsresult
    8983           0 : nsGlobalWindow::OpenNoNavigate(const nsAString& aUrl,
    8984             :                                const nsAString& aName,
    8985             :                                const nsAString& aOptions,
    8986             :                                nsPIDOMWindowOuter **_retval)
    8987             : {
    8988           0 :   MOZ_ASSERT(IsOuterWindow());
    8989             :   return OpenInternal(aUrl, aName, aOptions,
    8990             :                       false,          // aDialog
    8991             :                       false,          // aContentModal
    8992             :                       true,           // aCalledNoScript
    8993             :                       false,          // aDoJSFixups
    8994             :                       false,          // aNavigate
    8995             :                       nullptr, nullptr,  // No args
    8996             :                       nullptr,        // aLoadInfo
    8997             :                       false,          // aForceNoOpener
    8998           0 :                       _retval);
    8999             : 
    9000             : }
    9001             : 
    9002             : already_AddRefed<nsPIDOMWindowOuter>
    9003           0 : nsGlobalWindow::OpenDialogOuter(JSContext* aCx, const nsAString& aUrl,
    9004             :                                 const nsAString& aName, const nsAString& aOptions,
    9005             :                                 const Sequence<JS::Value>& aExtraArgument,
    9006             :                                 ErrorResult& aError)
    9007             : {
    9008           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    9009             : 
    9010           0 :   nsCOMPtr<nsIJSArgArray> argvArray;
    9011           0 :   aError = NS_CreateJSArgv(aCx, aExtraArgument.Length(),
    9012             :                            aExtraArgument.Elements(),
    9013           0 :                            getter_AddRefs(argvArray));
    9014           0 :   if (aError.Failed()) {
    9015           0 :     return nullptr;
    9016             :   }
    9017             : 
    9018           0 :   nsCOMPtr<nsPIDOMWindowOuter> dialog;
    9019           0 :   aError = OpenInternal(aUrl, aName, aOptions,
    9020             :                         true,             // aDialog
    9021             :                         false,            // aContentModal
    9022             :                         false,            // aCalledNoScript
    9023             :                         false,            // aDoJSFixups
    9024             :                         true,                // aNavigate
    9025             :                         argvArray, nullptr,  // Arguments
    9026             :                         nullptr,          // aLoadInfo
    9027             :                         false,            // aForceNoOpener
    9028           0 :                         getter_AddRefs(dialog));
    9029           0 :   return dialog.forget();
    9030             : }
    9031             : 
    9032             : already_AddRefed<nsPIDOMWindowOuter>
    9033           0 : nsGlobalWindow::OpenDialog(JSContext* aCx, const nsAString& aUrl,
    9034             :                            const nsAString& aName, const nsAString& aOptions,
    9035             :                            const Sequence<JS::Value>& aExtraArgument,
    9036             :                            ErrorResult& aError)
    9037             : {
    9038           0 :   FORWARD_TO_OUTER_OR_THROW(OpenDialogOuter,
    9039             :                             (aCx, aUrl, aName, aOptions, aExtraArgument, aError),
    9040             :                             aError, nullptr);
    9041             : }
    9042             : 
    9043             : already_AddRefed<nsPIDOMWindowOuter>
    9044           8 : nsGlobalWindow::GetFramesOuter()
    9045             : {
    9046          16 :   RefPtr<nsPIDOMWindowOuter> frames(AsOuter());
    9047           8 :   FlushPendingNotifications(FlushType::ContentAndNotify);
    9048          16 :   return frames.forget();
    9049             : }
    9050             : 
    9051             : already_AddRefed<nsPIDOMWindowOuter>
    9052           8 : nsGlobalWindow::GetFrames(ErrorResult& aError)
    9053             : {
    9054           8 :   FORWARD_TO_OUTER_OR_THROW(GetFramesOuter, (), aError, nullptr);
    9055             : }
    9056             : 
    9057             : nsGlobalWindow*
    9058           0 : nsGlobalWindow::CallerInnerWindow()
    9059             : {
    9060           0 :   JSContext *cx = nsContentUtils::GetCurrentJSContext();
    9061           0 :   NS_ENSURE_TRUE(cx, nullptr);
    9062           0 :   nsIGlobalObject* global = GetIncumbentGlobal();
    9063           0 :   NS_ENSURE_TRUE(global, nullptr);
    9064           0 :   JS::Rooted<JSObject*> scope(cx, global->GetGlobalJSObject());
    9065           0 :   NS_ENSURE_TRUE(scope, nullptr);
    9066             : 
    9067             :   // When Jetpack runs content scripts inside a sandbox, it uses
    9068             :   // sandboxPrototype to make them appear as though they're running in the
    9069             :   // scope of the page. So when a content script invokes postMessage, it expects
    9070             :   // the |source| of the received message to be the window set as the
    9071             :   // sandboxPrototype. This used to work incidentally for unrelated reasons, but
    9072             :   // now we need to do some special handling to support it.
    9073           0 :   if (xpc::IsSandbox(scope)) {
    9074           0 :     JSAutoCompartment ac(cx, scope);
    9075           0 :     JS::Rooted<JSObject*> scopeProto(cx);
    9076           0 :     bool ok = JS_GetPrototype(cx, scope, &scopeProto);
    9077           0 :     NS_ENSURE_TRUE(ok, nullptr);
    9078           0 :     if (scopeProto && xpc::IsSandboxPrototypeProxy(scopeProto) &&
    9079           0 :         (scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtWindowProxy = */ false)))
    9080             :     {
    9081           0 :       global = xpc::NativeGlobal(scopeProto);
    9082           0 :       NS_ENSURE_TRUE(global, nullptr);
    9083             :     }
    9084             :   }
    9085             : 
    9086             :   // The calling window must be holding a reference, so we can return a weak
    9087             :   // pointer.
    9088           0 :   nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
    9089           0 :   return nsGlobalWindow::Cast(win);
    9090             : }
    9091             : 
    9092             : void
    9093           0 : nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
    9094             :                                     const nsAString& aTargetOrigin,
    9095             :                                     JS::Handle<JS::Value> aTransfer,
    9096             :                                     nsIPrincipal& aSubjectPrincipal,
    9097             :                                     ErrorResult& aError)
    9098             : {
    9099           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    9100             : 
    9101             :   //
    9102             :   // Window.postMessage is an intentional subversion of the same-origin policy.
    9103             :   // As such, this code must be particularly careful in the information it
    9104             :   // exposes to calling code.
    9105             :   //
    9106             :   // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
    9107             :   //
    9108             : 
    9109             :   // First, get the caller's window
    9110           0 :   RefPtr<nsGlobalWindow> callerInnerWin = CallerInnerWindow();
    9111             :   nsIPrincipal* callerPrin;
    9112           0 :   if (callerInnerWin) {
    9113           0 :     MOZ_ASSERT(callerInnerWin->IsInnerWindow(),
    9114             :                "should have gotten an inner window here");
    9115             : 
    9116             :     // Compute the caller's origin either from its principal or, in the case the
    9117             :     // principal doesn't carry a URI (e.g. the system principal), the caller's
    9118             :     // document.  We must get this now instead of when the event is created and
    9119             :     // dispatched, because ultimately it is the identity of the calling window
    9120             :     // *now* that determines who sent the message (and not an identity which might
    9121             :     // have changed due to intervening navigations).
    9122           0 :     callerPrin = callerInnerWin->GetPrincipal();
    9123             :   }
    9124             :   else {
    9125             :     // In case the global is not a window, it can be a sandbox, and the sandbox's
    9126             :     // principal can be used for the security check.
    9127           0 :     nsIGlobalObject* global = GetIncumbentGlobal();
    9128           0 :     NS_ASSERTION(global, "Why is there no global object?");
    9129           0 :     callerPrin = global->PrincipalOrNull();
    9130             :   }
    9131           0 :   if (!callerPrin) {
    9132           0 :     return;
    9133             :   }
    9134             : 
    9135           0 :   nsCOMPtr<nsIURI> callerOuterURI;
    9136           0 :   if (NS_FAILED(callerPrin->GetURI(getter_AddRefs(callerOuterURI)))) {
    9137           0 :     return;
    9138             :   }
    9139             : 
    9140           0 :   nsAutoString origin;
    9141           0 :   if (callerOuterURI) {
    9142             :     // if the principal has a URI, use that to generate the origin
    9143           0 :     nsContentUtils::GetUTFOrigin(callerPrin, origin);
    9144             :   }
    9145           0 :   else if (callerInnerWin) {
    9146             :     // otherwise use the URI of the document to generate origin
    9147           0 :     nsCOMPtr<nsIDocument> doc = callerInnerWin->GetExtantDoc();
    9148           0 :     if (!doc) {
    9149           0 :       return;
    9150             :     }
    9151           0 :     callerOuterURI = doc->GetDocumentURI();
    9152             :     // if the principal has a URI, use that to generate the origin
    9153           0 :     nsContentUtils::GetUTFOrigin(callerOuterURI, origin);
    9154             :   }
    9155             :   else {
    9156             :     // in case of a sandbox with a system principal origin can be empty
    9157           0 :     if (!nsContentUtils::IsSystemPrincipal(callerPrin)) {
    9158           0 :       return;
    9159             :     }
    9160             :   }
    9161             : 
    9162             :   // Convert the provided origin string into a URI for comparison purposes.
    9163           0 :   nsCOMPtr<nsIPrincipal> providedPrincipal;
    9164             : 
    9165           0 :   if (aTargetOrigin.EqualsASCII("/")) {
    9166           0 :     providedPrincipal = callerPrin;
    9167             :   }
    9168             :   // "*" indicates no specific origin is required.
    9169           0 :   else if (!aTargetOrigin.EqualsASCII("*")) {
    9170           0 :     nsCOMPtr<nsIURI> originURI;
    9171           0 :     if (NS_FAILED(NS_NewURI(getter_AddRefs(originURI), aTargetOrigin))) {
    9172           0 :       aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
    9173           0 :       return;
    9174             :     }
    9175             : 
    9176           0 :     if (NS_FAILED(originURI->SetUserPass(EmptyCString())) ||
    9177           0 :         NS_FAILED(originURI->SetPath(EmptyCString()))) {
    9178           0 :       return;
    9179             :     }
    9180             : 
    9181           0 :     OriginAttributes attrs = aSubjectPrincipal.OriginAttributesRef();
    9182           0 :     if (aSubjectPrincipal.GetIsSystemPrincipal()) {
    9183           0 :       auto principal = BasePrincipal::Cast(GetPrincipal());
    9184             : 
    9185           0 :       if (attrs != principal->OriginAttributesRef()) {
    9186           0 :         nsCOMPtr<nsIURI> targetURI;
    9187           0 :         nsAutoCString targetURL;
    9188           0 :         nsAutoCString sourceOrigin;
    9189           0 :         nsAutoCString targetOrigin;
    9190             : 
    9191           0 :         if (NS_FAILED(principal->GetURI(getter_AddRefs(targetURI))) ||
    9192           0 :             NS_FAILED(targetURI->GetAsciiSpec(targetURL)) ||
    9193           0 :             NS_FAILED(principal->GetOrigin(targetOrigin)) ||
    9194           0 :             NS_FAILED(aSubjectPrincipal.GetOrigin(sourceOrigin))) {
    9195           0 :           NS_WARNING("Failed to get source and target origins");
    9196           0 :           return;
    9197             :         }
    9198             : 
    9199             :         nsContentUtils::LogSimpleConsoleError(
    9200           0 :           NS_ConvertUTF8toUTF16(nsPrintfCString(
    9201             :             R"(Attempting to post a message to window with url "%s" and )"
    9202             :             R"(origin "%s" from a system principal scope with mismatched )"
    9203             :             R"(origin "%s".)",
    9204             :             targetURL.get(), targetOrigin.get(), sourceOrigin.get())),
    9205           0 :           "DOM");
    9206             : 
    9207           0 :         attrs = principal->OriginAttributesRef();
    9208             :       }
    9209             :     }
    9210             : 
    9211             :     // Create a nsIPrincipal inheriting the app/browser attributes from the
    9212             :     // caller.
    9213           0 :     providedPrincipal = BasePrincipal::CreateCodebasePrincipal(originURI, attrs);
    9214           0 :     if (NS_WARN_IF(!providedPrincipal)) {
    9215           0 :       return;
    9216             :     }
    9217             :   }
    9218             : 
    9219             :   // Create and asynchronously dispatch a runnable which will handle actual DOM
    9220             :   // event creation and dispatch.
    9221             :   RefPtr<PostMessageEvent> event =
    9222           0 :     new PostMessageEvent(nsContentUtils::IsCallerChrome() || !callerInnerWin
    9223           0 :                          ? nullptr
    9224           0 :                          : callerInnerWin->GetOuterWindowInternal(),
    9225             :                          origin,
    9226             :                          this,
    9227             :                          providedPrincipal,
    9228             :                          callerInnerWin
    9229           0 :                          ? callerInnerWin->GetDoc()
    9230           0 :                          : nullptr,
    9231           0 :                          nsContentUtils::IsCallerChrome());
    9232             : 
    9233           0 :   JS::Rooted<JS::Value> message(aCx, aMessage);
    9234           0 :   JS::Rooted<JS::Value> transfer(aCx, aTransfer);
    9235             : 
    9236           0 :   event->Write(aCx, message, transfer, JS::CloneDataPolicy(), aError);
    9237           0 :   if (NS_WARN_IF(aError.Failed())) {
    9238           0 :     return;
    9239             :   }
    9240             : 
    9241           0 :   aError = Dispatch("PostMessageEvent", TaskCategory::Other, event.forget());
    9242             : }
    9243             : 
    9244             : void
    9245           0 : nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
    9246             :                                const nsAString& aTargetOrigin,
    9247             :                                JS::Handle<JS::Value> aTransfer,
    9248             :                                nsIPrincipal& aSubjectPrincipal,
    9249             :                                ErrorResult& aError)
    9250             : {
    9251           0 :   FORWARD_TO_OUTER_OR_THROW(PostMessageMozOuter,
    9252             :                             (aCx, aMessage, aTargetOrigin, aTransfer,
    9253             :                              aSubjectPrincipal, aError),
    9254             :                             aError, );
    9255             : }
    9256             : 
    9257             : void
    9258           0 : nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
    9259             :                                const nsAString& aTargetOrigin,
    9260             :                                const Sequence<JSObject*>& aTransfer,
    9261             :                                nsIPrincipal& aSubjectPrincipal,
    9262             :                                ErrorResult& aRv)
    9263             : {
    9264           0 :   JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
    9265             : 
    9266           0 :   aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransfer,
    9267           0 :                                                           &transferArray);
    9268           0 :   if (NS_WARN_IF(aRv.Failed())) {
    9269           0 :     return;
    9270             :   }
    9271             : 
    9272           0 :   PostMessageMoz(aCx, aMessage, aTargetOrigin, transferArray,
    9273           0 :                  aSubjectPrincipal, aRv);
    9274             : }
    9275             : 
    9276           0 : class nsCloseEvent : public Runnable {
    9277             : 
    9278             :   RefPtr<nsGlobalWindow> mWindow;
    9279             :   bool mIndirect;
    9280             : 
    9281           0 :   nsCloseEvent(nsGlobalWindow* aWindow, bool aIndirect)
    9282           0 :     : mozilla::Runnable("nsCloseEvent")
    9283             :     , mWindow(aWindow)
    9284           0 :     , mIndirect(aIndirect)
    9285           0 :   {}
    9286             : 
    9287             : public:
    9288             : 
    9289             :   static nsresult
    9290           0 :   PostCloseEvent(nsGlobalWindow* aWindow, bool aIndirect) {
    9291           0 :     nsCOMPtr<nsIRunnable> ev = new nsCloseEvent(aWindow, aIndirect);
    9292             :     nsresult rv =
    9293           0 :       aWindow->Dispatch("nsCloseEvent", TaskCategory::Other, ev.forget());
    9294           0 :     if (NS_SUCCEEDED(rv))
    9295           0 :       aWindow->MaybeForgiveSpamCount();
    9296           0 :     return rv;
    9297             :   }
    9298             : 
    9299           0 :   NS_IMETHOD Run() override {
    9300           0 :     if (mWindow) {
    9301           0 :       if (mIndirect) {
    9302           0 :         return PostCloseEvent(mWindow, false);
    9303             :       }
    9304           0 :       mWindow->ReallyCloseWindow();
    9305             :     }
    9306           0 :     return NS_OK;
    9307             :   }
    9308             : 
    9309             : };
    9310             : 
    9311             : bool
    9312           0 : nsGlobalWindow::CanClose()
    9313             : {
    9314           0 :   MOZ_ASSERT(IsOuterWindow());
    9315             : 
    9316           0 :   if (mIsChrome) {
    9317           0 :     nsCOMPtr<nsIBrowserDOMWindow> bwin;
    9318           0 :     nsIDOMChromeWindow* chromeWin = static_cast<nsGlobalChromeWindow*>(this);
    9319           0 :     chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
    9320             : 
    9321           0 :     bool canClose = true;
    9322           0 :     if (bwin && NS_SUCCEEDED(bwin->CanClose(&canClose))) {
    9323           0 :       return canClose;
    9324             :     }
    9325             :   }
    9326             : 
    9327           0 :   if (!mDocShell) {
    9328           0 :     return true;
    9329             :   }
    9330             : 
    9331             :   // Ask the content viewer whether the toplevel window can close.
    9332             :   // If the content viewer returns false, it is responsible for calling
    9333             :   // Close() as soon as it is possible for the window to close.
    9334             :   // This allows us to not close the window while printing is happening.
    9335             : 
    9336           0 :   nsCOMPtr<nsIContentViewer> cv;
    9337           0 :   mDocShell->GetContentViewer(getter_AddRefs(cv));
    9338           0 :   if (cv) {
    9339             :     bool canClose;
    9340           0 :     nsresult rv = cv->PermitUnload(&canClose);
    9341           0 :     if (NS_SUCCEEDED(rv) && !canClose)
    9342           0 :       return false;
    9343             : 
    9344           0 :     rv = cv->RequestWindowClose(&canClose);
    9345           0 :     if (NS_SUCCEEDED(rv) && !canClose)
    9346           0 :       return false;
    9347             :   }
    9348             : 
    9349           0 :   return true;
    9350             : }
    9351             : 
    9352             : void
    9353           0 : nsGlobalWindow::CloseOuter(bool aTrustedCaller)
    9354             : {
    9355           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    9356             : 
    9357           0 :   if (!mDocShell || IsInModalState() ||
    9358           0 :       (IsFrame() && !mDocShell->GetIsMozBrowser())) {
    9359             :     // window.close() is called on a frame in a frameset, on a window
    9360             :     // that's already closed, or on a window for which there's
    9361             :     // currently a modal dialog open. Ignore such calls.
    9362           0 :     return;
    9363             :   }
    9364             : 
    9365           0 :   if (mHavePendingClose) {
    9366             :     // We're going to be closed anyway; do nothing since we don't want
    9367             :     // to double-close
    9368           0 :     return;
    9369             :   }
    9370             : 
    9371           0 :   if (mBlockScriptedClosingFlag)
    9372             :   {
    9373             :     // A script's popup has been blocked and we don't want
    9374             :     // the window to be closed directly after this event,
    9375             :     // so the user can see that there was a blocked popup.
    9376           0 :     return;
    9377             :   }
    9378             : 
    9379             :   // Don't allow scripts from content to close non-neterror windows that
    9380             :   // were not opened by script.
    9381           0 :   nsAutoString url;
    9382           0 :   nsresult rv = mDoc->GetURL(url);
    9383           0 :   NS_ENSURE_SUCCESS_VOID(rv);
    9384             : 
    9385           0 :   if (!StringBeginsWith(url, NS_LITERAL_STRING("about:neterror")) &&
    9386           0 :       !mHadOriginalOpener && !aTrustedCaller) {
    9387           0 :     bool allowClose = mAllowScriptsToClose ||
    9388           0 :       Preferences::GetBool("dom.allow_scripts_to_close_windows", true);
    9389           0 :     if (!allowClose) {
    9390             :       // We're blocking the close operation
    9391             :       // report localized error msg in JS console
    9392           0 :       nsContentUtils::ReportToConsole(
    9393             :           nsIScriptError::warningFlag,
    9394           0 :           NS_LITERAL_CSTRING("DOM Window"), mDoc,  // Better name for the category?
    9395             :           nsContentUtils::eDOM_PROPERTIES,
    9396           0 :           "WindowCloseBlockedWarning");
    9397             : 
    9398           0 :       return;
    9399             :     }
    9400             :   }
    9401             : 
    9402           0 :   if (!mInClose && !mIsClosed && !CanClose()) {
    9403           0 :     return;
    9404             :   }
    9405             : 
    9406             :   // Fire a DOM event notifying listeners that this window is about to
    9407             :   // be closed. The tab UI code may choose to cancel the default
    9408             :   // action for this event, if so, we won't actually close the window
    9409             :   // (since the tab UI code will close the tab in stead). Sure, this
    9410             :   // could be abused by content code, but do we care? I don't think
    9411             :   // so...
    9412             : 
    9413           0 :   bool wasInClose = mInClose;
    9414           0 :   mInClose = true;
    9415             : 
    9416           0 :   if (!DispatchCustomEvent(NS_LITERAL_STRING("DOMWindowClose"))) {
    9417             :     // Someone chose to prevent the default action for this event, if
    9418             :     // so, let's not close this window after all...
    9419             : 
    9420           0 :     mInClose = wasInClose;
    9421           0 :     return;
    9422             :   }
    9423             : 
    9424           0 :   FinalClose();
    9425             : }
    9426             : 
    9427             : void
    9428           0 : nsGlobalWindow::Close(ErrorResult& aError)
    9429             : {
    9430           0 :   FORWARD_TO_OUTER_OR_THROW(CloseOuter, (nsContentUtils::IsCallerChrome()), aError, );
    9431             : }
    9432             : 
    9433             : nsresult
    9434           0 : nsGlobalWindow::Close()
    9435             : {
    9436           0 :   FORWARD_TO_OUTER(Close, (), NS_ERROR_UNEXPECTED);
    9437           0 :   CloseOuter(/* aTrustedCaller = */ true);
    9438           0 :   return NS_OK;
    9439             : }
    9440             : 
    9441             : void
    9442           0 : nsGlobalWindow::ForceClose()
    9443             : {
    9444           0 :   MOZ_ASSERT(IsOuterWindow());
    9445           0 :   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
    9446             : 
    9447           0 :   if (IsFrame() || !mDocShell) {
    9448             :     // This may be a frame in a frameset, or a window that's already closed.
    9449             :     // Ignore such calls.
    9450           0 :     return;
    9451             :   }
    9452             : 
    9453           0 :   if (mHavePendingClose) {
    9454             :     // We're going to be closed anyway; do nothing since we don't want
    9455             :     // to double-close
    9456           0 :     return;
    9457             :   }
    9458             : 
    9459           0 :   mInClose = true;
    9460             : 
    9461           0 :   DispatchCustomEvent(NS_LITERAL_STRING("DOMWindowClose"));
    9462             : 
    9463           0 :   FinalClose();
    9464             : }
    9465             : 
    9466             : void
    9467           0 : nsGlobalWindow::FinalClose()
    9468             : {
    9469           0 :   MOZ_ASSERT(IsOuterWindow());
    9470             : 
    9471             :   // Flag that we were closed.
    9472           0 :   mIsClosed = true;
    9473             : 
    9474             :   // If we get here from CloseOuter then it means that the parent process is
    9475             :   // going to close our window for us. It's just important to set mIsClosed.
    9476           0 :   if (XRE_GetProcessType() == GeckoProcessType_Content) {
    9477           0 :     return;
    9478             :   }
    9479             : 
    9480             :   // This stuff is non-sensical but incredibly fragile. The reasons for the
    9481             :   // behavior here don't make sense today and may not have ever made sense,
    9482             :   // but various bits of frontend code break when you change them. If you need
    9483             :   // to fix up this behavior, feel free to. It's a righteous task, but involves
    9484             :   // wrestling with various download manager tests, frontend code, and possible
    9485             :   // broken addons. The chrome tests in toolkit/mozapps/downloads are a good
    9486             :   // testing ground.
    9487             :   //
    9488             :   // In particular, if some inner of |win| is the entry global, we must
    9489             :   // complete _two_ round-trips to the event loop before the call to
    9490             :   // ReallyCloseWindow. This allows setTimeout handlers that are set after
    9491             :   // FinalClose() is called to run before the window is torn down.
    9492             :   nsCOMPtr<nsPIDOMWindowInner> entryWindow =
    9493           0 :     do_QueryInterface(GetEntryGlobal());
    9494             :   bool indirect =
    9495           0 :     entryWindow && entryWindow->GetOuterWindow() == this->AsOuter();
    9496           0 :   if (NS_FAILED(nsCloseEvent::PostCloseEvent(this, indirect))) {
    9497           0 :     ReallyCloseWindow();
    9498             :   } else {
    9499           0 :     mHavePendingClose = true;
    9500             :   }
    9501             : }
    9502             : 
    9503             : 
    9504             : void
    9505           0 : nsGlobalWindow::ReallyCloseWindow()
    9506             : {
    9507           0 :   FORWARD_TO_OUTER_VOID(ReallyCloseWindow, ());
    9508             : 
    9509             :   // Make sure we never reenter this method.
    9510           0 :   mHavePendingClose = true;
    9511             : 
    9512           0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
    9513             : 
    9514             :   // If there's no treeOwnerAsWin, this window must already be closed.
    9515             : 
    9516           0 :   if (treeOwnerAsWin) {
    9517             : 
    9518             :     // but if we're a browser window we could be in some nasty
    9519             :     // self-destroying cascade that we should mostly ignore
    9520             : 
    9521           0 :     if (mDocShell) {
    9522           0 :       nsCOMPtr<nsIBrowserDOMWindow> bwin;
    9523           0 :       nsCOMPtr<nsIDocShellTreeItem> rootItem;
    9524           0 :       mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
    9525             :       nsCOMPtr<nsPIDOMWindowOuter> rootWin =
    9526           0 :        rootItem ? rootItem->GetWindow() : nullptr;
    9527           0 :       nsCOMPtr<nsIDOMChromeWindow> chromeWin(do_QueryInterface(rootWin));
    9528           0 :       if (chromeWin)
    9529           0 :         chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
    9530             : 
    9531           0 :       if (rootWin) {
    9532             :         /* Normally we destroy the entire window, but not if
    9533             :            this DOM window belongs to a tabbed browser and doesn't
    9534             :            correspond to a tab. This allows a well-behaved tab
    9535             :            to destroy the container as it should but is a final measure
    9536             :            to prevent an errant tab from doing so when it shouldn't.
    9537             :            This works because we reach this code when we shouldn't only
    9538             :            in the particular circumstance that we belong to a tab
    9539             :            that has just been closed (and is therefore already missing
    9540             :            from the list of browsers) (and has an unload handler
    9541             :            that closes the window). */
    9542             :         // XXXbz now that we have mHavePendingClose, is this needed?
    9543             :         bool isTab;
    9544           0 :         if (rootWin == AsOuter() ||
    9545           0 :             !bwin ||
    9546           0 :             (NS_SUCCEEDED(bwin->IsTabContentWindow(GetOuterWindowInternal(),
    9547           0 :                                                    &isTab)) && isTab)) {
    9548           0 :           treeOwnerAsWin->Destroy();
    9549             :         }
    9550             :       }
    9551             :     }
    9552             : 
    9553           0 :     CleanUp();
    9554             :   }
    9555             : }
    9556             : 
    9557             : void
    9558           0 : nsGlobalWindow::EnterModalState()
    9559             : {
    9560           0 :   MOZ_ASSERT(IsOuterWindow(), "Modal state is maintained on outer windows");
    9561             : 
    9562             :   // GetScriptableTop, not GetTop, so that EnterModalState works properly with
    9563             :   // <iframe mozbrowser>.
    9564           0 :   nsGlobalWindow* topWin = GetScriptableTopInternal();
    9565             : 
    9566           0 :   if (!topWin) {
    9567           0 :     NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");
    9568           0 :     return;
    9569             :   }
    9570             : 
    9571             :   // If there is an active ESM in this window, clear it. Otherwise, this can
    9572             :   // cause a problem if a modal state is entered during a mouseup event.
    9573             :   EventStateManager* activeESM =
    9574             :     static_cast<EventStateManager*>(
    9575           0 :       EventStateManager::GetActiveEventStateManager());
    9576           0 :   if (activeESM && activeESM->GetPresContext()) {
    9577           0 :     nsIPresShell* activeShell = activeESM->GetPresContext()->GetPresShell();
    9578           0 :     if (activeShell && (
    9579           0 :         nsContentUtils::ContentIsCrossDocDescendantOf(activeShell->GetDocument(), mDoc) ||
    9580           0 :         nsContentUtils::ContentIsCrossDocDescendantOf(mDoc, activeShell->GetDocument()))) {
    9581           0 :       EventStateManager::ClearGlobalActiveContent(activeESM);
    9582             : 
    9583           0 :       activeShell->SetCapturingContent(nullptr, 0);
    9584             : 
    9585           0 :       if (activeShell) {
    9586           0 :         RefPtr<nsFrameSelection> frameSelection = activeShell->FrameSelection();
    9587           0 :         frameSelection->SetDragState(false);
    9588             :       }
    9589             :     }
    9590             :   }
    9591             : 
    9592             :   // If there are any drag and drop operations in flight, try to end them.
    9593             :   nsCOMPtr<nsIDragService> ds =
    9594           0 :     do_GetService("@mozilla.org/widget/dragservice;1");
    9595           0 :   if (ds) {
    9596           0 :     ds->EndDragSession(true, 0);
    9597             :   }
    9598             : 
    9599             :   // Clear the capturing content if it is under topDoc.
    9600             :   // Usually the activeESM check above does that, but there are cases when
    9601             :   // we don't have activeESM, or it is for different document.
    9602           0 :   nsIDocument* topDoc = topWin->GetExtantDoc();
    9603           0 :   nsIContent* capturingContent = nsIPresShell::GetCapturingContent();
    9604           0 :   if (capturingContent && topDoc &&
    9605           0 :       nsContentUtils::ContentIsCrossDocDescendantOf(capturingContent, topDoc)) {
    9606           0 :     nsIPresShell::SetCapturingContent(nullptr, 0);
    9607             :   }
    9608             : 
    9609           0 :   if (topWin->mModalStateDepth == 0) {
    9610           0 :     NS_ASSERTION(!topWin->mSuspendedDoc, "Shouldn't have mSuspendedDoc here!");
    9611             : 
    9612           0 :     topWin->mSuspendedDoc = topDoc;
    9613           0 :     if (topDoc) {
    9614           0 :       topDoc->SuppressEventHandling();
    9615             :     }
    9616             : 
    9617           0 :     nsGlobalWindow* inner = topWin->GetCurrentInnerWindowInternal();
    9618           0 :     if (inner) {
    9619           0 :       topWin->GetCurrentInnerWindowInternal()->Suspend();
    9620             :     }
    9621             :   }
    9622           0 :   topWin->mModalStateDepth++;
    9623             : }
    9624             : 
    9625             : void
    9626           0 : nsGlobalWindow::LeaveModalState()
    9627             : {
    9628           0 :   MOZ_ASSERT(IsOuterWindow(), "Modal state is maintained on outer windows");
    9629             : 
    9630           0 :   nsGlobalWindow* topWin = GetScriptableTopInternal();
    9631             : 
    9632           0 :   if (!topWin) {
    9633           0 :     NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?");
    9634           0 :     return;
    9635             :   }
    9636             : 
    9637           0 :   MOZ_ASSERT(topWin->mModalStateDepth != 0);
    9638           0 :   MOZ_ASSERT(IsSuspended());
    9639           0 :   MOZ_ASSERT(topWin->IsSuspended());
    9640           0 :   topWin->mModalStateDepth--;
    9641             : 
    9642           0 :   nsGlobalWindow* inner = topWin->GetCurrentInnerWindowInternal();
    9643             : 
    9644           0 :   if (topWin->mModalStateDepth == 0) {
    9645           0 :     if (inner) {
    9646           0 :       inner->Resume();
    9647             :     }
    9648             : 
    9649           0 :     if (topWin->mSuspendedDoc) {
    9650           0 :       nsCOMPtr<nsIDocument> currentDoc = topWin->GetExtantDoc();
    9651           0 :       topWin->mSuspendedDoc->UnsuppressEventHandlingAndFireEvents(currentDoc == topWin->mSuspendedDoc);
    9652           0 :       topWin->mSuspendedDoc = nullptr;
    9653             :     }
    9654             :   }
    9655             : 
    9656             :   // Remember the time of the last dialog quit.
    9657           0 :   if (inner) {
    9658           0 :     inner->mLastDialogQuitTime = TimeStamp::Now();
    9659             :   }
    9660             : 
    9661           0 :   if (topWin->mModalStateDepth == 0) {
    9662           0 :     RefPtr<Event> event = NS_NewDOMEvent(inner, nullptr, nullptr);
    9663           0 :     event->InitEvent(NS_LITERAL_STRING("endmodalstate"), true, false);
    9664           0 :     event->SetTrusted(true);
    9665           0 :     event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
    9666             :     bool dummy;
    9667           0 :     topWin->DispatchEvent(event, &dummy);
    9668             :   }
    9669             : }
    9670             : 
    9671             : bool
    9672           9 : nsGlobalWindow::IsInModalState()
    9673             : {
    9674           9 :   nsGlobalWindow *topWin = GetScriptableTopInternal();
    9675             : 
    9676           9 :   if (!topWin) {
    9677             :     // IsInModalState() getting called w/o a reachable top window is a bit
    9678             :     // iffy, but valid enough not to make noise about it.  See bug 404828
    9679           0 :     return false;
    9680             :   }
    9681             : 
    9682           9 :   return topWin->mModalStateDepth != 0;
    9683             : }
    9684             : 
    9685             : // static
    9686             : void
    9687           3 : nsGlobalWindow::NotifyDOMWindowDestroyed(nsGlobalWindow* aWindow) {
    9688             :   nsCOMPtr<nsIObserverService> observerService =
    9689           6 :     services::GetObserverService();
    9690           3 :   if (observerService) {
    9691           3 :     observerService->
    9692           3 :       NotifyObservers(ToSupports(aWindow),
    9693           6 :                       DOM_WINDOW_DESTROYED_TOPIC, nullptr);
    9694             :   }
    9695           3 : }
    9696             : 
    9697             : // Try to match compartments that are not web content by matching compartments
    9698             : // with principals that are either the system principal or an expanded principal.
    9699             : // This may not return true for all non-web-content compartments.
    9700           3 : struct BrowserCompartmentMatcher : public js::CompartmentFilter {
    9701         437 :   bool match(JSCompartment* aC) const override
    9702             :   {
    9703         874 :     nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(aC));
    9704         874 :     return nsContentUtils::IsSystemOrExpandedPrincipal(pc);
    9705             :   }
    9706             : };
    9707             : 
    9708             : 
    9709          12 : class WindowDestroyedEvent final : public Runnable
    9710             : {
    9711             : public:
    9712           4 :   WindowDestroyedEvent(nsIDOMWindow* aWindow, uint64_t aID, const char* aTopic)
    9713           4 :     : mozilla::Runnable("WindowDestroyedEvent")
    9714             :     , mID(aID)
    9715             :     , mPhase(Phase::Destroying)
    9716           4 :     , mTopic(aTopic)
    9717             :   {
    9718           4 :     mWindow = do_GetWeakReference(aWindow);
    9719           4 :   }
    9720             : 
    9721             :   enum class Phase
    9722             :   {
    9723             :     Destroying,
    9724             :     Nuking
    9725             :   };
    9726             : 
    9727           8 :   NS_IMETHOD Run() override
    9728             :   {
    9729          16 :     AUTO_PROFILER_LABEL("WindowDestroyedEvent::Run", OTHER);
    9730             : 
    9731             :     nsCOMPtr<nsIObserverService> observerService =
    9732          16 :       services::GetObserverService();
    9733           8 :     if (!observerService) {
    9734           0 :       return NS_OK;
    9735             :     }
    9736             : 
    9737             :     nsCOMPtr<nsISupportsPRUint64> wrapper =
    9738          16 :       do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
    9739           8 :     if (wrapper) {
    9740           8 :       wrapper->SetData(mID);
    9741           8 :       observerService->NotifyObservers(wrapper, mTopic.get(), nullptr);
    9742             :     }
    9743             : 
    9744           8 :     switch (mPhase) {
    9745             :       case Phase::Destroying:
    9746             :       {
    9747           4 :         bool skipNukeCrossCompartment = false;
    9748             : #ifndef DEBUG
    9749             :         nsCOMPtr<nsIAppStartup> appStartup =
    9750             :           do_GetService(NS_APPSTARTUP_CONTRACTID);
    9751             : 
    9752             :         if (appStartup) {
    9753             :           appStartup->GetShuttingDown(&skipNukeCrossCompartment);
    9754             :         }
    9755             : #endif
    9756             : 
    9757           4 :         if (!skipNukeCrossCompartment) {
    9758             :           // The compartment nuking phase might be too expensive, so do that
    9759             :           // part off of idle dispatch.
    9760             : 
    9761             :           // For the compartment nuking phase, we dispatch either an
    9762             :           // inner-window-nuked or an outer-window-nuked notification.
    9763             :           // This will allow tests to wait for compartment nuking to happen.
    9764           4 :           if (mTopic.EqualsLiteral("inner-window-destroyed")) {
    9765           3 :             mTopic.AssignLiteral("inner-window-nuked");
    9766           1 :           } else if (mTopic.EqualsLiteral("outer-window-destroyed")) {
    9767           1 :             mTopic.AssignLiteral("outer-window-nuked");
    9768             :           }
    9769           4 :           mPhase = Phase::Nuking;
    9770             : 
    9771           8 :           nsCOMPtr<nsIRunnable> copy(this);
    9772           4 :           NS_IdleDispatchToCurrentThread(copy.forget(), 1000);
    9773             :         }
    9774             :       }
    9775           4 :       break;
    9776             : 
    9777             :       case Phase::Nuking:
    9778             :       {
    9779           8 :         nsCOMPtr<nsISupports> window = do_QueryReferent(mWindow);
    9780           4 :         if (window) {
    9781           4 :           nsGlobalWindow* win = nsGlobalWindow::FromSupports(window);
    9782           4 :           nsGlobalWindow* currentInner = win->IsInnerWindow() ? win : win->GetCurrentInnerWindowInternal();
    9783           4 :           NS_ENSURE_TRUE(currentInner, NS_OK);
    9784             : 
    9785           8 :           AutoSafeJSContext cx;
    9786           8 :           JS::Rooted<JSObject*> obj(cx, currentInner->FastGetGlobalJSObject());
    9787           4 :           if (obj && !js::IsSystemCompartment(js::GetObjectCompartment(obj))) {
    9788           3 :             JSCompartment* cpt = js::GetObjectCompartment(obj);
    9789           6 :             nsCOMPtr<nsIPrincipal> pc = nsJSPrincipals::get(JS_GetCompartmentPrincipals(cpt));
    9790             : 
    9791           6 :             nsAutoString addonId;
    9792           3 :             if (NS_SUCCEEDED(pc->GetAddonId(addonId)) && !addonId.IsEmpty()) {
    9793             :               // We want to nuke all references to the add-on compartment.
    9794           0 :               xpc::NukeAllWrappersForCompartment(cx, cpt,
    9795           0 :                                                  win->IsInnerWindow() ? js::DontNukeWindowReferences
    9796           0 :                                                                       : js::NukeWindowReferences);
    9797             :             } else {
    9798             :               // We only want to nuke wrappers for the chrome->content case
    9799           9 :               js::NukeCrossCompartmentWrappers(cx, BrowserCompartmentMatcher(), cpt,
    9800           3 :                                                win->IsInnerWindow() ? js::DontNukeWindowReferences
    9801             :                                                                     : js::NukeWindowReferences,
    9802           6 :                                                js::NukeIncomingReferences);
    9803             :             }
    9804             :           }
    9805             :         }
    9806             :       }
    9807           4 :       break;
    9808             :     }
    9809             : 
    9810           8 :     return NS_OK;
    9811             :   }
    9812             : 
    9813             : private:
    9814             :   uint64_t mID;
    9815             :   Phase mPhase;
    9816             :   nsCString mTopic;
    9817             :   nsWeakPtr mWindow;
    9818             : };
    9819             : 
    9820             : void
    9821           4 : nsGlobalWindow::NotifyWindowIDDestroyed(const char* aTopic)
    9822             : {
    9823           8 :   nsCOMPtr<nsIRunnable> runnable = new WindowDestroyedEvent(this, mWindowID, aTopic);
    9824             :   nsresult rv =
    9825           4 :     Dispatch("WindowDestroyedEvent", TaskCategory::Other, runnable.forget());
    9826           4 :   if (NS_SUCCEEDED(rv)) {
    9827           4 :     mNotifiedIDDestroyed = true;
    9828             :   }
    9829           4 : }
    9830             : 
    9831             : // static
    9832             : void
    9833           0 : nsGlobalWindow::NotifyDOMWindowFrozen(nsGlobalWindow* aWindow) {
    9834           0 :   if (aWindow && aWindow->IsInnerWindow()) {
    9835             :     nsCOMPtr<nsIObserverService> observerService =
    9836           0 :       services::GetObserverService();
    9837           0 :     if (observerService) {
    9838           0 :       observerService->
    9839           0 :         NotifyObservers(ToSupports(aWindow),
    9840           0 :                         DOM_WINDOW_FROZEN_TOPIC, nullptr);
    9841             :     }
    9842             :   }
    9843           0 : }
    9844             : 
    9845             : // static
    9846             : void
    9847           0 : nsGlobalWindow::NotifyDOMWindowThawed(nsGlobalWindow* aWindow) {
    9848           0 :   if (aWindow && aWindow->IsInnerWindow()) {
    9849             :     nsCOMPtr<nsIObserverService> observerService =
    9850           0 :       services::GetObserverService();
    9851           0 :     if (observerService) {
    9852           0 :       observerService->
    9853           0 :         NotifyObservers(ToSupports(aWindow),
    9854           0 :                         DOM_WINDOW_THAWED_TOPIC, nullptr);
    9855             :     }
    9856             :   }
    9857           0 : }
    9858             : 
    9859             : JSObject*
    9860           6 : nsGlobalWindow::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey)
    9861             : {
    9862          12 :   JS::Rooted<JSObject*> handler(RootingCx());
    9863           6 :   if (mCachedXBLPrototypeHandlers) {
    9864           5 :     mCachedXBLPrototypeHandlers->Get(aKey, handler.address());
    9865             :   }
    9866          12 :   return handler;
    9867             : }
    9868             : 
    9869             : void
    9870           4 : nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
    9871             :                                          JS::Handle<JSObject*> aHandler)
    9872             : {
    9873           4 :   if (!mCachedXBLPrototypeHandlers) {
    9874           1 :     mCachedXBLPrototypeHandlers = new XBLPrototypeHandlerTable();
    9875           1 :     PreserveWrapper(ToSupports(this));
    9876             :   }
    9877             : 
    9878           4 :   mCachedXBLPrototypeHandlers->Put(aKey, aHandler);
    9879           4 : }
    9880             : 
    9881             : Element*
    9882           0 : nsGlobalWindow::GetFrameElementOuter(nsIPrincipal& aSubjectPrincipal)
    9883             : {
    9884           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    9885             : 
    9886           0 :   if (!mDocShell || mDocShell->GetIsMozBrowser()) {
    9887           0 :     return nullptr;
    9888             :   }
    9889             : 
    9890             :   // Per HTML5, the frameElement getter returns null in cross-origin situations.
    9891           0 :   Element* element = GetRealFrameElementOuter();
    9892           0 :   if (!element) {
    9893           0 :     return nullptr;
    9894             :   }
    9895             : 
    9896           0 :   if (!aSubjectPrincipal.SubsumesConsideringDomain(element->NodePrincipal())) {
    9897           0 :     return nullptr;
    9898             :   }
    9899             : 
    9900           0 :   return element;
    9901             : }
    9902             : 
    9903             : Element*
    9904           0 : nsGlobalWindow::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
    9905             :                                 ErrorResult& aError)
    9906             : {
    9907           0 :   FORWARD_TO_OUTER_OR_THROW(GetFrameElementOuter, (aSubjectPrincipal), aError,
    9908             :                             nullptr);
    9909             : }
    9910             : 
    9911             : Element*
    9912           0 : nsGlobalWindow::GetRealFrameElementOuter()
    9913             : {
    9914           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
    9915             : 
    9916           0 :   if (!mDocShell) {
    9917           0 :     return nullptr;
    9918             :   }
    9919             : 
    9920           0 :   nsCOMPtr<nsIDocShell> parent;
    9921           0 :   mDocShell->GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent));
    9922             : 
    9923           0 :   if (!parent || parent == mDocShell) {
    9924             :     // We're at a chrome boundary, don't expose the chrome iframe
    9925             :     // element to content code.
    9926           0 :     return nullptr;
    9927             :   }
    9928             : 
    9929           0 :   return mFrameElement;
    9930             : }
    9931             : 
    9932             : Element*
    9933           0 : nsGlobalWindow::GetRealFrameElement(ErrorResult& aError)
    9934             : {
    9935           0 :   FORWARD_TO_OUTER_OR_THROW(GetRealFrameElementOuter, (), aError, nullptr);
    9936             : }
    9937             : 
    9938             : /**
    9939             :  * nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper
    9940             :  * around GetRealFrameElement.
    9941             :  */
    9942             : already_AddRefed<nsIDOMElement>
    9943           0 : nsGlobalWindow::GetFrameElement()
    9944             : {
    9945           0 :   FORWARD_TO_INNER(GetFrameElement, (), nullptr);
    9946             : 
    9947           0 :   ErrorResult dummy;
    9948             :   nsCOMPtr<nsIDOMElement> frameElement =
    9949           0 :     do_QueryInterface(GetRealFrameElement(dummy));
    9950           0 :   dummy.SuppressException();
    9951           0 :   return frameElement.forget();
    9952             : }
    9953             : 
    9954             : /* static */ bool
    9955           0 : nsGlobalWindow::TokenizeDialogOptions(nsAString& aToken,
    9956             :                                       nsAString::const_iterator& aIter,
    9957             :                                       nsAString::const_iterator aEnd)
    9958             : {
    9959           0 :   while (aIter != aEnd && nsCRT::IsAsciiSpace(*aIter)) {
    9960           0 :     ++aIter;
    9961             :   }
    9962             : 
    9963           0 :   if (aIter == aEnd) {
    9964           0 :     return false;
    9965             :   }
    9966             : 
    9967           0 :   if (*aIter == ';' || *aIter == ':' || *aIter == '=') {
    9968           0 :     aToken.Assign(*aIter);
    9969           0 :     ++aIter;
    9970           0 :     return true;
    9971             :   }
    9972             : 
    9973           0 :   nsAString::const_iterator start = aIter;
    9974             : 
    9975             :   // Skip characters until we find whitespace, ';', ':', or '='
    9976           0 :   while (aIter != aEnd && !nsCRT::IsAsciiSpace(*aIter) &&
    9977           0 :          *aIter != ';' &&
    9978           0 :          *aIter != ':' &&
    9979           0 :          *aIter != '=') {
    9980           0 :     ++aIter;
    9981             :   }
    9982             : 
    9983           0 :   aToken.Assign(Substring(start, aIter));
    9984           0 :   return true;
    9985             : }
    9986             : 
    9987             : // Helper for converting window.showModalDialog() options (list of ';'
    9988             : // separated name (:|=) value pairs) to a format that's parsable by
    9989             : // our normal window opening code.
    9990             : 
    9991             : /* static */
    9992             : void
    9993           0 : nsGlobalWindow::ConvertDialogOptions(const nsAString& aOptions,
    9994             :                                      nsAString& aResult)
    9995             : {
    9996           0 :   nsAString::const_iterator end;
    9997           0 :   aOptions.EndReading(end);
    9998             : 
    9999           0 :   nsAString::const_iterator iter;
   10000           0 :   aOptions.BeginReading(iter);
   10001             : 
   10002           0 :   nsAutoString token;
   10003           0 :   nsAutoString name;
   10004           0 :   nsAutoString value;
   10005             : 
   10006             :   while (true) {
   10007           0 :     if (!TokenizeDialogOptions(name, iter, end)) {
   10008           0 :       break;
   10009             :     }
   10010             : 
   10011             :     // Invalid name.
   10012           0 :     if (name.EqualsLiteral("=") ||
   10013           0 :         name.EqualsLiteral(":") ||
   10014           0 :         name.EqualsLiteral(";")) {
   10015           0 :       break;
   10016             :     }
   10017             : 
   10018           0 :     if (!TokenizeDialogOptions(token, iter, end)) {
   10019           0 :       break;
   10020             :     }
   10021             : 
   10022           0 :     if (!token.EqualsLiteral(":") && !token.EqualsLiteral("=")) {
   10023           0 :       continue;
   10024             :     }
   10025             : 
   10026             :     // We found name followed by ':' or '='. Look for a value.
   10027           0 :     if (!TokenizeDialogOptions(value, iter, end)) {
   10028           0 :       break;
   10029             :     }
   10030             : 
   10031           0 :     if (name.LowerCaseEqualsLiteral("center")) {
   10032           0 :       if (value.LowerCaseEqualsLiteral("on")  ||
   10033           0 :           value.LowerCaseEqualsLiteral("yes") ||
   10034           0 :           value.LowerCaseEqualsLiteral("1")) {
   10035           0 :         aResult.AppendLiteral(",centerscreen=1");
   10036             :       }
   10037           0 :     } else if (name.LowerCaseEqualsLiteral("dialogwidth")) {
   10038           0 :       if (!value.IsEmpty()) {
   10039           0 :         aResult.AppendLiteral(",width=");
   10040           0 :         aResult.Append(value);
   10041             :       }
   10042           0 :     } else if (name.LowerCaseEqualsLiteral("dialogheight")) {
   10043           0 :       if (!value.IsEmpty()) {
   10044           0 :         aResult.AppendLiteral(",height=");
   10045           0 :         aResult.Append(value);
   10046             :       }
   10047           0 :     } else if (name.LowerCaseEqualsLiteral("dialogtop")) {
   10048           0 :       if (!value.IsEmpty()) {
   10049           0 :         aResult.AppendLiteral(",top=");
   10050           0 :         aResult.Append(value);
   10051             :       }
   10052           0 :     } else if (name.LowerCaseEqualsLiteral("dialogleft")) {
   10053           0 :       if (!value.IsEmpty()) {
   10054           0 :         aResult.AppendLiteral(",left=");
   10055           0 :         aResult.Append(value);
   10056             :       }
   10057           0 :     } else if (name.LowerCaseEqualsLiteral("resizable")) {
   10058           0 :       if (value.LowerCaseEqualsLiteral("on")  ||
   10059           0 :           value.LowerCaseEqualsLiteral("yes") ||
   10060           0 :           value.LowerCaseEqualsLiteral("1")) {
   10061           0 :         aResult.AppendLiteral(",resizable=1");
   10062             :       }
   10063           0 :     } else if (name.LowerCaseEqualsLiteral("scroll")) {
   10064           0 :       if (value.LowerCaseEqualsLiteral("off")  ||
   10065           0 :           value.LowerCaseEqualsLiteral("no") ||
   10066           0 :           value.LowerCaseEqualsLiteral("0")) {
   10067           0 :         aResult.AppendLiteral(",scrollbars=0");
   10068             :       }
   10069             :     }
   10070             : 
   10071           0 :     if (iter == end ||
   10072           0 :         !TokenizeDialogOptions(token, iter, end) ||
   10073           0 :         !token.EqualsLiteral(";")) {
   10074           0 :       break;
   10075             :     }
   10076             :   }
   10077           0 : }
   10078             : 
   10079             : already_AddRefed<nsIVariant>
   10080           0 : nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl,
   10081             :                                      nsIVariant* aArgument,
   10082             :                                      const nsAString& aOptions,
   10083             :                                      nsIPrincipal& aSubjectPrincipal,
   10084             :                                      ErrorResult& aError)
   10085             : {
   10086           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   10087             : 
   10088           0 :   if (mDoc) {
   10089           0 :     mDoc->WarnOnceAbout(nsIDocument::eShowModalDialog);
   10090             :   }
   10091             : 
   10092           0 :   if (!IsShowModalDialogEnabled()) {
   10093           0 :     aError.Throw(NS_ERROR_NOT_AVAILABLE);
   10094           0 :     return nullptr;
   10095             :   }
   10096             : 
   10097             :   RefPtr<DialogValueHolder> argHolder =
   10098           0 :     new DialogValueHolder(&aSubjectPrincipal, aArgument);
   10099             : 
   10100             :   // Before bringing up the window/dialog, unsuppress painting and flush
   10101             :   // pending reflows.
   10102           0 :   EnsureReflowFlushAndPaint();
   10103             : 
   10104           0 :   if (!AreDialogsEnabled()) {
   10105             :     // We probably want to keep throwing here; silently doing nothing is a bit
   10106             :     // weird given the typical use cases of showModalDialog().
   10107           0 :     aError.Throw(NS_ERROR_NOT_AVAILABLE);
   10108           0 :     return nullptr;
   10109             :   }
   10110             : 
   10111           0 :   if (ShouldPromptToBlockDialogs() && !ConfirmDialogIfNeeded()) {
   10112           0 :     aError.Throw(NS_ERROR_NOT_AVAILABLE);
   10113           0 :     return nullptr;
   10114             :   }
   10115             : 
   10116           0 :   nsCOMPtr<nsPIDOMWindowOuter> dlgWin;
   10117           0 :   nsAutoString options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
   10118             : 
   10119           0 :   ConvertDialogOptions(aOptions, options);
   10120             : 
   10121           0 :   options.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
   10122             : 
   10123           0 :   EnterModalState();
   10124           0 :   uint32_t oldMicroTaskLevel = nsContentUtils::MicroTaskLevel();
   10125           0 :   nsContentUtils::SetMicroTaskLevel(0);
   10126           0 :   aError = OpenInternal(aUrl, EmptyString(), options,
   10127             :                         false,          // aDialog
   10128             :                         true,           // aContentModal
   10129             :                         true,           // aCalledNoScript
   10130             :                         true,           // aDoJSFixups
   10131             :                         true,           // aNavigate
   10132             :                         nullptr, argHolder, // args
   10133             :                         nullptr,        // aLoadInfo
   10134             :                         false,          // aForceNoOpener
   10135           0 :                         getter_AddRefs(dlgWin));
   10136           0 :   nsContentUtils::SetMicroTaskLevel(oldMicroTaskLevel);
   10137           0 :   LeaveModalState();
   10138           0 :   if (aError.Failed()) {
   10139           0 :     return nullptr;
   10140             :   }
   10141             : 
   10142           0 :   nsCOMPtr<nsIDOMModalContentWindow> dialog = do_QueryInterface(dlgWin);
   10143           0 :   if (!dialog) {
   10144           0 :     return nullptr;
   10145             :   }
   10146             : 
   10147           0 :   nsCOMPtr<nsIVariant> retVal;
   10148           0 :   aError = dialog->GetReturnValue(getter_AddRefs(retVal));
   10149           0 :   MOZ_ASSERT(!aError.Failed());
   10150             : 
   10151           0 :   return retVal.forget();
   10152             : }
   10153             : 
   10154             : already_AddRefed<nsIVariant>
   10155           0 : nsGlobalWindow::ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
   10156             :                                 const nsAString& aOptions,
   10157             :                                 nsIPrincipal& aSubjectPrincipal,
   10158             :                                 ErrorResult& aError)
   10159             : {
   10160           0 :   FORWARD_TO_OUTER_OR_THROW(ShowModalDialogOuter,
   10161             :                             (aUrl, aArgument, aOptions, aSubjectPrincipal,
   10162             :                              aError), aError, nullptr);
   10163             : }
   10164             : 
   10165             : void
   10166           0 : nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
   10167             :                                 JS::Handle<JS::Value> aArgument,
   10168             :                                 const nsAString& aOptions,
   10169             :                                 JS::MutableHandle<JS::Value> aRetval,
   10170             :                                 nsIPrincipal& aSubjectPrincipal,
   10171             :                                 ErrorResult& aError)
   10172             : {
   10173           0 :   MOZ_ASSERT(IsInnerWindow());
   10174             : 
   10175           0 :   nsCOMPtr<nsIVariant> args;
   10176           0 :   aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
   10177             :                                                     aArgument,
   10178           0 :                                                     getter_AddRefs(args));
   10179           0 :   if (aError.Failed()) {
   10180           0 :     return;
   10181             :   }
   10182             : 
   10183             :   nsCOMPtr<nsIVariant> retVal =
   10184           0 :     ShowModalDialog(aUrl, args, aOptions, aSubjectPrincipal, aError);
   10185           0 :   if (aError.Failed()) {
   10186           0 :     return;
   10187             :   }
   10188             : 
   10189           0 :   JS::Rooted<JS::Value> result(aCx);
   10190           0 :   if (retVal) {
   10191           0 :     JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
   10192           0 :     if (!global) {
   10193           0 :       global = FastGetGlobalJSObject();
   10194             :     }
   10195           0 :     aError = nsContentUtils::XPConnect()->VariantToJS(aCx,
   10196             :                                                       global,
   10197           0 :                                                       retVal, aRetval);
   10198             :   } else {
   10199           0 :     aRetval.setNull();
   10200             :   }
   10201             : }
   10202             : 
   10203           6 : class ChildCommandDispatcher : public Runnable
   10204             : {
   10205             : public:
   10206           2 :   ChildCommandDispatcher(nsGlobalWindow* aWindow,
   10207             :                          nsITabChild* aTabChild,
   10208             :                          const nsAString& aAction)
   10209           2 :     : mozilla::Runnable("ChildCommandDispatcher")
   10210             :     , mWindow(aWindow)
   10211             :     , mTabChild(aTabChild)
   10212           2 :     , mAction(aAction)
   10213             :   {
   10214           2 :   }
   10215             : 
   10216           2 :   NS_IMETHOD Run() override
   10217             :   {
   10218           4 :     nsCOMPtr<nsPIWindowRoot> root = mWindow->GetTopWindowRoot();
   10219           2 :     if (!root) {
   10220           0 :       return NS_OK;
   10221             :     }
   10222             : 
   10223           4 :     nsTArray<nsCString> enabledCommands, disabledCommands;
   10224           2 :     root->GetEnabledDisabledCommands(enabledCommands, disabledCommands);
   10225           2 :     if (enabledCommands.Length() || disabledCommands.Length()) {
   10226           2 :       mTabChild->EnableDisableCommands(mAction, enabledCommands, disabledCommands);
   10227             :     }
   10228             : 
   10229           2 :     return NS_OK;
   10230             :   }
   10231             : 
   10232             : private:
   10233             :   RefPtr<nsGlobalWindow>             mWindow;
   10234             :   nsCOMPtr<nsITabChild>                mTabChild;
   10235             :   nsString                             mAction;
   10236             : };
   10237             : 
   10238           9 : class CommandDispatcher : public Runnable
   10239             : {
   10240             : public:
   10241           3 :   CommandDispatcher(nsIDOMXULCommandDispatcher* aDispatcher,
   10242             :                     const nsAString& aAction)
   10243           3 :     : mozilla::Runnable("CommandDispatcher")
   10244             :     , mDispatcher(aDispatcher)
   10245           3 :     , mAction(aAction)
   10246             :   {
   10247           3 :   }
   10248             : 
   10249           3 :   NS_IMETHOD Run() override
   10250             :   {
   10251           3 :     return mDispatcher->UpdateCommands(mAction);
   10252             :   }
   10253             : 
   10254             :   nsCOMPtr<nsIDOMXULCommandDispatcher> mDispatcher;
   10255             :   nsString                             mAction;
   10256             : };
   10257             : 
   10258             : nsresult
   10259           5 : nsGlobalWindow::UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason)
   10260             : {
   10261             :   // If this is a child process, redirect to the parent process.
   10262           5 :   if (nsIDocShell* docShell = GetDocShell()) {
   10263           8 :     if (nsCOMPtr<nsITabChild> child = docShell->GetTabChild()) {
   10264             :       nsContentUtils::AddScriptRunner(new ChildCommandDispatcher(this, child,
   10265           4 :                                                                  anAction));
   10266           2 :       return NS_OK;
   10267             :     }
   10268             :   }
   10269             : 
   10270           3 :   nsPIDOMWindowOuter *rootWindow = nsGlobalWindow::GetPrivateRoot();
   10271           3 :   if (!rootWindow)
   10272           0 :     return NS_OK;
   10273             : 
   10274             :   nsCOMPtr<nsIDOMXULDocument> xulDoc =
   10275           6 :     do_QueryInterface(rootWindow->GetExtantDoc());
   10276             :   // See if we contain a XUL document.
   10277             :   // selectionchange action is only used for mozbrowser, not for XUL. So we bypass
   10278             :   // XUL command dispatch if anAction is "selectionchange".
   10279           3 :   if (xulDoc && !anAction.EqualsLiteral("selectionchange")) {
   10280             :     // Retrieve the command dispatcher and call updateCommands on it.
   10281           6 :     nsCOMPtr<nsIDOMXULCommandDispatcher> xulCommandDispatcher;
   10282           3 :     xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher));
   10283           3 :     if (xulCommandDispatcher) {
   10284             :       nsContentUtils::AddScriptRunner(new CommandDispatcher(xulCommandDispatcher,
   10285           6 :                                                             anAction));
   10286             :     }
   10287             :   }
   10288             : 
   10289           3 :   return NS_OK;
   10290             : }
   10291             : 
   10292             : Selection*
   10293           0 : nsGlobalWindow::GetSelectionOuter()
   10294             : {
   10295           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   10296             : 
   10297           0 :   if (!mDocShell) {
   10298           0 :     return nullptr;
   10299             :   }
   10300             : 
   10301           0 :   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   10302           0 :   if (!presShell) {
   10303           0 :     return nullptr;
   10304             :   }
   10305             :   nsISelection* domSelection =
   10306           0 :     presShell->GetCurrentSelection(SelectionType::eNormal);
   10307           0 :   return domSelection ? domSelection->AsSelection() : nullptr;
   10308             : }
   10309             : 
   10310             : Selection*
   10311           0 : nsGlobalWindow::GetSelection(ErrorResult& aError)
   10312             : {
   10313           0 :   FORWARD_TO_OUTER_OR_THROW(GetSelectionOuter, (), aError, nullptr);
   10314             : }
   10315             : 
   10316             : already_AddRefed<nsISelection>
   10317           0 : nsGlobalWindow::GetSelection()
   10318             : {
   10319           0 :   nsCOMPtr<nsISelection> selection = GetSelectionOuter();
   10320           0 :   return selection.forget();
   10321             : }
   10322             : 
   10323             : bool
   10324           0 : nsGlobalWindow::FindOuter(const nsAString& aString, bool aCaseSensitive,
   10325             :                           bool aBackwards, bool aWrapAround, bool aWholeWord,
   10326             :                           bool aSearchInFrames, bool aShowDialog,
   10327             :                           ErrorResult& aError)
   10328             : {
   10329           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   10330             : 
   10331             :   Unused << aShowDialog;
   10332             : 
   10333           0 :   if (Preferences::GetBool("dom.disable_window_find", false)) {
   10334           0 :     aError.Throw(NS_ERROR_NOT_AVAILABLE);
   10335           0 :     return false;
   10336             :   }
   10337             : 
   10338           0 :   nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(mDocShell));
   10339           0 :   if (!finder) {
   10340           0 :     aError.Throw(NS_ERROR_NOT_AVAILABLE);
   10341           0 :     return false;
   10342             :   }
   10343             : 
   10344             :   // Set the options of the search
   10345           0 :   aError = finder->SetSearchString(PromiseFlatString(aString).get());
   10346           0 :   if (aError.Failed()) {
   10347           0 :     return false;
   10348             :   }
   10349           0 :   finder->SetMatchCase(aCaseSensitive);
   10350           0 :   finder->SetFindBackwards(aBackwards);
   10351           0 :   finder->SetWrapFind(aWrapAround);
   10352           0 :   finder->SetEntireWord(aWholeWord);
   10353           0 :   finder->SetSearchFrames(aSearchInFrames);
   10354             : 
   10355             :   // the nsIWebBrowserFind is initialized to use this window
   10356             :   // as the search root, but uses focus to set the current search
   10357             :   // frame. If we're being called from JS (as here), this window
   10358             :   // should be the current search frame.
   10359           0 :   nsCOMPtr<nsIWebBrowserFindInFrames> framesFinder(do_QueryInterface(finder));
   10360           0 :   if (framesFinder) {
   10361           0 :     framesFinder->SetRootSearchFrame(AsOuter());   // paranoia
   10362           0 :     framesFinder->SetCurrentSearchFrame(AsOuter());
   10363             :   }
   10364             : 
   10365           0 :   if (aString.IsEmpty()) {
   10366           0 :     return false;
   10367             :   }
   10368             : 
   10369             :   // Launch the search with the passed in search string
   10370           0 :   bool didFind = false;
   10371           0 :   aError = finder->FindNext(&didFind);
   10372           0 :   return didFind;
   10373             : }
   10374             : 
   10375             : bool
   10376           0 : nsGlobalWindow::Find(const nsAString& aString, bool aCaseSensitive,
   10377             :                      bool aBackwards, bool aWrapAround, bool aWholeWord,
   10378             :                      bool aSearchInFrames, bool aShowDialog,
   10379             :                      ErrorResult& aError)
   10380             : {
   10381           0 :   FORWARD_TO_OUTER_OR_THROW(FindOuter,
   10382             :                             (aString, aCaseSensitive, aBackwards, aWrapAround,
   10383             :                              aWholeWord, aSearchInFrames, aShowDialog, aError),
   10384             :                             aError, false);
   10385             : }
   10386             : 
   10387             : void
   10388           0 : nsGlobalWindow::GetOrigin(nsAString& aOrigin)
   10389             : {
   10390           0 :   MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
   10391           0 :   nsContentUtils::GetUTFOrigin(GetPrincipal(), aOrigin);
   10392           0 : }
   10393             : 
   10394             : void
   10395           0 : nsGlobalWindow::Atob(const nsAString& aAsciiBase64String,
   10396             :                      nsAString& aBinaryData, ErrorResult& aError)
   10397             : {
   10398           0 :   MOZ_ASSERT(IsInnerWindow());
   10399           0 :   aError = nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
   10400           0 : }
   10401             : 
   10402             : void
   10403           0 : nsGlobalWindow::Btoa(const nsAString& aBinaryData,
   10404             :                      nsAString& aAsciiBase64String, ErrorResult& aError)
   10405             : {
   10406           0 :   MOZ_ASSERT(IsInnerWindow());
   10407           0 :   aError = nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
   10408           0 : }
   10409             : 
   10410             : //*****************************************************************************
   10411             : // nsGlobalWindow::nsIDOMEventTarget
   10412             : //*****************************************************************************
   10413             : 
   10414             : nsPIDOMWindowOuter*
   10415           0 : nsGlobalWindow::GetOwnerGlobalForBindings()
   10416             : {
   10417           0 :   if (IsOuterWindow()) {
   10418           0 :     return AsOuter();
   10419             :   }
   10420             : 
   10421           0 :   return nsPIDOMWindowOuter::GetFromCurrentInner(AsInner());
   10422             : }
   10423             : 
   10424             : NS_IMETHODIMP
   10425           0 : nsGlobalWindow::RemoveEventListener(const nsAString& aType,
   10426             :                                     nsIDOMEventListener* aListener,
   10427             :                                     bool aUseCapture)
   10428             : {
   10429           0 :   if (RefPtr<EventListenerManager> elm = GetExistingListenerManager()) {
   10430           0 :     elm->RemoveEventListener(aType, aListener, aUseCapture);
   10431             :   }
   10432           0 :   return NS_OK;
   10433             : }
   10434             : 
   10435           0 : NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsGlobalWindow)
   10436             : 
   10437             : NS_IMETHODIMP
   10438           8 : nsGlobalWindow::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
   10439             : {
   10440           8 :   FORWARD_TO_INNER(DispatchEvent, (aEvent, aRetVal), NS_OK);
   10441             : 
   10442           7 :   if (!AsInner()->IsCurrentInnerWindow()) {
   10443             :     NS_WARNING("DispatchEvent called on non-current inner window, dropping. "
   10444           0 :                "Please check the window in the caller instead.");
   10445           0 :     return NS_ERROR_FAILURE;
   10446             :   }
   10447             : 
   10448           7 :   if (!mDoc) {
   10449           0 :     return NS_ERROR_FAILURE;
   10450             :   }
   10451             : 
   10452             :   // Obtain a presentation shell
   10453           7 :   nsIPresShell *shell = mDoc->GetShell();
   10454          14 :   RefPtr<nsPresContext> presContext;
   10455           7 :   if (shell) {
   10456             :     // Retrieve the context
   10457           7 :     presContext = shell->GetPresContext();
   10458             :   }
   10459             : 
   10460           7 :   nsEventStatus status = nsEventStatus_eIgnore;
   10461           7 :   nsresult rv = EventDispatcher::DispatchDOMEvent(AsInner(), nullptr, aEvent,
   10462           7 :                                                   presContext, &status);
   10463             : 
   10464           7 :   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
   10465           7 :   return rv;
   10466             : }
   10467             : 
   10468             : NS_IMETHODIMP
   10469           0 : nsGlobalWindow::AddEventListener(const nsAString& aType,
   10470             :                                  nsIDOMEventListener *aListener,
   10471             :                                  bool aUseCapture, bool aWantsUntrusted,
   10472             :                                  uint8_t aOptionalArgc)
   10473             : {
   10474           0 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
   10475             :                "Won't check if this is chrome, you want to set "
   10476             :                "aWantsUntrusted to false or make the aWantsUntrusted "
   10477             :                "explicit by making optional_argc non-zero.");
   10478             : 
   10479           0 :   if (!aWantsUntrusted &&
   10480           0 :       (aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
   10481           0 :     aWantsUntrusted = true;
   10482             :   }
   10483             : 
   10484           0 :   EventListenerManager* manager = GetOrCreateListenerManager();
   10485           0 :   NS_ENSURE_STATE(manager);
   10486           0 :   manager->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
   10487           0 :   return NS_OK;
   10488             : }
   10489             : 
   10490             : void
   10491          49 : nsGlobalWindow::AddEventListener(const nsAString& aType,
   10492             :                                  EventListener* aListener,
   10493             :                                  const AddEventListenerOptionsOrBoolean& aOptions,
   10494             :                                  const Nullable<bool>& aWantsUntrusted,
   10495             :                                  ErrorResult& aRv)
   10496             : {
   10497          49 :   if (IsOuterWindow() && mInnerWindow &&
   10498           0 :       !nsContentUtils::CanCallerAccess(mInnerWindow)) {
   10499           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
   10500           0 :     return;
   10501             :   }
   10502             : 
   10503             :   bool wantsUntrusted;
   10504          49 :   if (aWantsUntrusted.IsNull()) {
   10505          47 :     wantsUntrusted = !nsContentUtils::IsChromeDoc(mDoc);
   10506             :   } else {
   10507           2 :     wantsUntrusted = aWantsUntrusted.Value();
   10508             :   }
   10509             : 
   10510          49 :   EventListenerManager* manager = GetOrCreateListenerManager();
   10511          49 :   if (!manager) {
   10512           0 :     aRv.Throw(NS_ERROR_UNEXPECTED);
   10513           0 :     return;
   10514             :   }
   10515             : 
   10516          49 :   manager->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
   10517             : }
   10518             : 
   10519             : NS_IMETHODIMP
   10520           0 : nsGlobalWindow::AddSystemEventListener(const nsAString& aType,
   10521             :                                        nsIDOMEventListener *aListener,
   10522             :                                        bool aUseCapture,
   10523             :                                        bool aWantsUntrusted,
   10524             :                                        uint8_t aOptionalArgc)
   10525             : {
   10526           0 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
   10527             :                "Won't check if this is chrome, you want to set "
   10528             :                "aWantsUntrusted to false or make the aWantsUntrusted "
   10529             :                "explicit by making optional_argc non-zero.");
   10530             : 
   10531           0 :   if (IsOuterWindow() && mInnerWindow &&
   10532           0 :       !nsContentUtils::LegacyIsCallerNativeCode() &&
   10533           0 :       !nsContentUtils::CanCallerAccess(mInnerWindow)) {
   10534           0 :     return NS_ERROR_DOM_SECURITY_ERR;
   10535             :   }
   10536             : 
   10537           0 :   if (!aWantsUntrusted &&
   10538           0 :       (aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
   10539           0 :     aWantsUntrusted = true;
   10540             :   }
   10541             : 
   10542           0 :   return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
   10543           0 :                                    aWantsUntrusted);
   10544             : }
   10545             : 
   10546             : EventListenerManager*
   10547          52 : nsGlobalWindow::GetOrCreateListenerManager()
   10548             : {
   10549          52 :   FORWARD_TO_INNER_CREATE(GetOrCreateListenerManager, (), nullptr);
   10550             : 
   10551          52 :   if (!mListenerManager) {
   10552             :     mListenerManager =
   10553           2 :       new EventListenerManager(static_cast<EventTarget*>(this));
   10554             :   }
   10555             : 
   10556          52 :   return mListenerManager;
   10557             : }
   10558             : 
   10559             : EventListenerManager*
   10560         347 : nsGlobalWindow::GetExistingListenerManager() const
   10561             : {
   10562         347 :   FORWARD_TO_INNER(GetExistingListenerManager, (), nullptr);
   10563             : 
   10564         294 :   return mListenerManager;
   10565             : }
   10566             : 
   10567             : nsIScriptContext*
   10568           0 : nsGlobalWindow::GetContextForEventHandlers(nsresult* aRv)
   10569             : {
   10570           0 :   *aRv = NS_ERROR_UNEXPECTED;
   10571           0 :   NS_ENSURE_TRUE(!IsInnerWindow() || AsInner()->IsCurrentInnerWindow(), nullptr);
   10572             : 
   10573             :   nsIScriptContext* scx;
   10574           0 :   if ((scx = GetContext())) {
   10575           0 :     *aRv = NS_OK;
   10576           0 :     return scx;
   10577             :   }
   10578           0 :   return nullptr;
   10579             : }
   10580             : 
   10581             : //*****************************************************************************
   10582             : // nsGlobalWindow::nsPIDOMWindow
   10583             : //*****************************************************************************
   10584             : 
   10585             : nsPIDOMWindowOuter*
   10586          27 : nsGlobalWindow::GetPrivateParent()
   10587             : {
   10588          27 :   MOZ_ASSERT(IsOuterWindow());
   10589             : 
   10590          54 :   nsCOMPtr<nsPIDOMWindowOuter> parent = GetParent();
   10591             : 
   10592          27 :   if (AsOuter() == parent) {
   10593          54 :     nsCOMPtr<nsIContent> chromeElement(do_QueryInterface(mChromeEventHandler));
   10594          27 :     if (!chromeElement)
   10595          27 :       return nullptr;             // This is ok, just means a null parent.
   10596             : 
   10597           0 :     nsIDocument* doc = chromeElement->GetComposedDoc();
   10598           0 :     if (!doc)
   10599           0 :       return nullptr;             // This is ok, just means a null parent.
   10600             : 
   10601           0 :     return doc->GetWindow();
   10602             :   }
   10603             : 
   10604           0 :   return parent;
   10605             : }
   10606             : 
   10607             : nsPIDOMWindowOuter*
   10608          60 : nsGlobalWindow::GetPrivateRoot()
   10609             : {
   10610          60 :   if (IsInnerWindow()) {
   10611           2 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   10612           2 :     if (!outer) {
   10613           0 :       NS_WARNING("No outer window available!");
   10614           0 :       return nullptr;
   10615             :     }
   10616           2 :     return outer->GetPrivateRoot();
   10617             :   }
   10618             : 
   10619         116 :   nsCOMPtr<nsPIDOMWindowOuter> top = GetTop();
   10620             : 
   10621         116 :   nsCOMPtr<nsIContent> chromeElement(do_QueryInterface(mChromeEventHandler));
   10622          58 :   if (chromeElement) {
   10623           2 :     nsIDocument* doc = chromeElement->GetComposedDoc();
   10624           2 :     if (doc) {
   10625           4 :       nsCOMPtr<nsPIDOMWindowOuter> parent = doc->GetWindow();
   10626           2 :       if (parent) {
   10627           2 :         top = parent->GetTop();
   10628             :       }
   10629             :     }
   10630             :   }
   10631             : 
   10632          58 :   return top;
   10633             : }
   10634             : 
   10635             : Location*
   10636           8 : nsGlobalWindow::GetLocation()
   10637             : {
   10638             :   // This method can be called on the outer window as well.
   10639           8 :   FORWARD_TO_INNER(GetLocation, (), nullptr);
   10640             : 
   10641           8 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   10642             : 
   10643           8 :   if (!mLocation) {
   10644           6 :     mLocation = new dom::Location(AsInner(), GetDocShell());
   10645             :   }
   10646             : 
   10647           8 :   return mLocation;
   10648             : }
   10649             : 
   10650             : void
   10651           4 : nsGlobalWindow::ActivateOrDeactivate(bool aActivate)
   10652             : {
   10653           4 :   MOZ_ASSERT(IsOuterWindow());
   10654             : 
   10655           4 :   if (!mDoc) {
   10656           0 :     return;
   10657             :   }
   10658             : 
   10659             :   // Set / unset mIsActive on the top level window, which is used for the
   10660             :   // :-moz-window-inactive pseudoclass, and its sheet (if any).
   10661           8 :   nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
   10662           8 :   nsCOMPtr<nsIWidget> topLevelWidget;
   10663           4 :   if (mainWidget) {
   10664             :     // Get the top level widget (if the main widget is a sheet, this will
   10665             :     // be the sheet's top (non-sheet) parent).
   10666           1 :     topLevelWidget = mainWidget->GetSheetWindowParent();
   10667           1 :     if (!topLevelWidget) {
   10668           1 :       topLevelWidget = mainWidget;
   10669             :     }
   10670             :   }
   10671             : 
   10672           4 :   SetActive(aActivate);
   10673             : 
   10674           4 :   if (mainWidget != topLevelWidget) {
   10675             :     // This is a workaround for the following problem:
   10676             :     // When a window with an open sheet gains or loses focus, only the sheet
   10677             :     // window receives the NS_ACTIVATE/NS_DEACTIVATE event.  However the
   10678             :     // styling of the containing top level window also needs to change.  We
   10679             :     // get around this by calling nsPIDOMWindow::SetActive() on both windows.
   10680             : 
   10681             :     // Get the top level widget's nsGlobalWindow
   10682           0 :     nsCOMPtr<nsPIDOMWindowOuter> topLevelWindow;
   10683             : 
   10684             :     // widgetListener should be a nsXULWindow
   10685           0 :     nsIWidgetListener* listener = topLevelWidget->GetWidgetListener();
   10686           0 :     if (listener) {
   10687           0 :       nsCOMPtr<nsIXULWindow> window = listener->GetXULWindow();
   10688           0 :       nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(window));
   10689           0 :       topLevelWindow = do_GetInterface(req);
   10690             :     }
   10691             : 
   10692           0 :     if (topLevelWindow) {
   10693           0 :       topLevelWindow->SetActive(aActivate);
   10694             :     }
   10695             :   }
   10696             : }
   10697             : 
   10698             : static bool
   10699           5 : NotifyDocumentTree(nsIDocument* aDocument, void* aData)
   10700             : {
   10701           5 :   aDocument->EnumerateSubDocuments(NotifyDocumentTree, nullptr);
   10702           5 :   aDocument->DocumentStatesChanged(NS_DOCUMENT_STATE_WINDOW_INACTIVE);
   10703           5 :   return true;
   10704             : }
   10705             : 
   10706             : void
   10707           4 : nsGlobalWindow::SetActive(bool aActive)
   10708             : {
   10709           4 :   nsPIDOMWindow::SetActive(aActive);
   10710           4 :   if (mDoc) {
   10711           4 :     NotifyDocumentTree(mDoc, nullptr);
   10712             :   }
   10713           4 : }
   10714             : 
   10715             : bool
   10716           0 : nsGlobalWindow::IsTopLevelWindowActive()
   10717             : {
   10718           0 :    nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShell());
   10719           0 :    if (!treeItem) {
   10720           0 :      return false;
   10721             :    }
   10722             : 
   10723           0 :    nsCOMPtr<nsIDocShellTreeItem> rootItem;
   10724           0 :    treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
   10725           0 :    if (!rootItem) {
   10726           0 :      return false;
   10727             :    }
   10728             : 
   10729           0 :    nsCOMPtr<nsPIDOMWindowOuter> domWindow = rootItem->GetWindow();
   10730           0 :    return domWindow && domWindow->IsActive();
   10731             : }
   10732             : 
   10733           0 : void nsGlobalWindow::SetIsBackground(bool aIsBackground)
   10734             : {
   10735           0 :   MOZ_ASSERT(IsOuterWindow());
   10736             : 
   10737           0 :   bool changed = aIsBackground != AsOuter()->IsBackground();
   10738           0 :   SetIsBackgroundInternal(aIsBackground);
   10739             : 
   10740           0 :   nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
   10741             : 
   10742           0 :   if (inner && changed) {
   10743           0 :     inner->mTimeoutManager->UpdateBackgroundState();
   10744             :   }
   10745             : 
   10746           0 :   if (aIsBackground) {
   10747             :     // Notify gamepadManager we are at the background window,
   10748             :     // we need to stop vibrate.
   10749           0 :     if (inner) {
   10750           0 :       inner->StopGamepadHaptics();
   10751             :     }
   10752           0 :     return;
   10753             :   }
   10754             : 
   10755           0 :   if (inner) {
   10756           0 :     inner->SyncGamepadState();
   10757             :   }
   10758             : }
   10759             : 
   10760             : void
   10761           5 : nsGlobalWindow::SetIsBackgroundInternal(bool aIsBackground)
   10762             : {
   10763           5 :   if (mIsBackground != aIsBackground) {
   10764           0 :     TabGroup()->WindowChangedBackgroundStatus(aIsBackground);
   10765             :   }
   10766           5 :   mIsBackground = aIsBackground;
   10767           5 : }
   10768             : 
   10769           1 : void nsGlobalWindow::MaybeUpdateTouchState()
   10770             : {
   10771           1 :   FORWARD_TO_INNER_VOID(MaybeUpdateTouchState, ());
   10772             : 
   10773           1 :   if (mMayHaveTouchEventListener) {
   10774             :     nsCOMPtr<nsIObserverService> observerService =
   10775           2 :       services::GetObserverService();
   10776             : 
   10777           1 :     if (observerService) {
   10778           2 :       observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
   10779             :                                        DOM_TOUCH_LISTENER_ADDED,
   10780           2 :                                        nullptr);
   10781             :     }
   10782             :   }
   10783             : }
   10784             : 
   10785             : void
   10786           0 : nsGlobalWindow::EnableGamepadUpdates()
   10787             : {
   10788           0 :   MOZ_ASSERT(IsInnerWindow());
   10789             : 
   10790           0 :   if (mHasGamepad) {
   10791           0 :     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
   10792           0 :     if (gamepadManager) {
   10793           0 :       gamepadManager->AddListener(this);
   10794             :     }
   10795             :   }
   10796           0 : }
   10797             : 
   10798             : void
   10799           4 : nsGlobalWindow::DisableGamepadUpdates()
   10800             : {
   10801           4 :   MOZ_ASSERT(IsInnerWindow());
   10802             : 
   10803           4 :   if (mHasGamepad) {
   10804           0 :     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
   10805           0 :     if (gamepadManager) {
   10806           0 :       gamepadManager->RemoveListener(this);
   10807             :     }
   10808             :   }
   10809           4 : }
   10810             : 
   10811             : void
   10812           0 : nsGlobalWindow::EnableVRUpdates()
   10813             : {
   10814           0 :   MOZ_ASSERT(IsInnerWindow());
   10815             : 
   10816           0 :   if (mHasVREvents && !mVREventObserver) {
   10817           0 :     mVREventObserver = new VREventObserver(this);
   10818             :   }
   10819           0 : }
   10820             : 
   10821             : void
   10822           4 : nsGlobalWindow::DisableVRUpdates()
   10823             : {
   10824           4 :   MOZ_ASSERT(IsInnerWindow());
   10825           4 :   if (mVREventObserver) {
   10826           0 :     mVREventObserver->DisconnectFromOwner();
   10827           0 :     mVREventObserver = nullptr;
   10828             :   }
   10829           4 : }
   10830             : 
   10831             : void
   10832           1 : nsGlobalWindow::SetChromeEventHandler(EventTarget* aChromeEventHandler)
   10833             : {
   10834           1 :   MOZ_ASSERT(IsOuterWindow());
   10835             : 
   10836           1 :   SetChromeEventHandlerInternal(aChromeEventHandler);
   10837             :   // update the chrome event handler on all our inner windows
   10838           1 :   for (nsGlobalWindow *inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
   10839           1 :        inner != this;
   10840           0 :        inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
   10841           0 :     NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == AsOuter(),
   10842             :                  "bad outer window pointer");
   10843           0 :     inner->SetChromeEventHandlerInternal(aChromeEventHandler);
   10844             :   }
   10845           1 : }
   10846             : 
   10847           0 : static bool IsLink(nsIContent* aContent)
   10848             : {
   10849           0 :   return aContent && (aContent->IsHTMLElement(nsGkAtoms::a) ||
   10850           0 :                       aContent->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
   10851           0 :                                             nsGkAtoms::simple, eCaseMatters));
   10852             : }
   10853             : 
   10854           0 : static bool ShouldShowFocusRingIfFocusedByMouse(nsIContent* aNode)
   10855             : {
   10856           0 :   if (!aNode) {
   10857           0 :     return true;
   10858             :   }
   10859           0 :   return !IsLink(aNode) &&
   10860           0 :          !aNode->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio);
   10861             : }
   10862             : 
   10863             : void
   10864           4 : nsGlobalWindow::SetFocusedNode(nsIContent* aNode,
   10865             :                                uint32_t aFocusMethod,
   10866             :                                bool aNeedsFocus)
   10867             : {
   10868           4 :   FORWARD_TO_INNER_VOID(SetFocusedNode, (aNode, aFocusMethod, aNeedsFocus));
   10869             : 
   10870           2 :   if (aNode && aNode->GetComposedDoc() != mDoc) {
   10871           0 :     NS_WARNING("Trying to set focus to a node from a wrong document");
   10872           0 :     return;
   10873             :   }
   10874             : 
   10875           2 :   if (mCleanedUp) {
   10876           0 :     NS_ASSERTION(!aNode, "Trying to focus cleaned up window!");
   10877           0 :     aNode = nullptr;
   10878           0 :     aNeedsFocus = false;
   10879             :   }
   10880           2 :   if (mFocusedNode != aNode) {
   10881           1 :     UpdateCanvasFocus(false, aNode);
   10882           1 :     mFocusedNode = aNode;
   10883           1 :     mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
   10884           1 :     mShowFocusRingForContent = false;
   10885             :   }
   10886             : 
   10887           2 :   if (mFocusedNode) {
   10888             :     // if a node was focused by a keypress, turn on focus rings for the
   10889             :     // window.
   10890           2 :     if (mFocusMethod & nsIFocusManager::FLAG_BYKEY) {
   10891           0 :       mFocusByKeyOccurred = true;
   10892           2 :     } else if (
   10893             :       // otherwise, we set mShowFocusRingForContent, as we don't want this to
   10894             :       // be permanent for the window. On Windows, focus rings are only shown
   10895             :       // when the FLAG_SHOWRING flag is used. On other platforms, focus rings
   10896             :       // are only visible on some elements.
   10897             : #ifndef XP_WIN
   10898           2 :       !(mFocusMethod & nsIFocusManager::FLAG_BYMOUSE) ||
   10899           2 :       ShouldShowFocusRingIfFocusedByMouse(aNode) ||
   10900             : #endif
   10901           0 :       aFocusMethod & nsIFocusManager::FLAG_SHOWRING) {
   10902           2 :         mShowFocusRingForContent = true;
   10903             :     }
   10904             :   }
   10905             : 
   10906           2 :   if (aNeedsFocus)
   10907           0 :     mNeedsFocus = aNeedsFocus;
   10908             : }
   10909             : 
   10910             : uint32_t
   10911           6 : nsGlobalWindow::GetFocusMethod()
   10912             : {
   10913           6 :   FORWARD_TO_INNER(GetFocusMethod, (), 0);
   10914             : 
   10915           3 :   return mFocusMethod;
   10916             : }
   10917             : 
   10918             : bool
   10919           2 : nsGlobalWindow::ShouldShowFocusRing()
   10920             : {
   10921           2 :   FORWARD_TO_INNER(ShouldShowFocusRing, (), false);
   10922             : 
   10923           1 :   if (mShowFocusRingForContent || mFocusByKeyOccurred) {
   10924           1 :     return true;
   10925             :   }
   10926             : 
   10927           0 :   nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
   10928           0 :   return root ? root->ShowFocusRings() : false;
   10929             : }
   10930             : 
   10931             : void
   10932           0 : nsGlobalWindow::SetKeyboardIndicators(UIStateChangeType aShowAccelerators,
   10933             :                                       UIStateChangeType aShowFocusRings)
   10934             : {
   10935           0 :   MOZ_ASSERT(IsOuterWindow());
   10936             : 
   10937           0 :   nsPIDOMWindowOuter* piWin = GetPrivateRoot();
   10938           0 :   if (!piWin) {
   10939           0 :     return;
   10940             :   }
   10941             : 
   10942           0 :   MOZ_ASSERT(piWin == AsOuter());
   10943             : 
   10944           0 :   bool oldShouldShowFocusRing = ShouldShowFocusRing();
   10945             : 
   10946             :   // only change the flags that have been modified
   10947           0 :   nsCOMPtr<nsPIWindowRoot> windowRoot = do_QueryInterface(mChromeEventHandler);
   10948           0 :   if (!windowRoot) {
   10949           0 :     return;
   10950             :   }
   10951             : 
   10952           0 :   if (aShowAccelerators != UIStateChangeType_NoChange) {
   10953           0 :     windowRoot->SetShowAccelerators(aShowAccelerators == UIStateChangeType_Set);
   10954             :   }
   10955           0 :   if (aShowFocusRings != UIStateChangeType_NoChange) {
   10956           0 :     windowRoot->SetShowFocusRings(aShowFocusRings == UIStateChangeType_Set);
   10957             :   }
   10958             : 
   10959           0 :   nsContentUtils::SetKeyboardIndicatorsOnRemoteChildren(GetOuterWindow(),
   10960             :                                                         aShowAccelerators,
   10961           0 :                                                         aShowFocusRings);
   10962             : 
   10963           0 :   bool newShouldShowFocusRing = ShouldShowFocusRing();
   10964           0 :   if (mHasFocus && mFocusedNode &&
   10965           0 :       oldShouldShowFocusRing != newShouldShowFocusRing &&
   10966           0 :       mFocusedNode->IsElement()) {
   10967             :     // Update mFocusedNode's state.
   10968           0 :     if (newShouldShowFocusRing) {
   10969           0 :       mFocusedNode->AsElement()->AddStates(NS_EVENT_STATE_FOCUSRING);
   10970             :     } else {
   10971           0 :       mFocusedNode->AsElement()->RemoveStates(NS_EVENT_STATE_FOCUSRING);
   10972             :     }
   10973             :   }
   10974             : }
   10975             : 
   10976             : bool
   10977           6 : nsGlobalWindow::TakeFocus(bool aFocus, uint32_t aFocusMethod)
   10978             : {
   10979           6 :   FORWARD_TO_INNER(TakeFocus, (aFocus, aFocusMethod), false);
   10980             : 
   10981           3 :   if (mCleanedUp) {
   10982           0 :     return false;
   10983             :   }
   10984             : 
   10985           3 :   if (aFocus)
   10986           3 :     mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
   10987             : 
   10988           3 :   if (mHasFocus != aFocus) {
   10989           3 :     mHasFocus = aFocus;
   10990           3 :     UpdateCanvasFocus(true, mFocusedNode);
   10991             :   }
   10992             : 
   10993             :   // if mNeedsFocus is true, then the document has not yet received a
   10994             :   // document-level focus event. If there is a root content node, then return
   10995             :   // true to tell the calling focus manager that a focus event is expected. If
   10996             :   // there is no root content node, the document hasn't loaded enough yet, or
   10997             :   // there isn't one and there is no point in firing a focus event.
   10998           3 :   if (aFocus && mNeedsFocus && mDoc && mDoc->GetRootElement() != nullptr) {
   10999           1 :     mNeedsFocus = false;
   11000           1 :     return true;
   11001             :   }
   11002             : 
   11003           2 :   mNeedsFocus = false;
   11004           2 :   return false;
   11005             : }
   11006             : 
   11007             : void
   11008           6 : nsGlobalWindow::SetReadyForFocus()
   11009             : {
   11010           6 :   FORWARD_TO_INNER_VOID(SetReadyForFocus, ());
   11011             : 
   11012           3 :   bool oldNeedsFocus = mNeedsFocus;
   11013           3 :   mNeedsFocus = false;
   11014             : 
   11015           3 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   11016           3 :   if (fm) {
   11017           3 :     fm->WindowShown(GetOuterWindow(), oldNeedsFocus);
   11018             :   }
   11019             : }
   11020             : 
   11021             : void
   11022           8 : nsGlobalWindow::PageHidden()
   11023             : {
   11024           8 :   FORWARD_TO_INNER_VOID(PageHidden, ());
   11025             : 
   11026             :   // the window is being hidden, so tell the focus manager that the frame is
   11027             :   // no longer valid. Use the persisted field to determine if the document
   11028             :   // is being destroyed.
   11029             : 
   11030           4 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   11031           4 :   if (fm) {
   11032           4 :     fm->WindowHidden(GetOuterWindow());
   11033             :   }
   11034             : 
   11035           4 :   mNeedsFocus = true;
   11036             : }
   11037             : 
   11038           0 : class HashchangeCallback : public Runnable
   11039             : {
   11040             : public:
   11041           0 :   HashchangeCallback(const nsAString& aOldURL,
   11042             :                      const nsAString& aNewURL,
   11043             :                      nsGlobalWindow* aWindow)
   11044           0 :     : mozilla::Runnable("HashchangeCallback")
   11045           0 :     , mWindow(aWindow)
   11046             :   {
   11047           0 :     MOZ_ASSERT(mWindow);
   11048           0 :     MOZ_ASSERT(mWindow->IsInnerWindow());
   11049           0 :     mOldURL.Assign(aOldURL);
   11050           0 :     mNewURL.Assign(aNewURL);
   11051           0 :   }
   11052             : 
   11053           0 :   NS_IMETHOD Run() override
   11054             :   {
   11055           0 :     NS_PRECONDITION(NS_IsMainThread(), "Should be called on the main thread.");
   11056           0 :     return mWindow->FireHashchange(mOldURL, mNewURL);
   11057             :   }
   11058             : 
   11059             : private:
   11060             :   nsString mOldURL;
   11061             :   nsString mNewURL;
   11062             :   RefPtr<nsGlobalWindow> mWindow;
   11063             : };
   11064             : 
   11065             : nsresult
   11066           0 : nsGlobalWindow::DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI)
   11067             : {
   11068           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   11069             : 
   11070             :   // Make sure that aOldURI and aNewURI are identical up to the '#', and that
   11071             :   // their hashes are different.
   11072           0 :   bool equal = false;
   11073           0 :   NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->EqualsExceptRef(aNewURI, &equal)) && equal);
   11074           0 :   nsAutoCString oldHash, newHash;
   11075             :   bool oldHasHash, newHasHash;
   11076           0 :   NS_ENSURE_STATE(NS_SUCCEEDED(aOldURI->GetRef(oldHash)) &&
   11077             :                   NS_SUCCEEDED(aNewURI->GetRef(newHash)) &&
   11078             :                   NS_SUCCEEDED(aOldURI->GetHasRef(&oldHasHash)) &&
   11079             :                   NS_SUCCEEDED(aNewURI->GetHasRef(&newHasHash)) &&
   11080             :                   (oldHasHash != newHasHash || !oldHash.Equals(newHash)));
   11081             : 
   11082           0 :   nsAutoCString oldSpec, newSpec;
   11083           0 :   nsresult rv = aOldURI->GetSpec(oldSpec);
   11084           0 :   NS_ENSURE_SUCCESS(rv, rv);
   11085           0 :   rv = aNewURI->GetSpec(newSpec);
   11086           0 :   NS_ENSURE_SUCCESS(rv, rv);
   11087             : 
   11088           0 :   NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
   11089           0 :   NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
   11090             : 
   11091             :   nsCOMPtr<nsIRunnable> callback =
   11092           0 :     new HashchangeCallback(oldWideSpec, newWideSpec, this);
   11093           0 :   return Dispatch("HashchangeCallback", TaskCategory::Other, callback.forget());
   11094             : }
   11095             : 
   11096             : nsresult
   11097           0 : nsGlobalWindow::FireHashchange(const nsAString &aOldURL,
   11098             :                                const nsAString &aNewURL)
   11099             : {
   11100           0 :   MOZ_ASSERT(IsInnerWindow());
   11101             : 
   11102             :   // Don't do anything if the window is frozen.
   11103           0 :   if (IsFrozen()) {
   11104           0 :     return NS_OK;
   11105             :   }
   11106             : 
   11107             :   // Get a presentation shell for use in creating the hashchange event.
   11108           0 :   NS_ENSURE_STATE(AsInner()->IsCurrentInnerWindow());
   11109             : 
   11110           0 :   nsIPresShell *shell = mDoc->GetShell();
   11111           0 :   RefPtr<nsPresContext> presContext;
   11112           0 :   if (shell) {
   11113           0 :     presContext = shell->GetPresContext();
   11114             :   }
   11115             : 
   11116           0 :   HashChangeEventInit init;
   11117           0 :   init.mBubbles = true;
   11118           0 :   init.mCancelable = false;
   11119           0 :   init.mNewURL = aNewURL;
   11120           0 :   init.mOldURL = aOldURL;
   11121             : 
   11122             :   RefPtr<HashChangeEvent> event =
   11123           0 :     HashChangeEvent::Constructor(this, NS_LITERAL_STRING("hashchange"),
   11124           0 :                                  init);
   11125             : 
   11126           0 :   event->SetTrusted(true);
   11127             : 
   11128             :   bool dummy;
   11129           0 :   return DispatchEvent(event, &dummy);
   11130             : }
   11131             : 
   11132             : nsresult
   11133           0 : nsGlobalWindow::DispatchSyncPopState()
   11134             : {
   11135           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   11136           0 :   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
   11137             :                "Must be safe to run script here.");
   11138             : 
   11139           0 :   nsresult rv = NS_OK;
   11140             : 
   11141             :   // Bail if the window is frozen.
   11142           0 :   if (IsFrozen()) {
   11143           0 :     return NS_OK;
   11144             :   }
   11145             : 
   11146             :   // Get the document's pending state object -- it contains the data we're
   11147             :   // going to send along with the popstate event.  The object is serialized
   11148             :   // using structured clone.
   11149           0 :   nsCOMPtr<nsIVariant> stateObj;
   11150           0 :   rv = mDoc->GetStateObject(getter_AddRefs(stateObj));
   11151           0 :   NS_ENSURE_SUCCESS(rv, rv);
   11152             : 
   11153             :   // Obtain a presentation shell for use in creating a popstate event.
   11154           0 :   nsIPresShell *shell = mDoc->GetShell();
   11155           0 :   RefPtr<nsPresContext> presContext;
   11156           0 :   if (shell) {
   11157           0 :     presContext = shell->GetPresContext();
   11158             :   }
   11159             : 
   11160           0 :   bool result = true;
   11161           0 :   AutoJSAPI jsapi;
   11162           0 :   result = jsapi.Init(AsInner());
   11163           0 :   NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
   11164             : 
   11165           0 :   JSContext* cx = jsapi.cx();
   11166           0 :   JS::Rooted<JS::Value> stateJSValue(cx, JS::NullValue());
   11167           0 :   result = stateObj ? VariantToJsval(cx, stateObj, &stateJSValue) : true;
   11168           0 :   NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
   11169             : 
   11170           0 :   RootedDictionary<PopStateEventInit> init(cx);
   11171           0 :   init.mBubbles = true;
   11172           0 :   init.mCancelable = false;
   11173           0 :   init.mState = stateJSValue;
   11174             : 
   11175             :   RefPtr<PopStateEvent> event =
   11176           0 :     PopStateEvent::Constructor(this, NS_LITERAL_STRING("popstate"),
   11177           0 :                                init);
   11178           0 :   event->SetTrusted(true);
   11179           0 :   event->SetTarget(this);
   11180             : 
   11181             :   bool dummy; // default action
   11182           0 :   return DispatchEvent(event, &dummy);
   11183             : }
   11184             : 
   11185             : // Find an nsICanvasFrame under aFrame.  Only search the principal
   11186             : // child lists.  aFrame must be non-null.
   11187           0 : static nsCanvasFrame* FindCanvasFrame(nsIFrame* aFrame)
   11188             : {
   11189           0 :     nsCanvasFrame* canvasFrame = do_QueryFrame(aFrame);
   11190           0 :     if (canvasFrame) {
   11191           0 :         return canvasFrame;
   11192             :     }
   11193             : 
   11194           0 :     for (nsIFrame* kid : aFrame->PrincipalChildList()) {
   11195           0 :         canvasFrame = FindCanvasFrame(kid);
   11196           0 :         if (canvasFrame) {
   11197           0 :             return canvasFrame;
   11198             :         }
   11199             :     }
   11200             : 
   11201           0 :     return nullptr;
   11202             : }
   11203             : 
   11204             : //-------------------------------------------------------
   11205             : // Tells the HTMLFrame/CanvasFrame that is now has focus
   11206             : void
   11207           4 : nsGlobalWindow::UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent)
   11208             : {
   11209           4 :   MOZ_ASSERT(IsInnerWindow());
   11210             : 
   11211             :   // this is called from the inner window so use GetDocShell
   11212           4 :   nsIDocShell* docShell = GetDocShell();
   11213           4 :   if (!docShell)
   11214           0 :     return;
   11215             : 
   11216             :   bool editable;
   11217           4 :   docShell->GetEditable(&editable);
   11218           4 :   if (editable)
   11219           0 :     return;
   11220             : 
   11221           8 :   nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
   11222           4 :   if (!presShell || !mDoc)
   11223           0 :     return;
   11224             : 
   11225           4 :   Element *rootElement = mDoc->GetRootElement();
   11226           4 :   if (rootElement) {
   11227           7 :       if ((mHasFocus || aFocusChanged) &&
   11228           6 :           (mFocusedNode == rootElement || aNewContent == rootElement)) {
   11229           0 :           nsIFrame* frame = rootElement->GetPrimaryFrame();
   11230           0 :           if (frame) {
   11231           0 :               frame = frame->GetParent();
   11232           0 :               nsCanvasFrame* canvasFrame = do_QueryFrame(frame);
   11233           0 :               if (canvasFrame) {
   11234           0 :                   canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
   11235             :               }
   11236             :           }
   11237             :       }
   11238             :   } else {
   11239             :       // Look for the frame the hard way
   11240           0 :       nsIFrame* frame = presShell->GetRootFrame();
   11241           0 :       if (frame) {
   11242           0 :           nsCanvasFrame* canvasFrame = FindCanvasFrame(frame);
   11243           0 :           if (canvasFrame) {
   11244           0 :               canvasFrame->SetHasFocus(false);
   11245             :           }
   11246             :       }
   11247             :   }
   11248             : }
   11249             : 
   11250             : already_AddRefed<nsICSSDeclaration>
   11251           4 : nsGlobalWindow::GetComputedStyle(Element& aElt, const nsAString& aPseudoElt,
   11252             :                                  ErrorResult& aError)
   11253             : {
   11254           4 :   MOZ_ASSERT(IsInnerWindow());
   11255           4 :   return GetComputedStyleHelper(aElt, aPseudoElt, false, aError);
   11256             : }
   11257             : 
   11258             : already_AddRefed<nsICSSDeclaration>
   11259           0 : nsGlobalWindow::GetDefaultComputedStyle(Element& aElt,
   11260             :                                         const nsAString& aPseudoElt,
   11261             :                                         ErrorResult& aError)
   11262             : {
   11263           0 :   MOZ_ASSERT(IsInnerWindow());
   11264           0 :   return GetComputedStyleHelper(aElt, aPseudoElt, true, aError);
   11265             : }
   11266             : 
   11267             : nsresult
   11268           0 : nsGlobalWindow::GetComputedStyleHelper(nsIDOMElement* aElt,
   11269             :                                        const nsAString& aPseudoElt,
   11270             :                                        bool aDefaultStylesOnly,
   11271             :                                        nsIDOMCSSStyleDeclaration** aReturn)
   11272             : {
   11273           0 :   MOZ_ASSERT(IsInnerWindow());
   11274             : 
   11275           0 :   NS_ENSURE_ARG_POINTER(aReturn);
   11276           0 :   *aReturn = nullptr;
   11277             : 
   11278           0 :   nsCOMPtr<dom::Element> element = do_QueryInterface(aElt);
   11279           0 :   if (!element) {
   11280           0 :     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   11281             :   }
   11282             : 
   11283           0 :   ErrorResult rv;
   11284             :   nsCOMPtr<nsIDOMCSSStyleDeclaration> declaration =
   11285           0 :     GetComputedStyleHelper(*element, aPseudoElt, aDefaultStylesOnly, rv);
   11286           0 :   declaration.forget(aReturn);
   11287             : 
   11288           0 :   return rv.StealNSResult();
   11289             : }
   11290             : 
   11291             : already_AddRefed<nsICSSDeclaration>
   11292           4 : nsGlobalWindow::GetComputedStyleHelperOuter(Element& aElt,
   11293             :                                             const nsAString& aPseudoElt,
   11294             :                                             bool aDefaultStylesOnly)
   11295             : {
   11296           4 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   11297             : 
   11298           4 :   if (!mDocShell) {
   11299           0 :     return nullptr;
   11300             :   }
   11301             : 
   11302           8 :   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   11303             : 
   11304           4 :   if (!presShell) {
   11305             :     // Try flushing frames on our parent in case there's a pending
   11306             :     // style change that will create the presshell.
   11307           0 :     auto* parent = nsGlobalWindow::Cast(GetPrivateParent());
   11308           0 :     if (!parent) {
   11309           0 :       return nullptr;
   11310             :     }
   11311             : 
   11312           0 :     parent->FlushPendingNotifications(FlushType::Frames);
   11313             : 
   11314             :     // Might have killed mDocShell
   11315           0 :     if (!mDocShell) {
   11316           0 :       return nullptr;
   11317             :     }
   11318             : 
   11319           0 :     presShell = mDocShell->GetPresShell();
   11320           0 :     if (!presShell) {
   11321           0 :       return nullptr;
   11322             :     }
   11323             :   }
   11324             : 
   11325             :   RefPtr<nsComputedDOMStyle> compStyle =
   11326           8 :     NS_NewComputedDOMStyle(&aElt, aPseudoElt, presShell,
   11327             :                            aDefaultStylesOnly ? nsComputedDOMStyle::eDefaultOnly :
   11328           8 :                                                 nsComputedDOMStyle::eAll);
   11329             : 
   11330           4 :   return compStyle.forget();
   11331             : }
   11332             : 
   11333             : already_AddRefed<nsICSSDeclaration>
   11334           4 : nsGlobalWindow::GetComputedStyleHelper(Element& aElt,
   11335             :                                        const nsAString& aPseudoElt,
   11336             :                                        bool aDefaultStylesOnly,
   11337             :                                        ErrorResult& aError)
   11338             : {
   11339           4 :   FORWARD_TO_OUTER_OR_THROW(GetComputedStyleHelperOuter,
   11340             :                             (aElt, aPseudoElt, aDefaultStylesOnly),
   11341             :                             aError, nullptr);
   11342             : }
   11343             : 
   11344             : Storage*
   11345           0 : nsGlobalWindow::GetSessionStorage(ErrorResult& aError)
   11346             : {
   11347           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   11348             : 
   11349           0 :   nsIPrincipal *principal = GetPrincipal();
   11350           0 :   nsIDocShell* docShell = GetDocShell();
   11351             : 
   11352           0 :   if (!principal || !docShell || !Preferences::GetBool(kStorageEnabled)) {
   11353           0 :     return nullptr;
   11354             :   }
   11355             : 
   11356           0 :   if (mSessionStorage) {
   11357           0 :     MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
   11358             :             ("nsGlobalWindow %p has %p sessionStorage", this, mSessionStorage.get()));
   11359           0 :     bool canAccess = principal->Subsumes(mSessionStorage->Principal());
   11360           0 :     NS_ASSERTION(canAccess,
   11361             :                  "This window owned sessionStorage "
   11362             :                  "that could not be accessed!");
   11363           0 :     if (!canAccess) {
   11364           0 :       mSessionStorage = nullptr;
   11365             :     }
   11366             :   }
   11367             : 
   11368           0 :   if (!mSessionStorage) {
   11369           0 :     nsString documentURI;
   11370           0 :     if (mDoc) {
   11371           0 :       aError = mDoc->GetDocumentURI(documentURI);
   11372           0 :       if (NS_WARN_IF(aError.Failed())) {
   11373           0 :         return nullptr;
   11374             :       }
   11375             :     }
   11376             : 
   11377             :     // If the document has the sandboxed origin flag set
   11378             :     // don't allow access to sessionStorage.
   11379           0 :     if (!mDoc) {
   11380           0 :       aError.Throw(NS_ERROR_FAILURE);
   11381           0 :       return nullptr;
   11382             :     }
   11383             : 
   11384           0 :     if (mDoc->GetSandboxFlags() & SANDBOXED_ORIGIN) {
   11385           0 :       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
   11386           0 :       return nullptr;
   11387             :     }
   11388             : 
   11389             :     nsresult rv;
   11390             : 
   11391           0 :     nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(docShell, &rv);
   11392           0 :     if (NS_FAILED(rv)) {
   11393           0 :       aError.Throw(rv);
   11394           0 :       return nullptr;
   11395             :     }
   11396             : 
   11397           0 :     nsCOMPtr<nsIDOMStorage> storage;
   11398           0 :     aError = storageManager->CreateStorage(AsInner(), principal, documentURI,
   11399           0 :                                            IsPrivateBrowsing(),
   11400           0 :                                            getter_AddRefs(storage));
   11401           0 :     if (aError.Failed()) {
   11402           0 :       return nullptr;
   11403             :     }
   11404             : 
   11405           0 :     mSessionStorage = static_cast<Storage*>(storage.get());
   11406           0 :     MOZ_ASSERT(mSessionStorage);
   11407             : 
   11408           0 :     MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
   11409             :             ("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage.get()));
   11410             : 
   11411           0 :     if (!mSessionStorage) {
   11412           0 :       aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   11413           0 :       return nullptr;
   11414             :     }
   11415             :   }
   11416             : 
   11417           0 :   MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
   11418             :           ("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage.get()));
   11419             : 
   11420           0 :   return mSessionStorage;
   11421             : }
   11422             : 
   11423             : Storage*
   11424           0 : nsGlobalWindow::GetLocalStorage(ErrorResult& aError)
   11425             : {
   11426           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   11427             : 
   11428           0 :   if (!Preferences::GetBool(kStorageEnabled)) {
   11429           0 :     return nullptr;
   11430             :   }
   11431             : 
   11432           0 :   if (!mLocalStorage) {
   11433           0 :     if (nsContentUtils::StorageAllowedForWindow(AsInner()) ==
   11434             :           nsContentUtils::StorageAccess::eDeny) {
   11435           0 :       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
   11436           0 :       return nullptr;
   11437             :     }
   11438             : 
   11439           0 :     nsIPrincipal *principal = GetPrincipal();
   11440           0 :     if (!principal) {
   11441           0 :       return nullptr;
   11442             :     }
   11443             : 
   11444             :     nsresult rv;
   11445             :     nsCOMPtr<nsIDOMStorageManager> storageManager =
   11446           0 :       do_GetService("@mozilla.org/dom/localStorage-manager;1", &rv);
   11447           0 :     if (NS_FAILED(rv)) {
   11448           0 :       aError.Throw(rv);
   11449           0 :       return nullptr;
   11450             :     }
   11451             : 
   11452           0 :     nsString documentURI;
   11453           0 :     if (mDoc) {
   11454           0 :       aError = mDoc->GetDocumentURI(documentURI);
   11455           0 :       if (NS_WARN_IF(aError.Failed())) {
   11456           0 :         return nullptr;
   11457             :       }
   11458             :     }
   11459             : 
   11460           0 :     nsCOMPtr<nsIDOMStorage> storage;
   11461           0 :     aError = storageManager->CreateStorage(AsInner(), principal, documentURI,
   11462           0 :                                            IsPrivateBrowsing(),
   11463           0 :                                            getter_AddRefs(storage));
   11464           0 :     if (aError.Failed()) {
   11465           0 :       return nullptr;
   11466             :     }
   11467             : 
   11468           0 :     mLocalStorage = static_cast<Storage*>(storage.get());
   11469           0 :     MOZ_ASSERT(mLocalStorage);
   11470             :   }
   11471             : 
   11472           0 :   return mLocalStorage;
   11473             : }
   11474             : 
   11475             : IDBFactory*
   11476           0 : nsGlobalWindow::GetIndexedDB(ErrorResult& aError)
   11477             : {
   11478           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   11479           0 :   if (!mIndexedDB) {
   11480             :     // This may keep mIndexedDB null without setting an error.
   11481           0 :     aError = IDBFactory::CreateForWindow(AsInner(),
   11482           0 :                                          getter_AddRefs(mIndexedDB));
   11483             :   }
   11484             : 
   11485           0 :   return mIndexedDB;
   11486             : }
   11487             : 
   11488             : //*****************************************************************************
   11489             : // nsGlobalWindow::nsIInterfaceRequestor
   11490             : //*****************************************************************************
   11491             : 
   11492             : NS_IMETHODIMP
   11493          53 : nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink)
   11494             : {
   11495          53 :   NS_ENSURE_ARG_POINTER(aSink);
   11496          53 :   *aSink = nullptr;
   11497             : 
   11498          53 :   if (aIID.Equals(NS_GET_IID(nsIDocCharset))) {
   11499           0 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   11500           0 :     NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED);
   11501             : 
   11502           0 :     NS_WARNING("Using deprecated nsIDocCharset: use nsIDocShell.GetCharset() instead ");
   11503           0 :     nsCOMPtr<nsIDocCharset> docCharset(do_QueryInterface(outer->mDocShell));
   11504           0 :     docCharset.forget(aSink);
   11505             :   }
   11506          53 :   else if (aIID.Equals(NS_GET_IID(nsIWebNavigation))) {
   11507          37 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   11508          37 :     NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED);
   11509             : 
   11510          74 :     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(outer->mDocShell));
   11511          37 :     webNav.forget(aSink);
   11512             :   }
   11513          16 :   else if (aIID.Equals(NS_GET_IID(nsIDocShell))) {
   11514           1 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   11515           1 :     NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED);
   11516             : 
   11517           2 :     nsCOMPtr<nsIDocShell> docShell = outer->mDocShell;
   11518           1 :     docShell.forget(aSink);
   11519             :   }
   11520             : #ifdef NS_PRINTING
   11521          15 :   else if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) {
   11522           0 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   11523           0 :     NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED);
   11524             : 
   11525           0 :     if (outer->mDocShell) {
   11526           0 :       nsCOMPtr<nsIContentViewer> viewer;
   11527           0 :       outer->mDocShell->GetContentViewer(getter_AddRefs(viewer));
   11528           0 :       if (viewer) {
   11529           0 :         nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint(do_QueryInterface(viewer));
   11530           0 :         webBrowserPrint.forget(aSink);
   11531             :       }
   11532             :     }
   11533             :   }
   11534             : #endif
   11535          15 :   else if (aIID.Equals(NS_GET_IID(nsIDOMWindowUtils))) {
   11536          15 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   11537          15 :     NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED);
   11538             : 
   11539          15 :     if (!mWindowUtils) {
   11540           4 :       mWindowUtils = new nsDOMWindowUtils(outer);
   11541             :     }
   11542             : 
   11543          15 :     *aSink = mWindowUtils;
   11544          15 :     NS_ADDREF(((nsISupports *) *aSink));
   11545             :   }
   11546           0 :   else if (aIID.Equals(NS_GET_IID(nsILoadContext))) {
   11547           0 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   11548           0 :     NS_ENSURE_TRUE(outer, NS_ERROR_NOT_INITIALIZED);
   11549             : 
   11550           0 :     nsCOMPtr<nsILoadContext> loadContext(do_QueryInterface(outer->mDocShell));
   11551           0 :     loadContext.forget(aSink);
   11552             :   }
   11553             :   else {
   11554           0 :     return QueryInterface(aIID, aSink);
   11555             :   }
   11556             : 
   11557          53 :   return *aSink ? NS_OK : NS_ERROR_NO_INTERFACE;
   11558             : }
   11559             : 
   11560             : void
   11561          39 : nsGlobalWindow::GetInterface(JSContext* aCx, nsIJSID* aIID,
   11562             :                              JS::MutableHandle<JS::Value> aRetval,
   11563             :                              ErrorResult& aError)
   11564             : {
   11565          39 :   MOZ_ASSERT(IsInnerWindow());
   11566          39 :   dom::GetInterface(aCx, this, aIID, aRetval, aError);
   11567          39 : }
   11568             : 
   11569             : already_AddRefed<CacheStorage>
   11570           0 : nsGlobalWindow::GetCaches(ErrorResult& aRv)
   11571             : {
   11572           0 :   MOZ_ASSERT(IsInnerWindow());
   11573             : 
   11574           0 :   if (!mCacheStorage) {
   11575             :     bool forceTrustedOrigin =
   11576           0 :       GetOuterWindow()->GetServiceWorkersTestingEnabled();
   11577             : 
   11578             :     nsContentUtils::StorageAccess access =
   11579           0 :       nsContentUtils::StorageAllowedForWindow(AsInner());
   11580             : 
   11581             :     // We don't block the cache API when being told to only allow storage for the
   11582             :     // current session.
   11583           0 :     bool storageBlocked = access <= nsContentUtils::StorageAccess::ePrivateBrowsing;
   11584             : 
   11585           0 :     mCacheStorage = CacheStorage::CreateOnMainThread(cache::DEFAULT_NAMESPACE,
   11586           0 :                                                      this, GetPrincipal(),
   11587             :                                                      storageBlocked,
   11588           0 :                                                      forceTrustedOrigin, aRv);
   11589             :   }
   11590             : 
   11591           0 :   RefPtr<CacheStorage> ref = mCacheStorage;
   11592           0 :   return ref.forget();
   11593             : }
   11594             : 
   11595             : already_AddRefed<ServiceWorkerRegistration>
   11596           0 : nsPIDOMWindowInner::GetServiceWorkerRegistration(const nsAString& aScope)
   11597             : {
   11598           0 :   RefPtr<ServiceWorkerRegistration> registration;
   11599           0 :   if (!mServiceWorkerRegistrationTable.Get(aScope,
   11600           0 :                                            getter_AddRefs(registration))) {
   11601             :     registration =
   11602           0 :       ServiceWorkerRegistration::CreateForMainThread(this, aScope);
   11603           0 :     mServiceWorkerRegistrationTable.Put(aScope, registration);
   11604             :   }
   11605           0 :   return registration.forget();
   11606             : }
   11607             : 
   11608             : void
   11609           0 : nsPIDOMWindowInner::InvalidateServiceWorkerRegistration(const nsAString& aScope)
   11610             : {
   11611           0 :   mServiceWorkerRegistrationTable.Remove(aScope);
   11612           0 : }
   11613             : 
   11614             : void
   11615           0 : nsGlobalWindow::FireOfflineStatusEventIfChanged()
   11616             : {
   11617           0 :   if (!AsInner()->IsCurrentInnerWindow())
   11618           0 :     return;
   11619             : 
   11620             :   // Don't fire an event if the status hasn't changed
   11621           0 :   if (mWasOffline == NS_IsOffline()) {
   11622           0 :     return;
   11623             :   }
   11624             : 
   11625           0 :   mWasOffline = !mWasOffline;
   11626             : 
   11627           0 :   nsAutoString name;
   11628           0 :   if (mWasOffline) {
   11629           0 :     name.AssignLiteral("offline");
   11630             :   } else {
   11631           0 :     name.AssignLiteral("online");
   11632             :   }
   11633             :   // The event is fired at the body element, or if there is no body element,
   11634             :   // at the document.
   11635           0 :   nsCOMPtr<EventTarget> eventTarget = mDoc.get();
   11636           0 :   nsHTMLDocument* htmlDoc = mDoc->AsHTMLDocument();
   11637           0 :   if (htmlDoc) {
   11638           0 :     Element* body = htmlDoc->GetBody();
   11639           0 :     if (body) {
   11640           0 :       eventTarget = body;
   11641             :     }
   11642             :   } else {
   11643           0 :     Element* documentElement = mDoc->GetDocumentElement();
   11644           0 :     if (documentElement) {
   11645           0 :       eventTarget = documentElement;
   11646             :     }
   11647             :   }
   11648           0 :   nsContentUtils::DispatchTrustedEvent(mDoc, eventTarget, name, true, false);
   11649             : }
   11650             : 
   11651           0 : class NotifyIdleObserverRunnable : public Runnable
   11652             : {
   11653             : public:
   11654           0 :   NotifyIdleObserverRunnable(nsIIdleObserver* aIdleObserver,
   11655             :                              uint32_t aTimeInS,
   11656             :                              bool aCallOnidle,
   11657             :                              nsGlobalWindow* aIdleWindow)
   11658           0 :     : mozilla::Runnable("NotifyIdleObserverRunnable")
   11659             :     , mIdleObserver(aIdleObserver)
   11660             :     , mTimeInS(aTimeInS)
   11661             :     , mIdleWindow(aIdleWindow)
   11662           0 :     , mCallOnidle(aCallOnidle)
   11663           0 :   { }
   11664             : 
   11665           0 :   NS_IMETHOD Run() override
   11666             :   {
   11667           0 :     if (mIdleWindow->ContainsIdleObserver(mIdleObserver, mTimeInS)) {
   11668           0 :       return mCallOnidle ? mIdleObserver->Onidle() : mIdleObserver->Onactive();
   11669             :     }
   11670           0 :     return NS_OK;
   11671             :   }
   11672             : 
   11673             : private:
   11674             :   nsCOMPtr<nsIIdleObserver> mIdleObserver;
   11675             :   uint32_t mTimeInS;
   11676             :   RefPtr<nsGlobalWindow> mIdleWindow;
   11677             : 
   11678             :   // If false then call on active
   11679             :   bool mCallOnidle;
   11680             : };
   11681             : 
   11682             : void
   11683           0 : nsGlobalWindow::NotifyIdleObserver(IdleObserverHolder* aIdleObserverHolder,
   11684             :                                    bool aCallOnidle)
   11685             : {
   11686           0 :   MOZ_ASSERT(aIdleObserverHolder);
   11687           0 :   aIdleObserverHolder->mPrevNotificationIdle = aCallOnidle;
   11688             : 
   11689             :   nsCOMPtr<nsIRunnable> caller =
   11690             :     new NotifyIdleObserverRunnable(aIdleObserverHolder->mIdleObserver,
   11691             :                                    aIdleObserverHolder->mTimeInS,
   11692           0 :                                    aCallOnidle, this);
   11693           0 :   if (NS_FAILED(Dispatch("NotifyIdleObserverRunnable", TaskCategory::Other,
   11694             :                          caller.forget()))) {
   11695           0 :     NS_WARNING("Failed to dispatch thread for idle observer notification.");
   11696             :   }
   11697           0 : }
   11698             : 
   11699             : bool
   11700           0 : nsGlobalWindow::ContainsIdleObserver(nsIIdleObserver* aIdleObserver, uint32_t aTimeInS)
   11701             : {
   11702           0 :   MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
   11703           0 :   bool found = false;
   11704           0 :   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
   11705           0 :   while (iter.HasMore()) {
   11706           0 :     IdleObserverHolder& idleObserver = iter.GetNext();
   11707           0 :     if (idleObserver.mIdleObserver == aIdleObserver &&
   11708           0 :         idleObserver.mTimeInS == aTimeInS) {
   11709           0 :       found = true;
   11710           0 :       break;
   11711             :     }
   11712             :   }
   11713           0 :   return found;
   11714             : }
   11715             : 
   11716             : void
   11717           0 : IdleActiveTimerCallback(nsITimer* aTimer, void* aClosure)
   11718             : {
   11719           0 :   RefPtr<nsGlobalWindow> idleWindow = static_cast<nsGlobalWindow*>(aClosure);
   11720           0 :   MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
   11721           0 :   idleWindow->HandleIdleActiveEvent();
   11722           0 : }
   11723             : 
   11724             : void
   11725           0 : IdleObserverTimerCallback(nsITimer* aTimer, void* aClosure)
   11726             : {
   11727           0 :   RefPtr<nsGlobalWindow> idleWindow = static_cast<nsGlobalWindow*>(aClosure);
   11728           0 :   MOZ_ASSERT(idleWindow, "Idle window has not been instantiated.");
   11729           0 :   idleWindow->HandleIdleObserverCallback();
   11730           0 : }
   11731             : 
   11732             : void
   11733           0 : nsGlobalWindow::HandleIdleObserverCallback()
   11734             : {
   11735           0 :   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   11736           0 :   MOZ_ASSERT(static_cast<uint32_t>(mIdleCallbackIndex) < mIdleObservers.Length(),
   11737             :                                   "Idle callback index exceeds array bounds!");
   11738           0 :   IdleObserverHolder& idleObserver = mIdleObservers.ElementAt(mIdleCallbackIndex);
   11739           0 :   NotifyIdleObserver(&idleObserver, true);
   11740           0 :   mIdleCallbackIndex++;
   11741           0 :   if (NS_FAILED(ScheduleNextIdleObserverCallback())) {
   11742           0 :     NS_WARNING("Failed to set next idle observer callback.");
   11743             :   }
   11744           0 : }
   11745             : 
   11746             : nsresult
   11747           0 : nsGlobalWindow::ScheduleNextIdleObserverCallback()
   11748             : {
   11749           0 :   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   11750           0 :   MOZ_ASSERT(mIdleService, "No idle service!");
   11751             : 
   11752           0 :   if (mIdleCallbackIndex < 0 ||
   11753           0 :       static_cast<uint32_t>(mIdleCallbackIndex) >= mIdleObservers.Length()) {
   11754           0 :     return NS_OK;
   11755             :   }
   11756             : 
   11757             :   IdleObserverHolder& idleObserver =
   11758           0 :     mIdleObservers.ElementAt(mIdleCallbackIndex);
   11759             : 
   11760           0 :   uint32_t userIdleTimeMS = 0;
   11761           0 :   nsresult rv = mIdleService->GetIdleTime(&userIdleTimeMS);
   11762           0 :   NS_ENSURE_SUCCESS(rv, rv);
   11763             : 
   11764           0 :   uint32_t callbackTimeMS = 0;
   11765           0 :   if (idleObserver.mTimeInS * 1000 + mIdleFuzzFactor > userIdleTimeMS) {
   11766           0 :     callbackTimeMS = idleObserver.mTimeInS * 1000 - userIdleTimeMS + mIdleFuzzFactor;
   11767             :   }
   11768             : 
   11769           0 :   mIdleTimer->Cancel();
   11770           0 :   rv = mIdleTimer->InitWithNamedFuncCallback(
   11771             :     IdleObserverTimerCallback,
   11772             :     this,
   11773             :     callbackTimeMS,
   11774             :     nsITimer::TYPE_ONE_SHOT,
   11775           0 :     "nsGlobalWindow::ScheduleNextIdleObserverCallback");
   11776           0 :   NS_ENSURE_SUCCESS(rv, rv);
   11777             : 
   11778           0 :   return NS_OK;
   11779             : }
   11780             : 
   11781             : uint32_t
   11782           0 : nsGlobalWindow::GetFuzzTimeMS()
   11783             : {
   11784           0 :   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   11785             : 
   11786           0 :   if (sIdleObserversAPIFuzzTimeDisabled) {
   11787           0 :     return 0;
   11788             :   }
   11789             : 
   11790           0 :   uint32_t randNum = MAX_IDLE_FUZZ_TIME_MS;
   11791           0 :   size_t nbytes = PR_GetRandomNoise(&randNum, sizeof(randNum));
   11792           0 :   if (nbytes != sizeof(randNum)) {
   11793           0 :     NS_WARNING("PR_GetRandomNoise(...) Not implemented or no available noise!");
   11794           0 :     return MAX_IDLE_FUZZ_TIME_MS;
   11795             :   }
   11796             : 
   11797           0 :   if (randNum > MAX_IDLE_FUZZ_TIME_MS) {
   11798           0 :     randNum %= MAX_IDLE_FUZZ_TIME_MS;
   11799             :   }
   11800             : 
   11801           0 :   return randNum;
   11802             : }
   11803             : 
   11804             : nsresult
   11805           0 : nsGlobalWindow::ScheduleActiveTimerCallback()
   11806             : {
   11807           0 :   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   11808             : 
   11809           0 :   if (!mAddActiveEventFuzzTime) {
   11810           0 :     return HandleIdleActiveEvent();
   11811             :   }
   11812             : 
   11813           0 :   MOZ_ASSERT(mIdleTimer);
   11814           0 :   mIdleTimer->Cancel();
   11815             : 
   11816           0 :   uint32_t fuzzFactorInMS = GetFuzzTimeMS();
   11817           0 :   nsresult rv = mIdleTimer->InitWithNamedFuncCallback(
   11818             :     IdleActiveTimerCallback,
   11819             :     this,
   11820             :     fuzzFactorInMS,
   11821             :     nsITimer::TYPE_ONE_SHOT,
   11822           0 :     "nsGlobalWindow::ScheduleActiveTimerCallback");
   11823           0 :   NS_ENSURE_SUCCESS(rv, rv);
   11824           0 :   return NS_OK;
   11825             : }
   11826             : 
   11827             : nsresult
   11828           0 : nsGlobalWindow::HandleIdleActiveEvent()
   11829             : {
   11830           0 :   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   11831             : 
   11832           0 :   if (mCurrentlyIdle) {
   11833           0 :     mIdleCallbackIndex = 0;
   11834           0 :     mIdleFuzzFactor = GetFuzzTimeMS();
   11835           0 :     nsresult rv = ScheduleNextIdleObserverCallback();
   11836           0 :     NS_ENSURE_SUCCESS(rv, rv);
   11837           0 :     return NS_OK;
   11838             :   }
   11839             : 
   11840           0 :   mIdleCallbackIndex = -1;
   11841           0 :   MOZ_ASSERT(mIdleTimer);
   11842           0 :   mIdleTimer->Cancel();
   11843           0 :   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
   11844           0 :   while (iter.HasMore()) {
   11845           0 :     IdleObserverHolder& idleObserver = iter.GetNext();
   11846           0 :     if (idleObserver.mPrevNotificationIdle) {
   11847           0 :       NotifyIdleObserver(&idleObserver, false);
   11848             :     }
   11849             :   }
   11850             : 
   11851           0 :   return NS_OK;
   11852             : }
   11853             : 
   11854             : nsGlobalWindow::SlowScriptResponse
   11855           0 : nsGlobalWindow::ShowSlowScriptDialog()
   11856             : {
   11857           0 :   MOZ_ASSERT(IsInnerWindow());
   11858             : 
   11859             :   nsresult rv;
   11860           0 :   AutoJSContext cx;
   11861             : 
   11862           0 :   if (Preferences::GetBool("dom.always_stop_slow_scripts")) {
   11863           0 :     return KillSlowScript;
   11864             :   }
   11865             : 
   11866             :   // If it isn't safe to run script, then it isn't safe to bring up the prompt
   11867             :   // (since that spins the event loop). In that (rare) case, we just kill the
   11868             :   // script and report a warning.
   11869           0 :   if (!nsContentUtils::IsSafeToRunScript()) {
   11870           0 :     JS_ReportWarningASCII(cx, "A long running script was terminated");
   11871           0 :     return KillSlowScript;
   11872             :   }
   11873             : 
   11874             :   // If our document is not active, just kill the script: we've been unloaded
   11875           0 :   if (!AsInner()->HasActiveDocument()) {
   11876           0 :     return KillSlowScript;
   11877             :   }
   11878             : 
   11879             :   // Check if we should offer the option to debug
   11880           0 :   JS::AutoFilename filename;
   11881             :   unsigned lineno;
   11882             :   // Computing the line number can be very expensive (see bug 1330231 for
   11883             :   // example), and we don't use the line number anywhere except than in the
   11884             :   // parent process, so we avoid computing it elsewhere.  This gives us most of
   11885             :   // the wins we are interested in, since the source of the slowness here is
   11886             :   // minified scripts which is more common in Web content that is loaded in the
   11887             :   // content process.
   11888           0 :   unsigned* linenop = XRE_IsParentProcess() ? &lineno : nullptr;
   11889           0 :   bool hasFrame = JS::DescribeScriptedCaller(cx, &filename, linenop);
   11890             : 
   11891             :   // Record the slow script event if we haven't done so already for this inner window
   11892             :   // (which represents a particular page to the user).
   11893           0 :   if (!mHasHadSlowScript) {
   11894           0 :     Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_PAGE_COUNT, 1);
   11895             :   }
   11896           0 :   mHasHadSlowScript = true;
   11897             : 
   11898           0 :   if (XRE_IsContentProcess() &&
   11899           0 :       ProcessHangMonitor::Get()) {
   11900             :     ProcessHangMonitor::SlowScriptAction action;
   11901           0 :     RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
   11902           0 :     nsIDocShell* docShell = GetDocShell();
   11903           0 :     nsCOMPtr<nsITabChild> child = docShell ? docShell->GetTabChild() : nullptr;
   11904           0 :     action = monitor->NotifySlowScript(child,
   11905           0 :                                        filename.get());
   11906           0 :     if (action == ProcessHangMonitor::Terminate) {
   11907           0 :       return KillSlowScript;
   11908             :     }
   11909             : 
   11910           0 :     if (action == ProcessHangMonitor::StartDebugger) {
   11911             :       // Spin a nested event loop so that the debugger in the parent can fetch
   11912             :       // any information it needs. Once the debugger has started, return to the
   11913             :       // script.
   11914           0 :       RefPtr<nsGlobalWindow> outer = GetOuterWindowInternal();
   11915           0 :       outer->EnterModalState();
   11916           0 :       SpinEventLoopUntil([&]() { return monitor->IsDebuggerStartupComplete(); });
   11917           0 :       outer->LeaveModalState();
   11918           0 :       return ContinueSlowScript;
   11919             :     }
   11920             : 
   11921           0 :     return ContinueSlowScriptAndKeepNotifying;
   11922             :   }
   11923             : 
   11924             :   // Reached only on non-e10s - once per slow script dialog.
   11925             :   // On e10s - we probe once at ProcessHangsMonitor.jsm
   11926           0 :   Telemetry::Accumulate(Telemetry::SLOW_SCRIPT_NOTICE_COUNT, 1);
   11927             : 
   11928             :   // Get the nsIPrompt interface from the docshell
   11929           0 :   nsCOMPtr<nsIDocShell> ds = GetDocShell();
   11930           0 :   NS_ENSURE_TRUE(ds, KillSlowScript);
   11931           0 :   nsCOMPtr<nsIPrompt> prompt = do_GetInterface(ds);
   11932           0 :   NS_ENSURE_TRUE(prompt, KillSlowScript);
   11933             : 
   11934             :   // Prioritize the SlowScriptDebug interface over JSD1.
   11935           0 :   nsCOMPtr<nsISlowScriptDebugCallback> debugCallback;
   11936             : 
   11937           0 :   if (hasFrame) {
   11938           0 :     const char *debugCID = "@mozilla.org/dom/slow-script-debug;1";
   11939           0 :     nsCOMPtr<nsISlowScriptDebug> debugService = do_GetService(debugCID, &rv);
   11940           0 :     if (NS_SUCCEEDED(rv)) {
   11941           0 :       debugService->GetActivationHandler(getter_AddRefs(debugCallback));
   11942             :     }
   11943             :   }
   11944             : 
   11945           0 :   bool showDebugButton = !!debugCallback;
   11946             : 
   11947             :   // Get localizable strings
   11948           0 :   nsXPIDLString title, msg, stopButton, waitButton, debugButton, neverShowDlg;
   11949             : 
   11950           0 :   rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
   11951             :                                           "KillScriptTitle",
   11952             :                                           title);
   11953             : 
   11954             :   nsresult tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
   11955             :                                            "StopScriptButton",
   11956           0 :                                            stopButton);
   11957           0 :   if (NS_FAILED(tmp)) {
   11958           0 :     rv = tmp;
   11959             :   }
   11960             : 
   11961             :   tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
   11962             :                                            "WaitForScriptButton",
   11963           0 :                                            waitButton);
   11964           0 :   if (NS_FAILED(tmp)) {
   11965           0 :     rv = tmp;
   11966             :   }
   11967             : 
   11968             :   tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
   11969             :                                            "DontAskAgain",
   11970           0 :                                            neverShowDlg);
   11971           0 :   if (NS_FAILED(tmp)) {
   11972           0 :     rv = tmp;
   11973             :   }
   11974             : 
   11975             : 
   11976           0 :   if (showDebugButton) {
   11977             :     tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
   11978             :                                              "DebugScriptButton",
   11979           0 :                                              debugButton);
   11980           0 :     if (NS_FAILED(tmp)) {
   11981           0 :       rv = tmp;
   11982             :     }
   11983             : 
   11984             :     tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
   11985             :                                              "KillScriptWithDebugMessage",
   11986           0 :                                              msg);
   11987           0 :     if (NS_FAILED(tmp)) {
   11988           0 :       rv = tmp;
   11989             :     }
   11990             :   }
   11991             :   else {
   11992             :     tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
   11993             :                                              "KillScriptMessage",
   11994           0 :                                              msg);
   11995           0 :     if (NS_FAILED(tmp)) {
   11996           0 :       rv = tmp;
   11997             :     }
   11998             :   }
   11999             : 
   12000             :   // GetStringFromName can return NS_OK and still give nullptr string
   12001           0 :   if (NS_FAILED(rv) || !title || !msg || !stopButton || !waitButton ||
   12002           0 :       (!debugButton && showDebugButton) || !neverShowDlg) {
   12003           0 :     NS_ERROR("Failed to get localized strings.");
   12004           0 :     return ContinueSlowScript;
   12005             :   }
   12006             : 
   12007             :   // Append file and line number information, if available
   12008           0 :   if (filename.get()) {
   12009           0 :     nsXPIDLString scriptLocation;
   12010             :     // We want to drop the middle part of too-long locations.  We'll
   12011             :     // define "too-long" as longer than 60 UTF-16 code units.  Just
   12012             :     // have to be a bit careful about unpaired surrogates.
   12013           0 :     NS_ConvertUTF8toUTF16 filenameUTF16(filename.get());
   12014           0 :     if (filenameUTF16.Length() > 60) {
   12015             :       // XXXbz Do we need to insert any bidi overrides here?
   12016           0 :       size_t cutStart = 30;
   12017           0 :       size_t cutLength = filenameUTF16.Length() - 60;
   12018           0 :       MOZ_ASSERT(cutLength > 0);
   12019           0 :       if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart])) {
   12020             :         // Don't truncate before the low surrogate, in case it's preceded by a
   12021             :         // high surrogate and forms a single Unicode character.  Instead, just
   12022             :         // include the low surrogate.
   12023           0 :         ++cutStart;
   12024           0 :         --cutLength;
   12025             :       }
   12026           0 :       if (NS_IS_LOW_SURROGATE(filenameUTF16[cutStart + cutLength])) {
   12027             :         // Likewise, don't drop a trailing low surrogate here.  We want to
   12028             :         // increase cutLength, since it might be 0 already so we can't very well
   12029             :         // decrease it.
   12030           0 :         ++cutLength;
   12031             :       }
   12032             : 
   12033             :       // Insert U+2026 HORIZONTAL ELLIPSIS
   12034           0 :       filenameUTF16.Replace(cutStart, cutLength, NS_LITERAL_STRING(u"\x2026"));
   12035             :     }
   12036           0 :     const char16_t *formatParams[] = { filenameUTF16.get() };
   12037           0 :     rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
   12038             :                                                "KillScriptLocation",
   12039             :                                                formatParams,
   12040             :                                                scriptLocation);
   12041             : 
   12042           0 :     if (NS_SUCCEEDED(rv) && scriptLocation) {
   12043           0 :       msg.AppendLiteral("\n\n");
   12044           0 :       msg.Append(scriptLocation);
   12045           0 :       msg.Append(':');
   12046           0 :       msg.AppendInt(lineno);
   12047             :     }
   12048             :   }
   12049             : 
   12050           0 :   int32_t buttonPressed = 0; // In case the user exits dialog by clicking X.
   12051           0 :   bool neverShowDlgChk = false;
   12052             :   uint32_t buttonFlags = nsIPrompt::BUTTON_POS_1_DEFAULT +
   12053             :                          (nsIPrompt::BUTTON_TITLE_IS_STRING *
   12054           0 :                           (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));
   12055             : 
   12056             :   // Add a third button if necessary.
   12057           0 :   if (showDebugButton)
   12058           0 :     buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
   12059             : 
   12060             :   // Null out the operation callback while we're re-entering JS here.
   12061           0 :   bool old = JS_DisableInterruptCallback(cx);
   12062             : 
   12063             :   // Open the dialog.
   12064           0 :   rv = prompt->ConfirmEx(title, msg, buttonFlags, waitButton, stopButton,
   12065             :                          debugButton, neverShowDlg, &neverShowDlgChk,
   12066           0 :                          &buttonPressed);
   12067             : 
   12068           0 :   JS_ResetInterruptCallback(cx, old);
   12069             : 
   12070           0 :   if (NS_SUCCEEDED(rv) && (buttonPressed == 0)) {
   12071           0 :     return neverShowDlgChk ? AlwaysContinueSlowScript : ContinueSlowScript;
   12072             :   }
   12073           0 :   if (buttonPressed == 2) {
   12074           0 :     if (debugCallback) {
   12075           0 :       rv = debugCallback->HandleSlowScriptDebug(this);
   12076           0 :       return NS_SUCCEEDED(rv) ? ContinueSlowScript : KillSlowScript;
   12077             :     }
   12078             :   }
   12079           0 :   JS_ClearPendingException(cx);
   12080           0 :   return KillSlowScript;
   12081             : }
   12082             : 
   12083             : uint32_t
   12084           0 : nsGlobalWindow::FindInsertionIndex(IdleObserverHolder* aIdleObserver)
   12085             : {
   12086           0 :   MOZ_ASSERT(IsInnerWindow());
   12087           0 :   MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
   12088             : 
   12089           0 :   uint32_t i = 0;
   12090           0 :   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
   12091           0 :   while (iter.HasMore()) {
   12092           0 :     IdleObserverHolder& idleObserver = iter.GetNext();
   12093           0 :     if (idleObserver.mTimeInS > aIdleObserver->mTimeInS) {
   12094           0 :       break;
   12095             :     }
   12096           0 :     i++;
   12097           0 :     MOZ_ASSERT(i <= mIdleObservers.Length(), "Array index out of bounds error.");
   12098             :   }
   12099             : 
   12100           0 :   return i;
   12101             : }
   12102             : 
   12103             : nsresult
   12104           0 : nsGlobalWindow::RegisterIdleObserver(nsIIdleObserver* aIdleObserver)
   12105             : {
   12106           0 :   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   12107             : 
   12108             :   nsresult rv;
   12109           0 :   if (mIdleObservers.IsEmpty()) {
   12110           0 :     mIdleService = do_GetService("@mozilla.org/widget/idleservice;1", &rv);
   12111           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12112             : 
   12113           0 :     rv = mIdleService->AddIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
   12114           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12115             : 
   12116           0 :     if (!mIdleTimer) {
   12117           0 :       mIdleTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
   12118           0 :       NS_ENSURE_SUCCESS(rv, rv);
   12119             :     } else {
   12120           0 :       mIdleTimer->Cancel();
   12121             :     }
   12122             :   }
   12123             : 
   12124           0 :   MOZ_ASSERT(mIdleService);
   12125           0 :   MOZ_ASSERT(mIdleTimer);
   12126             : 
   12127           0 :   IdleObserverHolder tmpIdleObserver;
   12128           0 :   tmpIdleObserver.mIdleObserver = aIdleObserver;
   12129           0 :   rv = aIdleObserver->GetTime(&tmpIdleObserver.mTimeInS);
   12130           0 :   NS_ENSURE_SUCCESS(rv, rv);
   12131           0 :   NS_ENSURE_ARG_MAX(tmpIdleObserver.mTimeInS, UINT32_MAX / 1000);
   12132           0 :   NS_ENSURE_ARG_MIN(tmpIdleObserver.mTimeInS, MIN_IDLE_NOTIFICATION_TIME_S);
   12133             : 
   12134           0 :   uint32_t insertAtIndex = FindInsertionIndex(&tmpIdleObserver);
   12135           0 :   if (insertAtIndex == mIdleObservers.Length()) {
   12136           0 :     mIdleObservers.AppendElement(tmpIdleObserver);
   12137             :   }
   12138             :   else {
   12139           0 :     mIdleObservers.InsertElementAt(insertAtIndex, tmpIdleObserver);
   12140             :   }
   12141             : 
   12142           0 :   bool userIsIdle = false;
   12143           0 :   rv = nsContentUtils::IsUserIdle(MIN_IDLE_NOTIFICATION_TIME_S, &userIsIdle);
   12144           0 :   NS_ENSURE_SUCCESS(rv, rv);
   12145             : 
   12146             :   // Special case. First idle observer added to empty list while the user is idle.
   12147             :   // Haven't received 'idle' topic notification from slow idle service yet.
   12148             :   // Need to wait for the idle notification and then notify idle observers in the list.
   12149           0 :   if (userIsIdle && mIdleCallbackIndex == -1) {
   12150           0 :     return NS_OK;
   12151             :   }
   12152             : 
   12153           0 :   if (!mCurrentlyIdle) {
   12154           0 :     return NS_OK;
   12155             :   }
   12156             : 
   12157           0 :   MOZ_ASSERT(mIdleCallbackIndex >= 0);
   12158             : 
   12159           0 :   if (static_cast<int32_t>(insertAtIndex) < mIdleCallbackIndex) {
   12160           0 :     IdleObserverHolder& idleObserver = mIdleObservers.ElementAt(insertAtIndex);
   12161           0 :     NotifyIdleObserver(&idleObserver, true);
   12162           0 :     mIdleCallbackIndex++;
   12163           0 :     return NS_OK;
   12164             :   }
   12165             : 
   12166           0 :   if (static_cast<int32_t>(insertAtIndex) == mIdleCallbackIndex) {
   12167           0 :     mIdleTimer->Cancel();
   12168           0 :     rv = ScheduleNextIdleObserverCallback();
   12169           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12170             :   }
   12171           0 :   return NS_OK;
   12172             : }
   12173             : 
   12174             : nsresult
   12175           0 : nsGlobalWindow::FindIndexOfElementToRemove(nsIIdleObserver* aIdleObserver,
   12176             :                                            int32_t* aRemoveElementIndex)
   12177             : {
   12178           0 :   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   12179           0 :   MOZ_ASSERT(aIdleObserver, "Idle observer not instantiated.");
   12180             : 
   12181           0 :   *aRemoveElementIndex = 0;
   12182           0 :   if (mIdleObservers.IsEmpty()) {
   12183           0 :     return NS_ERROR_FAILURE;
   12184             :   }
   12185             : 
   12186             :   uint32_t aIdleObserverTimeInS;
   12187           0 :   nsresult rv = aIdleObserver->GetTime(&aIdleObserverTimeInS);
   12188           0 :   NS_ENSURE_SUCCESS(rv, rv);
   12189           0 :   NS_ENSURE_ARG_MIN(aIdleObserverTimeInS, MIN_IDLE_NOTIFICATION_TIME_S);
   12190             : 
   12191           0 :   nsTObserverArray<IdleObserverHolder>::ForwardIterator iter(mIdleObservers);
   12192           0 :   while (iter.HasMore()) {
   12193           0 :     IdleObserverHolder& idleObserver = iter.GetNext();
   12194           0 :     if (idleObserver.mTimeInS == aIdleObserverTimeInS &&
   12195           0 :         idleObserver.mIdleObserver == aIdleObserver ) {
   12196           0 :       break;
   12197             :     }
   12198           0 :     (*aRemoveElementIndex)++;
   12199             :   }
   12200           0 :   return static_cast<uint32_t>(*aRemoveElementIndex) >= mIdleObservers.Length() ?
   12201           0 :     NS_ERROR_FAILURE : NS_OK;
   12202             : }
   12203             : 
   12204             : nsresult
   12205           0 : nsGlobalWindow::UnregisterIdleObserver(nsIIdleObserver* aIdleObserver)
   12206             : {
   12207           0 :   MOZ_ASSERT(IsInnerWindow(), "Must be an inner window!");
   12208             : 
   12209             :   int32_t removeElementIndex;
   12210           0 :   nsresult rv = FindIndexOfElementToRemove(aIdleObserver, &removeElementIndex);
   12211           0 :   if (NS_FAILED(rv)) {
   12212           0 :     NS_WARNING("Idle observer not found in list of idle observers. No idle observer removed.");
   12213           0 :     return NS_OK;
   12214             :   }
   12215           0 :   mIdleObservers.RemoveElementAt(removeElementIndex);
   12216             : 
   12217           0 :   MOZ_ASSERT(mIdleTimer);
   12218           0 :   if (mIdleObservers.IsEmpty() && mIdleService) {
   12219           0 :     rv = mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
   12220           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12221           0 :     mIdleService = nullptr;
   12222             : 
   12223           0 :     mIdleTimer->Cancel();
   12224           0 :     mIdleCallbackIndex = -1;
   12225           0 :     return NS_OK;
   12226             :   }
   12227             : 
   12228           0 :   if (!mCurrentlyIdle) {
   12229           0 :     return NS_OK;
   12230             :   }
   12231             : 
   12232           0 :   if (removeElementIndex < mIdleCallbackIndex) {
   12233           0 :     mIdleCallbackIndex--;
   12234           0 :     return NS_OK;
   12235             :   }
   12236             : 
   12237           0 :   if (removeElementIndex != mIdleCallbackIndex) {
   12238           0 :     return NS_OK;
   12239             :   }
   12240             : 
   12241           0 :   mIdleTimer->Cancel();
   12242             : 
   12243             :   // If the last element in the array had been notified then decrement
   12244             :   // mIdleCallbackIndex because an idle was removed from the list of
   12245             :   // idle observers.
   12246             :   // Example: add idle observer with time 1, 2, 3,
   12247             :   // Idle notifications for idle observers with time 1, 2, 3 are complete
   12248             :   // Remove idle observer with time 3 while the user is still idle.
   12249             :   // The user never transitioned to active state.
   12250             :   // Add an idle observer with idle time 4
   12251           0 :   if (static_cast<uint32_t>(mIdleCallbackIndex) == mIdleObservers.Length()) {
   12252           0 :     mIdleCallbackIndex--;
   12253             :   }
   12254           0 :   rv = ScheduleNextIdleObserverCallback();
   12255           0 :   NS_ENSURE_SUCCESS(rv, rv);
   12256             : 
   12257           0 :   return NS_OK;
   12258             : }
   12259             : 
   12260             : nsresult
   12261           0 : nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
   12262             :                         const char16_t* aData)
   12263             : {
   12264           0 :   if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
   12265           0 :     if (!IsFrozen()) {
   12266             :         // Fires an offline status event if the offline status has changed
   12267           0 :         FireOfflineStatusEventIfChanged();
   12268             :     }
   12269           0 :     return NS_OK;
   12270             :   }
   12271             : 
   12272           0 :   if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_IDLE)) {
   12273           0 :     mCurrentlyIdle = true;
   12274           0 :     if (IsFrozen()) {
   12275             :       // need to fire only one idle event while the window is frozen.
   12276           0 :       mNotifyIdleObserversIdleOnThaw = true;
   12277           0 :       mNotifyIdleObserversActiveOnThaw = false;
   12278           0 :     } else if (AsInner()->IsCurrentInnerWindow()) {
   12279           0 :       HandleIdleActiveEvent();
   12280             :     }
   12281           0 :     return NS_OK;
   12282             :   }
   12283             : 
   12284           0 :   if (!nsCRT::strcmp(aTopic, OBSERVER_TOPIC_ACTIVE)) {
   12285           0 :     mCurrentlyIdle = false;
   12286           0 :     if (IsFrozen()) {
   12287           0 :       mNotifyIdleObserversActiveOnThaw = true;
   12288           0 :       mNotifyIdleObserversIdleOnThaw = false;
   12289           0 :     } else if (AsInner()->IsCurrentInnerWindow()) {
   12290           0 :       MOZ_ASSERT(IsInnerWindow());
   12291           0 :       ScheduleActiveTimerCallback();
   12292             :     }
   12293           0 :     return NS_OK;
   12294             :   }
   12295             : 
   12296           0 :   if (!nsCRT::strcmp(aTopic, "offline-cache-update-added")) {
   12297           0 :     if (mApplicationCache)
   12298           0 :       return NS_OK;
   12299             : 
   12300             :     // Instantiate the application object now. It observes update belonging to
   12301             :     // this window's document and correctly updates the applicationCache object
   12302             :     // state.
   12303           0 :     nsCOMPtr<nsIDOMOfflineResourceList> applicationCache = GetApplicationCache();
   12304           0 :     nsCOMPtr<nsIObserver> observer = do_QueryInterface(applicationCache);
   12305           0 :     if (observer)
   12306           0 :       observer->Observe(aSubject, aTopic, aData);
   12307             : 
   12308           0 :     return NS_OK;
   12309             :   }
   12310             : 
   12311             : #ifdef MOZ_B2G
   12312             :   if (!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) ||
   12313             :       !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC)) {
   12314             :     MOZ_ASSERT(IsInnerWindow());
   12315             :     if (!AsInner()->IsCurrentInnerWindow()) {
   12316             :       return NS_OK;
   12317             :     }
   12318             : 
   12319             :     RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
   12320             :     event->InitEvent(
   12321             :       !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC)
   12322             :         ? NETWORK_UPLOAD_EVENT_NAME
   12323             :         : NETWORK_DOWNLOAD_EVENT_NAME,
   12324             :       false, false);
   12325             :     event->SetTrusted(true);
   12326             : 
   12327             :     bool dummy;
   12328             :     return DispatchEvent(event, &dummy);
   12329             :   }
   12330             : #endif // MOZ_B2G
   12331             : 
   12332           0 :   if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
   12333           0 :     MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages"));
   12334           0 :     MOZ_ASSERT(IsInnerWindow());
   12335             : 
   12336             :     // The user preferred languages have changed, we need to fire an event on
   12337             :     // Window object and invalidate the cache for navigator.languages. It is
   12338             :     // done for every change which can be a waste of cycles but those should be
   12339             :     // fairly rare.
   12340             :     // We MUST invalidate navigator.languages before sending the event in the
   12341             :     // very likely situation where an event handler will try to read its value.
   12342             : 
   12343           0 :     if (mNavigator) {
   12344           0 :       NavigatorBinding::ClearCachedLanguageValue(mNavigator);
   12345           0 :       NavigatorBinding::ClearCachedLanguagesValue(mNavigator);
   12346             :     }
   12347             : 
   12348             :     // The event has to be dispatched only to the current inner window.
   12349           0 :     if (!AsInner()->IsCurrentInnerWindow()) {
   12350           0 :       return NS_OK;
   12351             :     }
   12352             : 
   12353           0 :     RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
   12354           0 :     event->InitEvent(NS_LITERAL_STRING("languagechange"), false, false);
   12355           0 :     event->SetTrusted(true);
   12356             : 
   12357             :     bool dummy;
   12358           0 :     return DispatchEvent(event, &dummy);
   12359             :   }
   12360             : 
   12361           0 :   NS_WARNING("unrecognized topic in nsGlobalWindow::Observe");
   12362           0 :   return NS_ERROR_FAILURE;
   12363             : }
   12364             : 
   12365             : void
   12366           0 : nsGlobalWindow::ObserveStorageNotification(StorageEvent* aEvent,
   12367             :                                            const char16_t* aStorageType,
   12368             :                                            bool aPrivateBrowsing)
   12369             : {
   12370           0 :   MOZ_ASSERT(aEvent);
   12371             : 
   12372             :   // Enforce that the source storage area's private browsing state matches
   12373             :   // this window's state.  These flag checks and their maintenance independent
   12374             :   // from the principal's OriginAttributes matter because chrome docshells
   12375             :   // that are part of private browsing windows can be private browsing without
   12376             :   // having their OriginAttributes set (because they have the system
   12377             :   // principal).
   12378           0 :   bool isPrivateBrowsing = IsPrivateBrowsing();
   12379           0 :   if (isPrivateBrowsing != aPrivateBrowsing) {
   12380           0 :     return;
   12381             :   }
   12382             : 
   12383             :   // LocalStorage can only exist on an inner window, and we don't want to
   12384             :   // generate events on frozen or otherwise-navigated-away from windows.
   12385             :   // (Actually, this code used to try and buffer events for frozen windows,
   12386             :   // but it never worked, so we've removed it.  See bug 1285898.)
   12387           0 :   if (!IsInnerWindow() || !AsInner()->IsCurrentInnerWindow() || IsFrozen()) {
   12388           0 :     return;
   12389             :   }
   12390             : 
   12391           0 :   nsIPrincipal *principal = GetPrincipal();
   12392           0 :   if (!principal) {
   12393           0 :     return;
   12394             :   }
   12395             : 
   12396           0 :   bool fireMozStorageChanged = false;
   12397           0 :   nsAutoString eventType;
   12398           0 :   eventType.AssignLiteral("storage");
   12399             : 
   12400           0 :   if (!NS_strcmp(aStorageType, u"sessionStorage")) {
   12401           0 :     nsCOMPtr<nsIDOMStorage> changingStorage = aEvent->GetStorageArea();
   12402           0 :     MOZ_ASSERT(changingStorage);
   12403             : 
   12404           0 :     bool check = false;
   12405             : 
   12406           0 :     nsCOMPtr<nsIDOMStorageManager> storageManager = do_QueryInterface(GetDocShell());
   12407           0 :     if (storageManager) {
   12408           0 :       nsresult rv = storageManager->CheckStorage(principal, changingStorage,
   12409           0 :                                                  &check);
   12410           0 :       if (NS_FAILED(rv)) {
   12411           0 :         return;
   12412             :       }
   12413             :     }
   12414             : 
   12415           0 :     if (!check) {
   12416             :       // This storage event is not coming from our storage or is coming
   12417             :       // from a different docshell, i.e. it is a clone, ignore this event.
   12418           0 :       return;
   12419             :     }
   12420             : 
   12421           0 :     MOZ_LOG(gDOMLeakPRLog, LogLevel::Debug,
   12422             :             ("nsGlobalWindow %p with sessionStorage %p passing event from %p",
   12423             :              this, mSessionStorage.get(), changingStorage.get()));
   12424             : 
   12425           0 :     fireMozStorageChanged = mSessionStorage == changingStorage;
   12426           0 :     if (fireMozStorageChanged) {
   12427           0 :       eventType.AssignLiteral("MozSessionStorageChanged");
   12428             :     }
   12429             :   }
   12430             : 
   12431             :   else {
   12432           0 :     MOZ_ASSERT(!NS_strcmp(aStorageType, u"localStorage"));
   12433           0 :     nsIPrincipal* storagePrincipal = aEvent->GetPrincipal();
   12434           0 :     if (!storagePrincipal) {
   12435           0 :       return;
   12436             :     }
   12437             : 
   12438           0 :     bool equals = false;
   12439           0 :     nsresult rv = storagePrincipal->Equals(principal, &equals);
   12440           0 :     NS_ENSURE_SUCCESS_VOID(rv);
   12441             : 
   12442           0 :     if (!equals) {
   12443           0 :       return;
   12444             :     }
   12445             : 
   12446           0 :     fireMozStorageChanged = mLocalStorage == aEvent->GetStorageArea();
   12447             : 
   12448           0 :     if (fireMozStorageChanged) {
   12449           0 :       eventType.AssignLiteral("MozLocalStorageChanged");
   12450             :     }
   12451             :   }
   12452             : 
   12453             :   // Clone the storage event included in the observer notification. We want
   12454             :   // to dispatch clones rather than the original event.
   12455           0 :   IgnoredErrorResult error;
   12456             :   RefPtr<StorageEvent> clonedEvent =
   12457           0 :     CloneStorageEvent(eventType, aEvent, error);
   12458           0 :   if (error.Failed()) {
   12459           0 :     return;
   12460             :   }
   12461             : 
   12462           0 :   clonedEvent->SetTrusted(true);
   12463             : 
   12464           0 :   if (fireMozStorageChanged) {
   12465           0 :     WidgetEvent* internalEvent = clonedEvent->WidgetEventPtr();
   12466           0 :     internalEvent->mFlags.mOnlyChromeDispatch = true;
   12467             :   }
   12468             : 
   12469             :   bool defaultActionEnabled;
   12470           0 :   DispatchEvent(clonedEvent, &defaultActionEnabled);
   12471             : }
   12472             : 
   12473             : already_AddRefed<StorageEvent>
   12474           0 : nsGlobalWindow::CloneStorageEvent(const nsAString& aType,
   12475             :                                   const RefPtr<StorageEvent>& aEvent,
   12476             :                                   ErrorResult& aRv)
   12477             : {
   12478           0 :   MOZ_ASSERT(IsInnerWindow());
   12479             : 
   12480           0 :   StorageEventInit dict;
   12481             : 
   12482           0 :   dict.mBubbles = aEvent->Bubbles();
   12483           0 :   dict.mCancelable = aEvent->Cancelable();
   12484           0 :   aEvent->GetKey(dict.mKey);
   12485           0 :   aEvent->GetOldValue(dict.mOldValue);
   12486           0 :   aEvent->GetNewValue(dict.mNewValue);
   12487           0 :   aEvent->GetUrl(dict.mUrl);
   12488             : 
   12489           0 :   RefPtr<Storage> storageArea = aEvent->GetStorageArea();
   12490             : 
   12491           0 :   RefPtr<Storage> storage;
   12492             : 
   12493             :   // If null, this is a localStorage event received by IPC.
   12494           0 :   if (!storageArea) {
   12495           0 :     storage = GetLocalStorage(aRv);
   12496           0 :     if (aRv.Failed() || !storage) {
   12497           0 :       return nullptr;
   12498             :     }
   12499             : 
   12500           0 :     MOZ_ASSERT(storage->Type() == Storage::eLocalStorage);
   12501             :     RefPtr<LocalStorage> localStorage =
   12502           0 :       static_cast<LocalStorage*>(storage.get());
   12503             : 
   12504             :     // We must apply the current change to the 'local' localStorage.
   12505           0 :     localStorage->ApplyEvent(aEvent);
   12506           0 :   } else if (storageArea->Type() == Storage::eSessionStorage) {
   12507           0 :     storage = GetSessionStorage(aRv);
   12508             :   } else {
   12509           0 :     MOZ_ASSERT(storageArea->Type() == Storage::eLocalStorage);
   12510           0 :     storage = GetLocalStorage(aRv);
   12511             :   }
   12512             : 
   12513           0 :   if (aRv.Failed() || !storage) {
   12514           0 :     return nullptr;
   12515             :   }
   12516             : 
   12517           0 :   MOZ_ASSERT(storage);
   12518           0 :   MOZ_ASSERT_IF(storageArea, storage->IsForkOf(storageArea));
   12519             : 
   12520           0 :   dict.mStorageArea = storage;
   12521             : 
   12522           0 :   RefPtr<StorageEvent> event = StorageEvent::Constructor(this, aType, dict);
   12523           0 :   return event.forget();
   12524             : }
   12525             : 
   12526             : void
   12527           0 : nsGlobalWindow::Suspend()
   12528             : {
   12529           0 :   MOZ_ASSERT(NS_IsMainThread());
   12530           0 :   MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
   12531             : 
   12532             :   // We can only safely suspend windows that are the current inner window.  If
   12533             :   // its not the current inner, then we are in one of two different cases.
   12534             :   // Either we are in the bfcache or we are doomed window that is going away.
   12535             :   // When a window becomes inactive we purposely avoid placing already suspended
   12536             :   // windows into the bfcache.  It only expects windows suspended due to the
   12537             :   // Freeze() method which occurs while the window is still the current inner.
   12538             :   // So we must not call Suspend() on bfcache windows at this point or this
   12539             :   // invariant will be broken.  If the window is doomed there is no point in
   12540             :   // suspending it since it will soon be gone.
   12541           0 :   if (!AsInner()->IsCurrentInnerWindow()) {
   12542           0 :     return;
   12543             :   }
   12544             : 
   12545             :   // All children are also suspended.  This ensure mSuspendDepth is
   12546             :   // set properly and the timers are properly canceled for each child.
   12547           0 :   CallOnChildren(&nsGlobalWindow::Suspend);
   12548             : 
   12549           0 :   mSuspendDepth += 1;
   12550           0 :   if (mSuspendDepth != 1) {
   12551           0 :     return;
   12552             :   }
   12553             : 
   12554           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
   12555           0 :   if (ac) {
   12556           0 :     for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
   12557           0 :       ac->RemoveWindowListener(mEnabledSensors[i], this);
   12558             :   }
   12559           0 :   DisableGamepadUpdates();
   12560           0 :   DisableVRUpdates();
   12561             : 
   12562           0 :   mozilla::dom::workers::SuspendWorkersForWindow(AsInner());
   12563             : 
   12564           0 :   SuspendIdleRequests();
   12565             : 
   12566           0 :   mTimeoutManager->Suspend();
   12567             : 
   12568             :   // Suspend all of the AudioContexts for this window
   12569           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
   12570           0 :     ErrorResult dummy;
   12571           0 :     RefPtr<Promise> d = mAudioContexts[i]->Suspend(dummy);
   12572             :   }
   12573             : }
   12574             : 
   12575             : void
   12576           0 : nsGlobalWindow::Resume()
   12577             : {
   12578           0 :   MOZ_ASSERT(NS_IsMainThread());
   12579           0 :   MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
   12580             : 
   12581             :   // We can only safely resume a window if its the current inner window.  If
   12582             :   // its not the current inner, then we are in one of two different cases.
   12583             :   // Either we are in the bfcache or we are doomed window that is going away.
   12584             :   // If a window is suspended when it becomes inactive we purposely do not
   12585             :   // put it in the bfcache, so Resume should never be needed in that case.
   12586             :   // If the window is doomed then there is no point in resuming it.
   12587           0 :   if (!AsInner()->IsCurrentInnerWindow()) {
   12588           0 :     return;
   12589             :   }
   12590             : 
   12591             :   // Resume all children.  This restores timers recursively canceled
   12592             :   // in Suspend() and ensures all children have the correct mSuspendDepth.
   12593           0 :   CallOnChildren(&nsGlobalWindow::Resume);
   12594             : 
   12595           0 :   MOZ_ASSERT(mSuspendDepth != 0);
   12596           0 :   mSuspendDepth -= 1;
   12597           0 :   if (mSuspendDepth != 0) {
   12598           0 :     return;
   12599             :   }
   12600             : 
   12601             :   // We should not be able to resume a frozen window.  It must be Thaw()'d first.
   12602           0 :   MOZ_ASSERT(mFreezeDepth == 0);
   12603             : 
   12604           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
   12605           0 :   if (ac) {
   12606           0 :     for (uint32_t i = 0; i < mEnabledSensors.Length(); i++)
   12607           0 :       ac->AddWindowListener(mEnabledSensors[i], this);
   12608             :   }
   12609           0 :   EnableGamepadUpdates();
   12610           0 :   EnableVRUpdates();
   12611             : 
   12612             :   // Resume all of the AudioContexts for this window
   12613           0 :   for (uint32_t i = 0; i < mAudioContexts.Length(); ++i) {
   12614           0 :     ErrorResult dummy;
   12615           0 :     RefPtr<Promise> d = mAudioContexts[i]->Resume(dummy);
   12616             :   }
   12617             : 
   12618           0 :   mTimeoutManager->Resume();
   12619             : 
   12620           0 :   ResumeIdleRequests();
   12621             : 
   12622             :   // Resume all of the workers for this window.  We must do this
   12623             :   // after timeouts since workers may have queued events that can trigger
   12624             :   // a setTimeout().
   12625           0 :   mozilla::dom::workers::ResumeWorkersForWindow(AsInner());
   12626             : }
   12627             : 
   12628             : bool
   12629          49 : nsGlobalWindow::IsSuspended() const
   12630             : {
   12631          49 :   MOZ_ASSERT(NS_IsMainThread());
   12632             :   // No inner means we are effectively suspended
   12633          49 :   if (IsOuterWindow()) {
   12634           0 :     if (!mInnerWindow) {
   12635           0 :       return true;
   12636             :     }
   12637           0 :     return mInnerWindow->IsSuspended();
   12638             :   }
   12639          49 :   return mSuspendDepth != 0;
   12640             : }
   12641             : 
   12642             : void
   12643           0 : nsGlobalWindow::Freeze()
   12644             : {
   12645           0 :   MOZ_ASSERT(NS_IsMainThread());
   12646           0 :   Suspend();
   12647           0 :   FreezeInternal();
   12648           0 : }
   12649             : 
   12650             : void
   12651           0 : nsGlobalWindow::FreezeInternal()
   12652             : {
   12653           0 :   MOZ_ASSERT(NS_IsMainThread());
   12654           0 :   MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
   12655           0 :   MOZ_DIAGNOSTIC_ASSERT(AsInner()->IsCurrentInnerWindow());
   12656           0 :   MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
   12657             : 
   12658           0 :   CallOnChildren(&nsGlobalWindow::FreezeInternal);
   12659             : 
   12660           0 :   mFreezeDepth += 1;
   12661           0 :   MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
   12662           0 :   if (mFreezeDepth != 1) {
   12663           0 :     return;
   12664             :   }
   12665             : 
   12666           0 :   mozilla::dom::workers::FreezeWorkersForWindow(AsInner());
   12667             : 
   12668           0 :   mTimeoutManager->Freeze();
   12669             : 
   12670           0 :   NotifyDOMWindowFrozen(this);
   12671             : }
   12672             : 
   12673             : void
   12674           0 : nsGlobalWindow::Thaw()
   12675             : {
   12676           0 :   MOZ_ASSERT(NS_IsMainThread());
   12677           0 :   ThawInternal();
   12678           0 :   Resume();
   12679           0 : }
   12680             : 
   12681             : void
   12682           0 : nsGlobalWindow::ThawInternal()
   12683             : {
   12684           0 :   MOZ_ASSERT(NS_IsMainThread());
   12685           0 :   MOZ_DIAGNOSTIC_ASSERT(IsInnerWindow());
   12686           0 :   MOZ_DIAGNOSTIC_ASSERT(AsInner()->IsCurrentInnerWindow());
   12687           0 :   MOZ_DIAGNOSTIC_ASSERT(IsSuspended());
   12688             : 
   12689           0 :   CallOnChildren(&nsGlobalWindow::ThawInternal);
   12690             : 
   12691           0 :   MOZ_ASSERT(mFreezeDepth != 0);
   12692           0 :   mFreezeDepth -= 1;
   12693           0 :   MOZ_ASSERT(mSuspendDepth >= mFreezeDepth);
   12694           0 :   if (mFreezeDepth != 0) {
   12695           0 :     return;
   12696             :   }
   12697             : 
   12698           0 :   mTimeoutManager->Thaw();
   12699             : 
   12700           0 :   mozilla::dom::workers::ThawWorkersForWindow(AsInner());
   12701             : 
   12702           0 :   NotifyDOMWindowThawed(this);
   12703             : }
   12704             : 
   12705             : bool
   12706          71 : nsGlobalWindow::IsFrozen() const
   12707             : {
   12708          71 :   MOZ_ASSERT(NS_IsMainThread());
   12709             :   // No inner means we are effectively frozen
   12710          71 :   if (IsOuterWindow()) {
   12711          12 :     if (!mInnerWindow) {
   12712           5 :       return true;
   12713             :     }
   12714           7 :     return mInnerWindow->IsFrozen();
   12715             :   }
   12716          59 :   bool frozen = mFreezeDepth != 0;
   12717          59 :   MOZ_ASSERT_IF(frozen, IsSuspended());
   12718          59 :   return frozen;
   12719             : }
   12720             : 
   12721             : void
   12722           7 : nsGlobalWindow::SyncStateFromParentWindow()
   12723             : {
   12724             :   // This method should only be called on an inner window that has been
   12725             :   // assigned to an outer window already.
   12726           7 :   MOZ_ASSERT(IsInnerWindow());
   12727           7 :   MOZ_ASSERT(AsInner()->IsCurrentInnerWindow());
   12728           7 :   nsPIDOMWindowOuter* outer = GetOuterWindow();
   12729           7 :   MOZ_ASSERT(outer);
   12730             : 
   12731             :   // Attempt to find our parent windows.
   12732          14 :   nsCOMPtr<Element> frame = outer->GetFrameElementInternal();
   12733           7 :   nsPIDOMWindowOuter* parentOuter = frame ? frame->OwnerDoc()->GetWindow()
   12734          14 :                                           : nullptr;
   12735             :   nsGlobalWindow* parentInner =
   12736           7 :     parentOuter ? nsGlobalWindow::Cast(parentOuter->GetCurrentInnerWindow())
   12737           7 :                 : nullptr;
   12738             : 
   12739             :   // If our outer is in a modal state, but our parent is not in a modal
   12740             :   // state, then we must apply the suspend directly.  If our parent is
   12741             :   // in a modal state then we should get the suspend automatically
   12742             :   // via the parentSuspendDepth application below.
   12743           7 :   if ((!parentInner || !parentInner->IsInModalState()) && IsInModalState()) {
   12744           0 :     Suspend();
   12745             :   }
   12746             : 
   12747           7 :   uint32_t parentFreezeDepth = parentInner ? parentInner->mFreezeDepth : 0;
   12748           7 :   uint32_t parentSuspendDepth = parentInner ? parentInner->mSuspendDepth : 0;
   12749             : 
   12750             :   // Since every Freeze() calls Suspend(), the suspend count must
   12751             :   // be equal or greater to the freeze count.
   12752           7 :   MOZ_ASSERT(parentFreezeDepth <= parentSuspendDepth);
   12753             : 
   12754             :   // First apply the Freeze() calls.
   12755           7 :   for (uint32_t i = 0; i < parentFreezeDepth; ++i) {
   12756           0 :     Freeze();
   12757             :   }
   12758             : 
   12759             :   // Now apply only the number of Suspend() calls to reach the target
   12760             :   // suspend count after applying the Freeze() calls.
   12761           7 :   for (uint32_t i = 0; i < (parentSuspendDepth - parentFreezeDepth); ++i) {
   12762           0 :     Suspend();
   12763             :   }
   12764           7 : }
   12765             : 
   12766             : template<typename Method>
   12767             : void
   12768           0 : nsGlobalWindow::CallOnChildren(Method aMethod)
   12769             : {
   12770           0 :   MOZ_ASSERT(NS_IsMainThread());
   12771           0 :   MOZ_ASSERT(IsInnerWindow());
   12772           0 :   MOZ_ASSERT(AsInner()->IsCurrentInnerWindow());
   12773             : 
   12774           0 :   nsCOMPtr<nsIDocShell> docShell = GetDocShell();
   12775           0 :   if (!docShell) {
   12776           0 :     return;
   12777             :   }
   12778             : 
   12779           0 :   int32_t childCount = 0;
   12780           0 :   docShell->GetChildCount(&childCount);
   12781             : 
   12782           0 :   for (int32_t i = 0; i < childCount; ++i) {
   12783           0 :     nsCOMPtr<nsIDocShellTreeItem> childShell;
   12784           0 :     docShell->GetChildAt(i, getter_AddRefs(childShell));
   12785           0 :     NS_ASSERTION(childShell, "null child shell");
   12786             : 
   12787           0 :     nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow();
   12788           0 :     if (!pWin) {
   12789           0 :       continue;
   12790             :     }
   12791             : 
   12792           0 :     auto* win = nsGlobalWindow::Cast(pWin);
   12793           0 :     nsGlobalWindow* inner = win->GetCurrentInnerWindowInternal();
   12794             : 
   12795             :     // This is a bit hackish. Only freeze/suspend windows which are truly our
   12796             :     // subwindows.
   12797           0 :     nsCOMPtr<Element> frame = pWin->GetFrameElementInternal();
   12798           0 :     if (!mDoc || !frame || mDoc != frame->OwnerDoc() || !inner) {
   12799           0 :       continue;
   12800             :     }
   12801             : 
   12802           0 :     (inner->*aMethod)();
   12803             :   }
   12804             : }
   12805             : 
   12806             : nsresult
   12807           0 : nsGlobalWindow::FireDelayedDOMEvents()
   12808             : {
   12809           0 :   FORWARD_TO_INNER(FireDelayedDOMEvents, (), NS_ERROR_UNEXPECTED);
   12810             : 
   12811           0 :   if (mApplicationCache) {
   12812           0 :     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->FirePendingEvents();
   12813             :   }
   12814             : 
   12815             :   // Fires an offline status event if the offline status has changed
   12816           0 :   FireOfflineStatusEventIfChanged();
   12817             : 
   12818           0 :   if (mNotifyIdleObserversIdleOnThaw) {
   12819           0 :     mNotifyIdleObserversIdleOnThaw = false;
   12820           0 :     HandleIdleActiveEvent();
   12821             :   }
   12822             : 
   12823           0 :   if (mNotifyIdleObserversActiveOnThaw) {
   12824           0 :     mNotifyIdleObserversActiveOnThaw = false;
   12825           0 :     ScheduleActiveTimerCallback();
   12826             :   }
   12827             : 
   12828           0 :   nsCOMPtr<nsIDocShell> docShell = GetDocShell();
   12829           0 :   if (docShell) {
   12830           0 :     int32_t childCount = 0;
   12831           0 :     docShell->GetChildCount(&childCount);
   12832             : 
   12833           0 :     for (int32_t i = 0; i < childCount; ++i) {
   12834           0 :       nsCOMPtr<nsIDocShellTreeItem> childShell;
   12835           0 :       docShell->GetChildAt(i, getter_AddRefs(childShell));
   12836           0 :       NS_ASSERTION(childShell, "null child shell");
   12837             : 
   12838           0 :       if (nsCOMPtr<nsPIDOMWindowOuter> pWin = childShell->GetWindow()) {
   12839           0 :         auto* win = nsGlobalWindow::Cast(pWin);
   12840           0 :         win->FireDelayedDOMEvents();
   12841             :       }
   12842             :     }
   12843             :   }
   12844             : 
   12845           0 :   return NS_OK;
   12846             : }
   12847             : 
   12848             : //*****************************************************************************
   12849             : // nsGlobalWindow: Window Control Functions
   12850             : //*****************************************************************************
   12851             : 
   12852             : nsPIDOMWindowOuter*
   12853           7 : nsGlobalWindow::GetParentInternal()
   12854             : {
   12855           7 :   if (IsInnerWindow()) {
   12856           1 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   12857           1 :     if (!outer) {
   12858           0 :       NS_WARNING("No outer window available!");
   12859           0 :       return nullptr;
   12860             :     }
   12861           1 :     return outer->GetParentInternal();
   12862             :   }
   12863             : 
   12864          12 :   nsCOMPtr<nsPIDOMWindowOuter> parent = GetParent();
   12865             : 
   12866           6 :   if (parent && parent != AsOuter()) {
   12867           2 :     return parent;
   12868             :   }
   12869             : 
   12870           4 :   return nullptr;
   12871             : }
   12872             : 
   12873             : void
   12874           0 : nsGlobalWindow::UnblockScriptedClosing()
   12875             : {
   12876           0 :   MOZ_ASSERT(IsOuterWindow());
   12877           0 :   mBlockScriptedClosingFlag = false;
   12878           0 : }
   12879             : 
   12880             : class AutoUnblockScriptClosing
   12881             : {
   12882             : private:
   12883             :   RefPtr<nsGlobalWindow> mWin;
   12884             : public:
   12885           0 :   explicit AutoUnblockScriptClosing(nsGlobalWindow* aWin)
   12886           0 :     : mWin(aWin)
   12887             :   {
   12888           0 :     MOZ_ASSERT(mWin);
   12889           0 :     MOZ_ASSERT(mWin->IsOuterWindow());
   12890           0 :   }
   12891           0 :   ~AutoUnblockScriptClosing()
   12892           0 :   {
   12893           0 :     void (nsGlobalWindow::*run)() = &nsGlobalWindow::UnblockScriptedClosing;
   12894           0 :     nsCOMPtr<nsIRunnable> caller = NewRunnableMethod(
   12895           0 :       "AutoUnblockScriptClosing::~AutoUnblockScriptClosing", mWin, run);
   12896           0 :     mWin->Dispatch("nsGlobalWindow::UnblockScriptedClosing",
   12897           0 :                    TaskCategory::Other, caller.forget());
   12898           0 :   }
   12899             : };
   12900             : 
   12901             : nsresult
   12902           0 : nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
   12903             :                              const nsAString& aOptions, bool aDialog,
   12904             :                              bool aContentModal, bool aCalledNoScript,
   12905             :                              bool aDoJSFixups, bool aNavigate,
   12906             :                              nsIArray *argv,
   12907             :                              nsISupports *aExtraArgument,
   12908             :                              nsIDocShellLoadInfo* aLoadInfo,
   12909             :                              bool aForceNoOpener,
   12910             :                              nsPIDOMWindowOuter **aReturn)
   12911             : {
   12912           0 :   MOZ_ASSERT(IsOuterWindow());
   12913             : 
   12914             : #ifdef DEBUG
   12915           0 :   uint32_t argc = 0;
   12916           0 :   if (argv)
   12917           0 :       argv->GetLength(&argc);
   12918             : #endif
   12919           0 :   NS_PRECONDITION(!aExtraArgument || (!argv && argc == 0),
   12920             :                   "Can't pass in arguments both ways");
   12921           0 :   NS_PRECONDITION(!aCalledNoScript || (!argv && argc == 0),
   12922             :                   "Can't pass JS args when called via the noscript methods");
   12923             : 
   12924           0 :   mozilla::Maybe<AutoUnblockScriptClosing> closeUnblocker;
   12925             : 
   12926             :   // Calls to window.open from script should navigate.
   12927           0 :   MOZ_ASSERT(aCalledNoScript || aNavigate);
   12928             : 
   12929           0 :   *aReturn = nullptr;
   12930             : 
   12931           0 :   nsCOMPtr<nsIWebBrowserChrome> chrome = GetWebBrowserChrome();
   12932           0 :   if (!chrome) {
   12933             :     // No chrome means we don't want to go through with this open call
   12934             :     // -- see nsIWindowWatcher.idl
   12935           0 :     return NS_ERROR_NOT_AVAILABLE;
   12936             :   }
   12937             : 
   12938           0 :   NS_ASSERTION(mDocShell, "Must have docshell here");
   12939             : 
   12940           0 :   bool forceNoOpener = aForceNoOpener;
   12941           0 :   if (!forceNoOpener) {
   12942             :     // Unlike other window flags, "noopener" comes from splitting on commas with
   12943             :     // HTML whitespace trimming...
   12944             :     nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
   12945           0 :       aOptions, ',');
   12946           0 :     while (tok.hasMoreTokens()) {
   12947           0 :       if (tok.nextToken().EqualsLiteral("noopener")) {
   12948           0 :         forceNoOpener = true;
   12949           0 :         break;
   12950             :       }
   12951             :     }
   12952             :   }
   12953             : 
   12954             :   // XXXbz When this gets fixed to not use LegacyIsCallerNativeCode()
   12955             :   // (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run.
   12956             :   // But note that if you change this to GetEntryGlobal(), say, then
   12957             :   // OnLinkClickEvent::Run will need a full-blown AutoEntryScript.
   12958           0 :   const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
   12959           0 :     !aDialog && !WindowExists(aName, forceNoOpener, !aCalledNoScript);
   12960             : 
   12961             :   // Note: it's very important that this be an nsXPIDLCString, since we want
   12962             :   // .get() on it to return nullptr until we write stuff to it.  The window
   12963             :   // watcher expects a null URL string if there is no URL to load.
   12964           0 :   nsXPIDLCString url;
   12965           0 :   nsresult rv = NS_OK;
   12966             : 
   12967             :   // It's important to do this security check before determining whether this
   12968             :   // window opening should be blocked, to ensure that we don't FireAbuseEvents
   12969             :   // for a window opening that wouldn't have succeeded in the first place.
   12970           0 :   if (!aUrl.IsEmpty()) {
   12971           0 :     AppendUTF16toUTF8(aUrl, url);
   12972             : 
   12973             :     // It's safe to skip the security check below if we're not a dialog
   12974             :     // because window.openDialog is not callable from content script.  See bug
   12975             :     // 56851.
   12976             :     //
   12977             :     // If we're not navigating, we assume that whoever *does* navigate the
   12978             :     // window will do a security check of their own.
   12979           0 :     if (url.get() && !aDialog && aNavigate)
   12980           0 :       rv = SecurityCheckURL(url.get());
   12981             :   }
   12982             : 
   12983           0 :   if (NS_FAILED(rv))
   12984           0 :     return rv;
   12985             : 
   12986           0 :   PopupControlState abuseLevel = gPopupControlState;
   12987           0 :   if (checkForPopup) {
   12988           0 :     abuseLevel = RevisePopupAbuseLevel(abuseLevel);
   12989           0 :     if (abuseLevel >= openAbused) {
   12990           0 :       if (!aCalledNoScript) {
   12991             :         // If script in some other window is doing a window.open on us and
   12992             :         // it's being blocked, then it's OK to close us afterwards, probably.
   12993             :         // But if we're doing a window.open on ourselves and block the popup,
   12994             :         // prevent this window from closing until after this script terminates
   12995             :         // so that whatever popup blocker UI the app has will be visible.
   12996             :         nsCOMPtr<nsPIDOMWindowInner> entryWindow =
   12997           0 :           do_QueryInterface(GetEntryGlobal());
   12998             :         // Note that entryWindow can be null here if some JS component was the
   12999             :         // place where script was entered for this JS execution.
   13000           0 :         if (entryWindow &&
   13001           0 :             entryWindow->GetOuterWindow() == this->AsOuter()) {
   13002           0 :           mBlockScriptedClosingFlag = true;
   13003           0 :           closeUnblocker.emplace(this);
   13004             :         }
   13005             :       }
   13006             : 
   13007           0 :       FireAbuseEvents(aUrl, aName, aOptions);
   13008           0 :       return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE;
   13009             :     }
   13010             :   }
   13011             : 
   13012           0 :   nsCOMPtr<mozIDOMWindowProxy> domReturn;
   13013             : 
   13014             :   nsCOMPtr<nsIWindowWatcher> wwatch =
   13015           0 :     do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
   13016           0 :   NS_ENSURE_TRUE(wwatch, rv);
   13017             : 
   13018           0 :   NS_ConvertUTF16toUTF8 options(aOptions);
   13019           0 :   NS_ConvertUTF16toUTF8 name(aName);
   13020             : 
   13021           0 :   const char *options_ptr = aOptions.IsEmpty() ? nullptr : options.get();
   13022           0 :   const char *name_ptr = aName.IsEmpty() ? nullptr : name.get();
   13023             : 
   13024           0 :   nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
   13025           0 :   NS_ENSURE_STATE(pwwatch);
   13026             : 
   13027           0 :   MOZ_ASSERT_IF(checkForPopup, abuseLevel < openAbused);
   13028             :   // At this point we should know for a fact that if checkForPopup then
   13029             :   // abuseLevel < openAbused, so we could just check for abuseLevel ==
   13030             :   // openControlled.  But let's be defensive just in case and treat anything
   13031             :   // that fails the above assert as a spam popup too, if it ever happens.
   13032           0 :   bool isPopupSpamWindow = checkForPopup && (abuseLevel >= openControlled);
   13033             : 
   13034             :   {
   13035             :     // Reset popup state while opening a window to prevent the
   13036             :     // current state from being active the whole time a modal
   13037             :     // dialog is open.
   13038           0 :     nsAutoPopupStatePusher popupStatePusher(openAbused, true);
   13039             : 
   13040           0 :     if (!aCalledNoScript) {
   13041             :       // We asserted at the top of this function that aNavigate is true for
   13042             :       // !aCalledNoScript.
   13043           0 :       rv = pwwatch->OpenWindow2(AsOuter(), url.get(), name_ptr,
   13044             :                                 options_ptr, /* aCalledFromScript = */ true,
   13045             :                                 aDialog, aNavigate, argv,
   13046             :                                 isPopupSpamWindow,
   13047             :                                 forceNoOpener,
   13048             :                                 aLoadInfo,
   13049           0 :                                 getter_AddRefs(domReturn));
   13050             :     } else {
   13051             :       // Force a system caller here so that the window watcher won't screw us
   13052             :       // up.  We do NOT want this case looking at the JS context on the stack
   13053             :       // when searching.  Compare comments on
   13054             :       // nsIDOMWindow::OpenWindow and nsIWindowWatcher::OpenWindow.
   13055             : 
   13056             :       // Note: Because nsWindowWatcher is so broken, it's actually important
   13057             :       // that we don't force a system caller here, because that screws it up
   13058             :       // when it tries to compute the caller principal to associate with dialog
   13059             :       // arguments. That whole setup just really needs to be rewritten. :-(
   13060           0 :       Maybe<AutoNoJSAPI> nojsapi;
   13061           0 :       if (!aContentModal) {
   13062           0 :         nojsapi.emplace();
   13063             :       }
   13064             : 
   13065           0 :       rv = pwwatch->OpenWindow2(AsOuter(), url.get(), name_ptr,
   13066             :                                 options_ptr, /* aCalledFromScript = */ false,
   13067             :                                 aDialog, aNavigate, aExtraArgument,
   13068             :                                 isPopupSpamWindow,
   13069             :                                 forceNoOpener,
   13070             :                                 aLoadInfo,
   13071           0 :                                 getter_AddRefs(domReturn));
   13072             : 
   13073             :     }
   13074             :   }
   13075             : 
   13076           0 :   NS_ENSURE_SUCCESS(rv, rv);
   13077             : 
   13078             :   // success!
   13079             : 
   13080           0 :   NS_ENSURE_TRUE(domReturn, NS_OK);
   13081             :   nsCOMPtr<nsPIDOMWindowOuter> outerReturn =
   13082           0 :     nsPIDOMWindowOuter::From(domReturn);
   13083           0 :   outerReturn.swap(*aReturn);
   13084             : 
   13085           0 :   if (aDoJSFixups) {
   13086           0 :     nsCOMPtr<nsIDOMChromeWindow> chrome_win(do_QueryInterface(*aReturn));
   13087           0 :     if (!chrome_win) {
   13088             :       // A new non-chrome window was created from a call to
   13089             :       // window.open() from JavaScript, make sure there's a document in
   13090             :       // the new window. We do this by simply asking the new window for
   13091             :       // its document, this will synchronously create an empty document
   13092             :       // if there is no document in the window.
   13093             :       // XXXbz should this just use EnsureInnerWindow()?
   13094             : 
   13095             :       // Force document creation.
   13096           0 :       nsCOMPtr<nsIDocument> doc = (*aReturn)->GetDoc();
   13097             :       Unused << doc;
   13098             :     }
   13099             :   }
   13100             : 
   13101           0 :   return rv;
   13102             : }
   13103             : 
   13104             : //*****************************************************************************
   13105             : // nsGlobalWindow: Timeout Functions
   13106             : //*****************************************************************************
   13107             : 
   13108             : nsGlobalWindow*
   13109          11 : nsGlobalWindow::InnerForSetTimeoutOrInterval(ErrorResult& aError)
   13110             : {
   13111             :   nsGlobalWindow* currentInner;
   13112             :   nsGlobalWindow* forwardTo;
   13113          11 :   if (IsInnerWindow()) {
   13114          11 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   13115          11 :     currentInner = outer ? outer->GetCurrentInnerWindowInternal() : this;
   13116             : 
   13117          11 :     forwardTo = this;
   13118             :   } else {
   13119           0 :     currentInner = GetCurrentInnerWindowInternal();
   13120             : 
   13121             :     // This needs to forward to the inner window, but since the current
   13122             :     // inner may not be the inner in the calling scope, we need to treat
   13123             :     // this specially here as we don't want timeouts registered in a
   13124             :     // dying inner window to get registered and run on the current inner
   13125             :     // window. To get this right, we need to forward this call to the
   13126             :     // inner window that's calling window.setTimeout().
   13127             : 
   13128           0 :     forwardTo = CallerInnerWindow();
   13129           0 :     if (!forwardTo && nsContentUtils::IsCallerChrome()) {
   13130           0 :       forwardTo = currentInner;
   13131             :     }
   13132           0 :     if (!forwardTo) {
   13133           0 :       aError.Throw(NS_ERROR_NOT_AVAILABLE);
   13134           0 :       return nullptr;
   13135             :     }
   13136             : 
   13137             :     // If the caller and the callee share the same outer window, forward to the
   13138             :     // caller inner. Else, we forward to the current inner (e.g. someone is
   13139             :     // calling setTimeout() on a reference to some other window).
   13140           0 :     if (forwardTo->GetOuterWindow() != AsOuter() ||
   13141           0 :         !forwardTo->IsInnerWindow()) {
   13142           0 :       if (!currentInner) {
   13143           0 :         NS_WARNING("No inner window available!");
   13144           0 :         aError.Throw(NS_ERROR_NOT_INITIALIZED);
   13145           0 :         return nullptr;
   13146             :       }
   13147             : 
   13148           0 :       return currentInner;
   13149             :     }
   13150             :   }
   13151             : 
   13152             :   // If forwardTo is not the window with an active document then we want the
   13153             :   // call to setTimeout/Interval to be a noop, so return null but don't set an
   13154             :   // error.
   13155          11 :   return forwardTo->AsInner()->HasActiveDocument() ? currentInner : nullptr;
   13156             : }
   13157             : 
   13158             : int32_t
   13159          11 : nsGlobalWindow::SetTimeout(JSContext* aCx, Function& aFunction,
   13160             :                            int32_t aTimeout,
   13161             :                            const Sequence<JS::Value>& aArguments,
   13162             :                            ErrorResult& aError)
   13163             : {
   13164             :   return SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments, false,
   13165          11 :                               aError);
   13166             : }
   13167             : 
   13168             : int32_t
   13169           0 : nsGlobalWindow::SetTimeout(JSContext* aCx, const nsAString& aHandler,
   13170             :                            int32_t aTimeout,
   13171             :                            const Sequence<JS::Value>& /* unused */,
   13172             :                            ErrorResult& aError)
   13173             : {
   13174           0 :   return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError);
   13175             : }
   13176             : 
   13177             : static bool
   13178           0 : IsInterval(const Optional<int32_t>& aTimeout, int32_t& aResultTimeout)
   13179             : {
   13180           0 :   if (aTimeout.WasPassed()) {
   13181           0 :     aResultTimeout = aTimeout.Value();
   13182           0 :     return true;
   13183             :   }
   13184             : 
   13185             :   // If no interval was specified, treat this like a timeout, to avoid setting
   13186             :   // an interval of 0 milliseconds.
   13187           0 :   aResultTimeout = 0;
   13188           0 :   return false;
   13189             : }
   13190             : 
   13191             : int32_t
   13192           0 : nsGlobalWindow::SetInterval(JSContext* aCx, Function& aFunction,
   13193             :                             const Optional<int32_t>& aTimeout,
   13194             :                             const Sequence<JS::Value>& aArguments,
   13195             :                             ErrorResult& aError)
   13196             : {
   13197             :   int32_t timeout;
   13198           0 :   bool isInterval = IsInterval(aTimeout, timeout);
   13199           0 :   return SetTimeoutOrInterval(aCx, aFunction, timeout, aArguments, isInterval,
   13200           0 :                               aError);
   13201             : }
   13202             : 
   13203             : int32_t
   13204           0 : nsGlobalWindow::SetInterval(JSContext* aCx, const nsAString& aHandler,
   13205             :                             const Optional<int32_t>& aTimeout,
   13206             :                             const Sequence<JS::Value>& /* unused */,
   13207             :                             ErrorResult& aError)
   13208             : {
   13209             :   int32_t timeout;
   13210           0 :   bool isInterval = IsInterval(aTimeout, timeout);
   13211           0 :   return SetTimeoutOrInterval(aCx, aHandler, timeout, isInterval, aError);
   13212             : }
   13213             : 
   13214             : int32_t
   13215          11 : nsGlobalWindow::SetTimeoutOrInterval(JSContext *aCx, Function& aFunction,
   13216             :                                      int32_t aTimeout,
   13217             :                                      const Sequence<JS::Value>& aArguments,
   13218             :                                      bool aIsInterval, ErrorResult& aError)
   13219             : {
   13220          11 :   nsGlobalWindow* inner = InnerForSetTimeoutOrInterval(aError);
   13221          11 :   if (!inner) {
   13222           0 :     return -1;
   13223             :   }
   13224             : 
   13225          11 :   if (inner != this) {
   13226           0 :     return inner->SetTimeoutOrInterval(aCx, aFunction, aTimeout, aArguments,
   13227           0 :                                        aIsInterval, aError);
   13228             :   }
   13229             : 
   13230             :   nsCOMPtr<nsIScriptTimeoutHandler> handler =
   13231          22 :     NS_CreateJSTimeoutHandler(aCx, this, aFunction, aArguments, aError);
   13232          11 :   if (!handler) {
   13233           0 :     return 0;
   13234             :   }
   13235             : 
   13236             :   int32_t result;
   13237          22 :   aError = mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
   13238             :                                       Timeout::Reason::eTimeoutOrInterval,
   13239          22 :                                       &result);
   13240          11 :   return result;
   13241             : }
   13242             : 
   13243             : int32_t
   13244           0 : nsGlobalWindow::SetTimeoutOrInterval(JSContext* aCx, const nsAString& aHandler,
   13245             :                                      int32_t aTimeout, bool aIsInterval,
   13246             :                                      ErrorResult& aError)
   13247             : {
   13248           0 :   nsGlobalWindow* inner = InnerForSetTimeoutOrInterval(aError);
   13249           0 :   if (!inner) {
   13250           0 :     return -1;
   13251             :   }
   13252             : 
   13253           0 :   if (inner != this) {
   13254           0 :     return inner->SetTimeoutOrInterval(aCx, aHandler, aTimeout, aIsInterval,
   13255           0 :                                        aError);
   13256             :   }
   13257             : 
   13258             :   nsCOMPtr<nsIScriptTimeoutHandler> handler =
   13259           0 :     NS_CreateJSTimeoutHandler(aCx, this, aHandler, aError);
   13260           0 :   if (!handler) {
   13261           0 :     return 0;
   13262             :   }
   13263             : 
   13264             :   int32_t result;
   13265           0 :   aError = mTimeoutManager->SetTimeout(handler, aTimeout, aIsInterval,
   13266             :                                       Timeout::Reason::eTimeoutOrInterval,
   13267           0 :                                       &result);
   13268           0 :   return result;
   13269             : }
   13270             : 
   13271             : bool
   13272           8 : nsGlobalWindow::RunTimeoutHandler(Timeout* aTimeout,
   13273             :                                   nsIScriptContext* aScx)
   13274             : {
   13275           8 :   MOZ_ASSERT(IsInnerWindow());
   13276             : 
   13277             :   // Hold on to the timeout in case mExpr or mFunObj releases its
   13278             :   // doc.
   13279          16 :   RefPtr<Timeout> timeout = aTimeout;
   13280           8 :   Timeout* last_running_timeout = mTimeoutManager->BeginRunningTimeout(timeout);
   13281           8 :   timeout->mRunning = true;
   13282             : 
   13283             :   // Push this timeout's popup control state, which should only be
   13284             :   // eabled the first time a timeout fires that was created while
   13285             :   // popups were enabled and with a delay less than
   13286             :   // "dom.disable_open_click_delay".
   13287          16 :   nsAutoPopupStatePusher popupStatePusher(timeout->mPopupState);
   13288             : 
   13289             :   // Clear the timeout's popup state, if any, to prevent interval
   13290             :   // timeouts from repeatedly opening poups.
   13291           8 :   timeout->mPopupState = openAbused;
   13292             : 
   13293           8 :   bool trackNestingLevel = !timeout->mIsInterval;
   13294             :   uint32_t nestingLevel;
   13295           8 :   if (trackNestingLevel) {
   13296           8 :     nestingLevel = TimeoutManager::GetNestingLevel();
   13297           8 :     TimeoutManager::SetNestingLevel(timeout->mNestingLevel);
   13298             :   }
   13299             : 
   13300             :   const char *reason;
   13301           8 :   if (timeout->mIsInterval) {
   13302           0 :     reason = "setInterval handler";
   13303             :   } else {
   13304           8 :     reason = "setTimeout handler";
   13305             :   }
   13306             : 
   13307           8 :   bool abortIntervalHandler = false;
   13308          16 :   nsCOMPtr<nsIScriptTimeoutHandler> handler(do_QueryInterface(timeout->mScriptHandler));
   13309           8 :   if (handler) {
   13310          14 :     RefPtr<Function> callback = handler->GetCallback();
   13311             : 
   13312           7 :     if (!callback) {
   13313             :       // Evaluate the timeout expression.
   13314           0 :       const nsAString& script = handler->GetHandlerText();
   13315             : 
   13316           0 :       const char* filename = nullptr;
   13317           0 :       uint32_t lineNo = 0, dummyColumn = 0;
   13318           0 :       handler->GetLocation(&filename, &lineNo, &dummyColumn);
   13319             : 
   13320             :       // New script entry point required, due to the "Create a script" sub-step of
   13321             :       // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps
   13322           0 :       nsAutoMicroTask mt;
   13323           0 :       AutoEntryScript aes(this, reason, true);
   13324           0 :       JS::CompileOptions options(aes.cx());
   13325           0 :       options.setFileAndLine(filename, lineNo).setVersion(JSVERSION_DEFAULT);
   13326           0 :       options.setNoScriptRval(true);
   13327           0 :       JS::Rooted<JSObject*> global(aes.cx(), FastGetGlobalJSObject());
   13328           0 :       nsresult rv = NS_OK;
   13329             :       {
   13330           0 :         nsJSUtils::ExecutionContext exec(aes.cx(), global);
   13331           0 :         rv = exec.CompileAndExec(options, script);
   13332             :       }
   13333             : 
   13334           0 :       if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) {
   13335           0 :         abortIntervalHandler = true;
   13336             :       }
   13337             :     } else {
   13338             :       // Hold strong ref to ourselves while we call the callback.
   13339          14 :       nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow*>(this));
   13340          14 :       ErrorResult rv;
   13341          14 :       JS::Rooted<JS::Value> ignoredVal(RootingCx());
   13342           7 :       callback->Call(me, handler->GetArgs(), &ignoredVal, rv, reason);
   13343           7 :       if (rv.IsUncatchableException()) {
   13344           0 :         abortIntervalHandler = true;
   13345             :       }
   13346             : 
   13347           7 :       rv.SuppressException();
   13348             :     }
   13349             :   } else {
   13350           2 :     nsCOMPtr<nsITimeoutHandler> basicHandler(timeout->mScriptHandler);
   13351           2 :     nsCOMPtr<nsISupports> kungFuDeathGrip(static_cast<nsIDOMWindow*>(this));
   13352             :     mozilla::Unused << kungFuDeathGrip;
   13353           1 :     basicHandler->Call();
   13354             :   }
   13355             : 
   13356             :   // If we received an uncatchable exception, do not schedule the timeout again.
   13357             :   // This allows the slow script dialog to break easy DoS attacks like
   13358             :   // setInterval(function() { while(1); }, 100);
   13359           8 :   if (abortIntervalHandler) {
   13360             :     // If it wasn't an interval timer to begin with, this does nothing.  If it
   13361             :     // was, we'll treat it as a timeout that we just ran and discard it when
   13362             :     // we return.
   13363           0 :     timeout->mIsInterval = false;
   13364             :    }
   13365             : 
   13366             :   // We ignore any failures from calling EvaluateString() on the context or
   13367             :   // Call() on a Function here since we're in a loop
   13368             :   // where we're likely to be running timeouts whose OS timers
   13369             :   // didn't fire in time and we don't want to not fire those timers
   13370             :   // now just because execution of one timer failed. We can't
   13371             :   // propagate the error to anyone who cares about it from this
   13372             :   // point anyway, and the script context should have already reported
   13373             :   // the script error in the usual way - so we just drop it.
   13374             : 
   13375             :   // Since we might be processing more timeouts, go ahead and flush the promise
   13376             :   // queue now before we do that.  We need to do that while we're still in our
   13377             :   // "running JS is safe" state (e.g. mRunningTimeout is set, timeout->mRunning
   13378             :   // is false).
   13379           8 :   Promise::PerformMicroTaskCheckpoint();
   13380             : 
   13381           8 :   if (trackNestingLevel) {
   13382           8 :     TimeoutManager::SetNestingLevel(nestingLevel);
   13383             :   }
   13384             : 
   13385           8 :   mTimeoutManager->EndRunningTimeout(last_running_timeout);
   13386           8 :   timeout->mRunning = false;
   13387             : 
   13388          16 :   return timeout->mCleared;
   13389             : }
   13390             : 
   13391             : //*****************************************************************************
   13392             : // nsGlobalWindow: Helper Functions
   13393             : //*****************************************************************************
   13394             : 
   13395             : already_AddRefed<nsIDocShellTreeOwner>
   13396          18 : nsGlobalWindow::GetTreeOwner()
   13397             : {
   13398          18 :   FORWARD_TO_OUTER(GetTreeOwner, (), nullptr);
   13399             : 
   13400             :   // If there's no docShellAsItem, this window must have been closed,
   13401             :   // in that case there is no tree owner.
   13402             : 
   13403          13 :   if (!mDocShell) {
   13404           0 :     return nullptr;
   13405             :   }
   13406             : 
   13407          26 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   13408          13 :   mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
   13409          13 :   return treeOwner.forget();
   13410             : }
   13411             : 
   13412             : already_AddRefed<nsIBaseWindow>
   13413          11 : nsGlobalWindow::GetTreeOwnerWindow()
   13414             : {
   13415          11 :   MOZ_ASSERT(IsOuterWindow());
   13416             : 
   13417          22 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   13418             : 
   13419             :   // If there's no mDocShell, this window must have been closed,
   13420             :   // in that case there is no tree owner.
   13421             : 
   13422          11 :   if (mDocShell) {
   13423          11 :     mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
   13424             :   }
   13425             : 
   13426          22 :   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(treeOwner);
   13427          22 :   return baseWindow.forget();
   13428             : }
   13429             : 
   13430             : already_AddRefed<nsIWebBrowserChrome>
   13431          13 : nsGlobalWindow::GetWebBrowserChrome()
   13432             : {
   13433          26 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner = GetTreeOwner();
   13434             : 
   13435          26 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome = do_GetInterface(treeOwner);
   13436          26 :   return browserChrome.forget();
   13437             : }
   13438             : 
   13439             : nsIScrollableFrame *
   13440           0 : nsGlobalWindow::GetScrollFrame()
   13441             : {
   13442           0 :   FORWARD_TO_OUTER(GetScrollFrame, (), nullptr);
   13443             : 
   13444           0 :   if (!mDocShell) {
   13445           0 :     return nullptr;
   13446             :   }
   13447             : 
   13448           0 :   nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   13449           0 :   if (presShell) {
   13450           0 :     return presShell->GetRootScrollFrameAsScrollable();
   13451             :   }
   13452           0 :   return nullptr;
   13453             : }
   13454             : 
   13455             : nsresult
   13456           0 : nsGlobalWindow::SecurityCheckURL(const char *aURL)
   13457             : {
   13458           0 :   nsCOMPtr<nsPIDOMWindowInner> sourceWindow = do_QueryInterface(GetEntryGlobal());
   13459           0 :   if (!sourceWindow) {
   13460           0 :     sourceWindow = AsOuter()->GetCurrentInnerWindow();
   13461             :   }
   13462           0 :   AutoJSContext cx;
   13463           0 :   nsGlobalWindow* sourceWin = nsGlobalWindow::Cast(sourceWindow);
   13464           0 :   JSAutoCompartment ac(cx, sourceWin->GetGlobalJSObject());
   13465             : 
   13466             :   // Resolve the baseURI, which could be relative to the calling window.
   13467             :   //
   13468             :   // Note the algorithm to get the base URI should match the one
   13469             :   // used to actually kick off the load in nsWindowWatcher.cpp.
   13470           0 :   nsCOMPtr<nsIDocument> doc = sourceWindow->GetDoc();
   13471           0 :   nsIURI* baseURI = nullptr;
   13472           0 :   auto encoding = UTF_8_ENCODING; // default to utf-8
   13473           0 :   if (doc) {
   13474           0 :     baseURI = doc->GetDocBaseURI();
   13475           0 :     encoding = doc->GetDocumentCharacterSet();
   13476             :   }
   13477           0 :   nsCOMPtr<nsIURI> uri;
   13478           0 :   nsresult rv = NS_NewURI(getter_AddRefs(uri), nsDependentCString(aURL),
   13479           0 :                           encoding, baseURI);
   13480           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
   13481           0 :     return rv;
   13482             :   }
   13483             : 
   13484           0 :   if (NS_FAILED(nsContentUtils::GetSecurityManager()->
   13485             :         CheckLoadURIFromScript(cx, uri))) {
   13486           0 :     return NS_ERROR_FAILURE;
   13487             :   }
   13488             : 
   13489           0 :   return NS_OK;
   13490             : }
   13491             : 
   13492             : bool
   13493           0 : nsGlobalWindow::IsPrivateBrowsing()
   13494             : {
   13495           0 :   nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(GetDocShell());
   13496           0 :   return loadContext && loadContext->UsePrivateBrowsing();
   13497             : }
   13498             : 
   13499             : void
   13500           8 : nsGlobalWindow::FlushPendingNotifications(FlushType aType)
   13501             : {
   13502           8 :   if (mDoc) {
   13503           8 :     mDoc->FlushPendingNotifications(aType);
   13504             :   }
   13505           8 : }
   13506             : 
   13507             : void
   13508          18 : nsGlobalWindow::EnsureSizeAndPositionUpToDate()
   13509             : {
   13510          18 :   MOZ_ASSERT(IsOuterWindow());
   13511             : 
   13512             :   // If we're a subframe, make sure our size is up to date.  It's OK that this
   13513             :   // crosses the content/chrome boundary, since chrome can have pending reflows
   13514             :   // too.
   13515          18 :   nsGlobalWindow *parent = nsGlobalWindow::Cast(GetPrivateParent());
   13516          18 :   if (parent) {
   13517           0 :     parent->FlushPendingNotifications(FlushType::Layout);
   13518             :   }
   13519          18 : }
   13520             : 
   13521             : already_AddRefed<nsISupports>
   13522           0 : nsGlobalWindow::SaveWindowState()
   13523             : {
   13524           0 :   NS_PRECONDITION(IsOuterWindow(), "Can't save the inner window's state");
   13525             : 
   13526           0 :   if (!mContext || !GetWrapperPreserveColor()) {
   13527             :     // The window may be getting torn down; don't bother saving state.
   13528           0 :     return nullptr;
   13529             :   }
   13530             : 
   13531           0 :   nsGlobalWindow *inner = GetCurrentInnerWindowInternal();
   13532           0 :   NS_ASSERTION(inner, "No inner window to save");
   13533             : 
   13534             :   // Don't do anything else to this inner window! After this point, all
   13535             :   // calls to SetTimeoutOrInterval will create entries in the timeout
   13536             :   // list that will only run after this window has come out of the bfcache.
   13537             :   // Also, while we're frozen, we won't dispatch online/offline events
   13538             :   // to the page.
   13539           0 :   inner->Freeze();
   13540             : 
   13541           0 :   nsCOMPtr<nsISupports> state = new WindowStateHolder(inner);
   13542             : 
   13543             : #ifdef DEBUG_PAGE_CACHE
   13544             :   printf("saving window state, state = %p\n", (void*)state);
   13545             : #endif
   13546             : 
   13547           0 :   return state.forget();
   13548             : }
   13549             : 
   13550             : nsresult
   13551           0 : nsGlobalWindow::RestoreWindowState(nsISupports *aState)
   13552             : {
   13553           0 :   NS_ASSERTION(IsOuterWindow(), "Cannot restore an inner window");
   13554             : 
   13555           0 :   if (!mContext || !GetWrapperPreserveColor()) {
   13556             :     // The window may be getting torn down; don't bother restoring state.
   13557           0 :     return NS_OK;
   13558             :   }
   13559             : 
   13560           0 :   nsCOMPtr<WindowStateHolder> holder = do_QueryInterface(aState);
   13561           0 :   NS_ENSURE_TRUE(holder, NS_ERROR_FAILURE);
   13562             : 
   13563             : #ifdef DEBUG_PAGE_CACHE
   13564             :   printf("restoring window state, state = %p\n", (void*)holder);
   13565             : #endif
   13566             : 
   13567             :   // And we're ready to go!
   13568           0 :   nsGlobalWindow *inner = GetCurrentInnerWindowInternal();
   13569             : 
   13570             :   // if a link is focused, refocus with the FLAG_SHOWRING flag set. This makes
   13571             :   // it easy to tell which link was last clicked when going back a page.
   13572           0 :   nsIContent* focusedNode = inner->GetFocusedNode();
   13573           0 :   if (IsLink(focusedNode)) {
   13574           0 :     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   13575           0 :     if (fm) {
   13576           0 :       nsCOMPtr<nsIDOMElement> focusedElement(do_QueryInterface(focusedNode));
   13577           0 :       fm->SetFocus(focusedElement, nsIFocusManager::FLAG_NOSCROLL |
   13578           0 :                                    nsIFocusManager::FLAG_SHOWRING);
   13579             :     }
   13580             :   }
   13581             : 
   13582           0 :   inner->Thaw();
   13583             : 
   13584           0 :   holder->DidRestoreWindow();
   13585             : 
   13586           0 :   return NS_OK;
   13587             : }
   13588             : 
   13589             : void
   13590           0 : nsGlobalWindow::EnableDeviceSensor(uint32_t aType)
   13591             : {
   13592           0 :   MOZ_ASSERT(IsInnerWindow());
   13593             : 
   13594           0 :   bool alreadyEnabled = false;
   13595           0 :   for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
   13596           0 :     if (mEnabledSensors[i] == aType) {
   13597           0 :       alreadyEnabled = true;
   13598           0 :       break;
   13599             :     }
   13600             :   }
   13601             : 
   13602           0 :   mEnabledSensors.AppendElement(aType);
   13603             : 
   13604           0 :   if (alreadyEnabled) {
   13605           0 :     return;
   13606             :   }
   13607             : 
   13608           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
   13609           0 :   if (ac) {
   13610           0 :     ac->AddWindowListener(aType, this);
   13611             :   }
   13612             : }
   13613             : 
   13614             : void
   13615           0 : nsGlobalWindow::DisableDeviceSensor(uint32_t aType)
   13616             : {
   13617           0 :   MOZ_ASSERT(IsInnerWindow());
   13618             : 
   13619           0 :   int32_t doomedElement = -1;
   13620           0 :   int32_t listenerCount = 0;
   13621           0 :   for (uint32_t i = 0; i < mEnabledSensors.Length(); i++) {
   13622           0 :     if (mEnabledSensors[i] == aType) {
   13623           0 :       doomedElement = i;
   13624           0 :       listenerCount++;
   13625             :     }
   13626             :   }
   13627             : 
   13628           0 :   if (doomedElement == -1) {
   13629           0 :     return;
   13630             :   }
   13631             : 
   13632           0 :   mEnabledSensors.RemoveElementAt(doomedElement);
   13633             : 
   13634           0 :   if (listenerCount > 1) {
   13635           0 :     return;
   13636             :   }
   13637             : 
   13638           0 :   nsCOMPtr<nsIDeviceSensors> ac = do_GetService(NS_DEVICE_SENSORS_CONTRACTID);
   13639           0 :   if (ac) {
   13640           0 :     ac->RemoveWindowListener(aType, this);
   13641             :   }
   13642             : }
   13643             : 
   13644             : #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
   13645             : void
   13646             : nsGlobalWindow::EnableOrientationChangeListener()
   13647             : {
   13648             :   MOZ_ASSERT(IsInnerWindow());
   13649             :   if (!nsContentUtils::ShouldResistFingerprinting(mDocShell) &&
   13650             :       !mOrientationChangeObserver) {
   13651             :     mOrientationChangeObserver =
   13652             :       new WindowOrientationObserver(this);
   13653             :   }
   13654             : }
   13655             : 
   13656             : void
   13657             : nsGlobalWindow::DisableOrientationChangeListener()
   13658             : {
   13659             :   MOZ_ASSERT(IsInnerWindow());
   13660             : 
   13661             :   mOrientationChangeObserver = nullptr;
   13662             : }
   13663             : #endif
   13664             : 
   13665             : void
   13666           0 : nsGlobalWindow::SetHasGamepadEventListener(bool aHasGamepad/* = true*/)
   13667             : {
   13668           0 :   MOZ_ASSERT(IsInnerWindow());
   13669           0 :   mHasGamepad = aHasGamepad;
   13670           0 :   if (aHasGamepad) {
   13671           0 :     EnableGamepadUpdates();
   13672             :   }
   13673           0 : }
   13674             : 
   13675             : 
   13676             : void
   13677          52 : nsGlobalWindow::EventListenerAdded(nsIAtom* aType)
   13678             : {
   13679         104 :   if (aType == nsGkAtoms::onvrdisplayactivate ||
   13680         104 :       aType == nsGkAtoms::onvrdisplayconnect ||
   13681         104 :       aType == nsGkAtoms::onvrdisplaydeactivate ||
   13682         104 :       aType == nsGkAtoms::onvrdisplaydisconnect ||
   13683          52 :       aType == nsGkAtoms::onvrdisplaypresentchange) {
   13684           0 :     NotifyVREventListenerAdded();
   13685             :   }
   13686             : 
   13687          52 :   if (aType == nsGkAtoms::onvrdisplayactivate) {
   13688           0 :     mHasVRDisplayActivateEvents = true;
   13689             :   }
   13690             : 
   13691         104 :   if (aType == nsGkAtoms::onbeforeunload &&
   13692          52 :       mTabChild &&
   13693           0 :       (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
   13694           0 :     MOZ_ASSERT(IsInnerWindow());
   13695           0 :     mBeforeUnloadListenerCount++;
   13696           0 :     MOZ_ASSERT(mBeforeUnloadListenerCount > 0);
   13697           0 :     mTabChild->BeforeUnloadAdded();
   13698             :   }
   13699             : 
   13700             :   // We need to initialize localStorage in order to receive notifications.
   13701          52 :   if (aType == nsGkAtoms::onstorage) {
   13702           0 :     ErrorResult rv;
   13703           0 :     GetLocalStorage(rv);
   13704           0 :     rv.SuppressException();
   13705             :   }
   13706          52 : }
   13707             : 
   13708             : void
   13709           4 : nsGlobalWindow::EventListenerRemoved(nsIAtom* aType)
   13710             : {
   13711           8 :   if (aType == nsGkAtoms::onbeforeunload &&
   13712           4 :       mTabChild &&
   13713           0 :       (!mDoc || !(mDoc->GetSandboxFlags() & SANDBOXED_MODALS))) {
   13714           0 :     MOZ_ASSERT(IsInnerWindow());
   13715           0 :     mBeforeUnloadListenerCount--;
   13716           0 :     MOZ_ASSERT(mBeforeUnloadListenerCount >= 0);
   13717           0 :     mTabChild->BeforeUnloadRemoved();
   13718             :   }
   13719           4 : }
   13720             : 
   13721             : void
   13722           0 : nsGlobalWindow::NotifyVREventListenerAdded()
   13723             : {
   13724           0 :   MOZ_ASSERT(IsInnerWindow());
   13725           0 :   mHasVREvents = true;
   13726           0 :   EnableVRUpdates();
   13727           0 : }
   13728             : 
   13729             : bool
   13730           0 : nsGlobalWindow::HasUsedVR() const
   13731             : {
   13732           0 :   MOZ_ASSERT(IsInnerWindow());
   13733             : 
   13734             :   // Returns true only if any WebVR API call or related event
   13735             :   // has been used
   13736           0 :   return mHasVREvents;
   13737             : }
   13738             : 
   13739             : bool
   13740           0 : nsGlobalWindow::IsVRContentDetected() const
   13741             : {
   13742           0 :   MOZ_ASSERT(IsInnerWindow());
   13743             : 
   13744             :   // Returns true only if the content will respond to
   13745             :   // the VRDisplayActivate event.
   13746           0 :   return mHasVRDisplayActivateEvents;
   13747             : }
   13748             : 
   13749             : bool
   13750           0 : nsGlobalWindow::IsVRContentPresenting() const
   13751             : {
   13752           0 :   for (const auto& display : mVRDisplays) {
   13753           0 :     if (display->IsAnyPresenting(gfx::kVRGroupAll)) {
   13754           0 :       return true;
   13755             :     }
   13756             :   }
   13757           0 :   return false;
   13758             : }
   13759             : 
   13760             : void
   13761           0 : nsGlobalWindow::EnableTimeChangeNotifications()
   13762             : {
   13763           0 :   mozilla::time::AddWindowListener(AsInner());
   13764           0 : }
   13765             : 
   13766             : void
   13767           0 : nsGlobalWindow::DisableTimeChangeNotifications()
   13768             : {
   13769           0 :   mozilla::time::RemoveWindowListener(AsInner());
   13770           0 : }
   13771             : 
   13772             : void
   13773           0 : nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
   13774             : {
   13775           0 :   aWindowSizes->mDOMOtherSize += aWindowSizes->mMallocSizeOf(this);
   13776             : 
   13777           0 :   if (IsInnerWindow()) {
   13778           0 :     EventListenerManager* elm = GetExistingListenerManager();
   13779           0 :     if (elm) {
   13780           0 :       aWindowSizes->mDOMOtherSize +=
   13781           0 :         elm->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
   13782           0 :       aWindowSizes->mDOMEventListenersCount +=
   13783           0 :         elm->ListenerCount();
   13784             :     }
   13785           0 :     if (mDoc) {
   13786             :       // Multiple global windows can share a document. So only measure the
   13787             :       // document if it (a) doesn't have a global window, or (b) it's the
   13788             :       // primary document for the window.
   13789           0 :       if (!mDoc->GetInnerWindow() ||
   13790           0 :           mDoc->GetInnerWindow() == AsInner()) {
   13791           0 :         mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
   13792             :       }
   13793             :     }
   13794             :   }
   13795             : 
   13796           0 :   if (mNavigator) {
   13797           0 :     aWindowSizes->mDOMOtherSize +=
   13798           0 :       mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
   13799             :   }
   13800             : 
   13801           0 :   aWindowSizes->mDOMEventTargetsSize +=
   13802           0 :     mEventTargetObjects.ShallowSizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
   13803             : 
   13804           0 :   for (auto iter = mEventTargetObjects.ConstIter(); !iter.Done(); iter.Next()) {
   13805           0 :     DOMEventTargetHelper* et = iter.Get()->GetKey();
   13806           0 :     if (nsCOMPtr<nsISizeOfEventTarget> iSizeOf = do_QueryObject(et)) {
   13807           0 :       aWindowSizes->mDOMEventTargetsSize +=
   13808           0 :         iSizeOf->SizeOfEventTargetIncludingThis(aWindowSizes->mMallocSizeOf);
   13809             :     }
   13810           0 :     if (EventListenerManager* elm = et->GetExistingListenerManager()) {
   13811           0 :       aWindowSizes->mDOMEventListenersCount += elm->ListenerCount();
   13812             :     }
   13813           0 :     ++aWindowSizes->mDOMEventTargetsCount;
   13814             :   }
   13815           0 : }
   13816             : 
   13817             : void
   13818           0 : nsGlobalWindow::AddGamepad(uint32_t aIndex, Gamepad* aGamepad)
   13819             : {
   13820           0 :   MOZ_ASSERT(IsInnerWindow());
   13821             :   // Create the index we will present to content based on which indices are
   13822             :   // already taken, as required by the spec.
   13823             :   // https://w3c.github.io/gamepad/gamepad.html#widl-Gamepad-index
   13824           0 :   int index = 0;
   13825           0 :   while(mGamepadIndexSet.Contains(index)) {
   13826           0 :     ++index;
   13827             :   }
   13828           0 :   mGamepadIndexSet.Put(index);
   13829           0 :   aGamepad->SetIndex(index);
   13830           0 :   mGamepads.Put(aIndex, aGamepad);
   13831           0 : }
   13832             : 
   13833             : void
   13834           0 : nsGlobalWindow::RemoveGamepad(uint32_t aIndex)
   13835             : {
   13836           0 :   MOZ_ASSERT(IsInnerWindow());
   13837           0 :   RefPtr<Gamepad> gamepad;
   13838           0 :   if (!mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
   13839           0 :     return;
   13840             :   }
   13841             :   // Free up the index we were using so it can be reused
   13842           0 :   mGamepadIndexSet.Remove(gamepad->Index());
   13843           0 :   mGamepads.Remove(aIndex);
   13844             : }
   13845             : 
   13846             : void
   13847           0 : nsGlobalWindow::GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads)
   13848             : {
   13849           0 :   MOZ_ASSERT(IsInnerWindow());
   13850           0 :   aGamepads.Clear();
   13851             : 
   13852             :   // navigator.getGamepads() always returns an empty array when
   13853             :   // privacy.resistFingerprinting is true.
   13854           0 :   if (nsContentUtils::ShouldResistFingerprinting()) {
   13855           0 :     return;
   13856             :   }
   13857             : 
   13858             :   // mGamepads.Count() may not be sufficient, but it's not harmful.
   13859           0 :   aGamepads.SetCapacity(mGamepads.Count());
   13860           0 :   for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
   13861           0 :     Gamepad* gamepad = iter.UserData();
   13862           0 :     aGamepads.EnsureLengthAtLeast(gamepad->Index() + 1);
   13863           0 :     aGamepads[gamepad->Index()] = gamepad;
   13864             :   }
   13865             : }
   13866             : 
   13867             : already_AddRefed<Gamepad>
   13868           0 : nsGlobalWindow::GetGamepad(uint32_t aIndex)
   13869             : {
   13870           0 :   MOZ_ASSERT(IsInnerWindow());
   13871           0 :   RefPtr<Gamepad> gamepad;
   13872             : 
   13873           0 :   if (mGamepads.Get(aIndex, getter_AddRefs(gamepad))) {
   13874           0 :     return gamepad.forget();
   13875             :   }
   13876             : 
   13877           0 :   return nullptr;
   13878             : }
   13879             : 
   13880             : void
   13881           0 : nsGlobalWindow::SetHasSeenGamepadInput(bool aHasSeen)
   13882             : {
   13883           0 :   MOZ_ASSERT(IsInnerWindow());
   13884           0 :   mHasSeenGamepadInput = aHasSeen;
   13885           0 : }
   13886             : 
   13887             : bool
   13888           0 : nsGlobalWindow::HasSeenGamepadInput()
   13889             : {
   13890           0 :   MOZ_ASSERT(IsInnerWindow());
   13891           0 :   return mHasSeenGamepadInput;
   13892             : }
   13893             : 
   13894             : void
   13895           0 : nsGlobalWindow::SyncGamepadState()
   13896             : {
   13897           0 :   MOZ_ASSERT(IsInnerWindow());
   13898           0 :   if (mHasSeenGamepadInput) {
   13899           0 :     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
   13900           0 :     for (auto iter = mGamepads.Iter(); !iter.Done(); iter.Next()) {
   13901           0 :       gamepadManager->SyncGamepadState(iter.Key(), iter.UserData());
   13902             :     }
   13903             :   }
   13904           0 : }
   13905             : 
   13906             : void
   13907           0 : nsGlobalWindow::StopGamepadHaptics()
   13908             : {
   13909           0 :   MOZ_ASSERT(IsInnerWindow());
   13910           0 :   if (mHasSeenGamepadInput) {
   13911           0 :     RefPtr<GamepadManager> gamepadManager(GamepadManager::GetService());
   13912           0 :     gamepadManager->StopHaptics();
   13913             :   }
   13914           0 : }
   13915             : 
   13916             : bool
   13917           0 : nsGlobalWindow::UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDevices)
   13918             : {
   13919           0 :   FORWARD_TO_INNER(UpdateVRDisplays, (aDevices), false);
   13920             : 
   13921           0 :   VRDisplay::UpdateVRDisplays(mVRDisplays, AsInner());
   13922           0 :   aDevices = mVRDisplays;
   13923           0 :   return true;
   13924             : }
   13925             : 
   13926             : void
   13927           0 : nsGlobalWindow::NotifyActiveVRDisplaysChanged()
   13928             : {
   13929           0 :   MOZ_ASSERT(IsInnerWindow());
   13930             : 
   13931           0 :   if (mNavigator) {
   13932           0 :     mNavigator->NotifyActiveVRDisplaysChanged();
   13933             :   }
   13934           0 : }
   13935             : 
   13936             : uint32_t
   13937           4 : nsGlobalWindow::GetAutoActivateVRDisplayID()
   13938             : {
   13939           4 :   MOZ_ASSERT(IsOuterWindow());
   13940           4 :   uint32_t retVal = mAutoActivateVRDisplayID;
   13941           4 :   mAutoActivateVRDisplayID = 0;
   13942           4 :   return retVal;
   13943             : }
   13944             : 
   13945             : void
   13946           0 : nsGlobalWindow::SetAutoActivateVRDisplayID(uint32_t aAutoActivateVRDisplayID)
   13947             : {
   13948           0 :   MOZ_ASSERT(IsOuterWindow());
   13949           0 :   mAutoActivateVRDisplayID = aAutoActivateVRDisplayID;
   13950           0 : }
   13951             : 
   13952             : void
   13953           0 : nsGlobalWindow::DispatchVRDisplayActivate(uint32_t aDisplayID,
   13954             :                                           mozilla::dom::VRDisplayEventReason aReason)
   13955             : {
   13956             :   // Search for the display identified with aDisplayID and fire the
   13957             :   // event if found.
   13958           0 :   for (const auto& display : mVRDisplays) {
   13959           0 :     if (display->DisplayId() == aDisplayID) {
   13960           0 :       if (aReason != VRDisplayEventReason::Navigation &&
   13961           0 :           display->IsAnyPresenting(gfx::kVRGroupContent)) {
   13962             :         // We only want to trigger this event if nobody is presenting to the
   13963             :         // display already or when a page is loaded by navigating away
   13964             :         // from a page with an active VR Presentation.
   13965           0 :         continue;
   13966             :       }
   13967             : 
   13968           0 :       VRDisplayEventInit init;
   13969           0 :       init.mBubbles = false;
   13970           0 :       init.mCancelable = false;
   13971           0 :       init.mDisplay = display;
   13972           0 :       init.mReason.Construct(aReason);
   13973             : 
   13974             :       RefPtr<VRDisplayEvent> event =
   13975           0 :         VRDisplayEvent::Constructor(this,
   13976           0 :                                     NS_LITERAL_STRING("vrdisplayactivate"),
   13977           0 :                                     init);
   13978             :       // vrdisplayactivate is a trusted event, allowing VRDisplay.requestPresent
   13979             :       // to be used in response to link traversal, user request (chrome UX), and
   13980             :       // HMD mounting detection sensors.
   13981           0 :       event->SetTrusted(true);
   13982             :       bool defaultActionEnabled;
   13983             :       // VRDisplay.requestPresent normally requires a user gesture; however, an
   13984             :       // exception is made to allow it to be called in response to vrdisplayactivate
   13985             :       // during VR link traversal.
   13986           0 :       display->StartHandlingVRNavigationEvent();
   13987           0 :       Unused << DispatchEvent(event, &defaultActionEnabled);
   13988           0 :       display->StopHandlingVRNavigationEvent();
   13989             :       // Once we dispatch the event, we must not access any members as an event
   13990             :       // listener can do anything, including closing windows.
   13991           0 :       return;
   13992             :     }
   13993             :   }
   13994             : }
   13995             : 
   13996             : void
   13997           0 : nsGlobalWindow::DispatchVRDisplayDeactivate(uint32_t aDisplayID,
   13998             :                                             mozilla::dom::VRDisplayEventReason aReason)
   13999             : {
   14000             :   // Search for the display identified with aDisplayID and fire the
   14001             :   // event if found.
   14002           0 :   for (const auto& display : mVRDisplays) {
   14003           0 :     if (display->DisplayId() == aDisplayID && display->IsPresenting()) {
   14004             :       // We only want to trigger this event to content that is presenting to
   14005             :       // the display already.
   14006             : 
   14007           0 :       VRDisplayEventInit init;
   14008           0 :       init.mBubbles = false;
   14009           0 :       init.mCancelable = false;
   14010           0 :       init.mDisplay = display;
   14011           0 :       init.mReason.Construct(aReason);
   14012             : 
   14013             :       RefPtr<VRDisplayEvent> event =
   14014           0 :         VRDisplayEvent::Constructor(this,
   14015           0 :                                     NS_LITERAL_STRING("vrdisplaydeactivate"),
   14016           0 :                                     init);
   14017           0 :       event->SetTrusted(true);
   14018             :       bool defaultActionEnabled;
   14019           0 :       Unused << DispatchEvent(event, &defaultActionEnabled);
   14020             :       // Once we dispatch the event, we must not access any members as an event
   14021             :       // listener can do anything, including closing windows.
   14022           0 :       return;
   14023             :     }
   14024             :   }
   14025             : }
   14026             : 
   14027             : void
   14028           0 : nsGlobalWindow::DispatchVRDisplayConnect(uint32_t aDisplayID)
   14029             : {
   14030             :   // Search for the display identified with aDisplayID and fire the
   14031             :   // event if found.
   14032           0 :   for (const auto& display : mVRDisplays) {
   14033           0 :     if (display->DisplayId() == aDisplayID) {
   14034             :       // Fire event even if not presenting to the display.
   14035           0 :       VRDisplayEventInit init;
   14036           0 :       init.mBubbles = false;
   14037           0 :       init.mCancelable = false;
   14038           0 :       init.mDisplay = display;
   14039             :       // VRDisplayEvent.reason is not set for vrdisplayconnect
   14040             : 
   14041             :       RefPtr<VRDisplayEvent> event =
   14042           0 :         VRDisplayEvent::Constructor(this,
   14043           0 :                                     NS_LITERAL_STRING("vrdisplayconnect"),
   14044           0 :                                     init);
   14045           0 :       event->SetTrusted(true);
   14046             :       bool defaultActionEnabled;
   14047           0 :       Unused << DispatchEvent(event, &defaultActionEnabled);
   14048             :       // Once we dispatch the event, we must not access any members as an event
   14049             :       // listener can do anything, including closing windows.
   14050           0 :       return;
   14051             :     }
   14052             :   }
   14053             : }
   14054             : 
   14055             : void
   14056           0 : nsGlobalWindow::DispatchVRDisplayDisconnect(uint32_t aDisplayID)
   14057             : {
   14058             :   // Search for the display identified with aDisplayID and fire the
   14059             :   // event if found.
   14060           0 :   for (const auto& display : mVRDisplays) {
   14061           0 :     if (display->DisplayId() == aDisplayID) {
   14062             :       // Fire event even if not presenting to the display.
   14063           0 :       VRDisplayEventInit init;
   14064           0 :       init.mBubbles = false;
   14065           0 :       init.mCancelable = false;
   14066           0 :       init.mDisplay = display;
   14067             :       // VRDisplayEvent.reason is not set for vrdisplaydisconnect
   14068             : 
   14069             :       RefPtr<VRDisplayEvent> event =
   14070           0 :         VRDisplayEvent::Constructor(this,
   14071           0 :                                     NS_LITERAL_STRING("vrdisplaydisconnect"),
   14072           0 :                                     init);
   14073           0 :       event->SetTrusted(true);
   14074             :       bool defaultActionEnabled;
   14075           0 :       Unused << DispatchEvent(event, &defaultActionEnabled);
   14076             :       // Once we dispatch the event, we must not access any members as an event
   14077             :       // listener can do anything, including closing windows.
   14078           0 :       return;
   14079             :     }
   14080             :   }
   14081             : }
   14082             : 
   14083             : void
   14084           0 : nsGlobalWindow::DispatchVRDisplayPresentChange(uint32_t aDisplayID)
   14085             : {
   14086             :   // Search for the display identified with aDisplayID and fire the
   14087             :   // event if found.
   14088           0 :   for (const auto& display : mVRDisplays) {
   14089           0 :     if (display->DisplayId() == aDisplayID) {
   14090             :       // Fire event even if not presenting to the display.
   14091           0 :       VRDisplayEventInit init;
   14092           0 :       init.mBubbles = false;
   14093           0 :       init.mCancelable = false;
   14094           0 :       init.mDisplay = display;
   14095             :       // VRDisplayEvent.reason is not set for vrdisplaypresentchange
   14096             :       RefPtr<VRDisplayEvent> event =
   14097           0 :         VRDisplayEvent::Constructor(this,
   14098           0 :                                     NS_LITERAL_STRING("vrdisplaypresentchange"),
   14099           0 :                                     init);
   14100           0 :       event->SetTrusted(true);
   14101             :       bool defaultActionEnabled;
   14102           0 :       Unused << DispatchEvent(event, &defaultActionEnabled);
   14103             :       // Once we dispatch the event, we must not access any members as an event
   14104             :       // listener can do anything, including closing windows.
   14105           0 :       return;
   14106             :     }
   14107             :   }
   14108             : }
   14109             : 
   14110             : // nsGlobalChromeWindow implementation
   14111             : 
   14112             : NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
   14113             : 
   14114           1 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
   14115             :                                                   nsGlobalWindow)
   14116           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserDOMWindow)
   14117           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
   14118           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGroupMessageManagers)
   14119           1 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerForInitialContentBrowser)
   14120           1 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   14121             : 
   14122             : 
   14123           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow,
   14124             :                                                 nsGlobalWindow)
   14125           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserDOMWindow)
   14126           0 :   if (tmp->mMessageManager) {
   14127             :     static_cast<nsFrameMessageManager*>(
   14128           0 :       tmp->mMessageManager.get())->Disconnect();
   14129           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
   14130             :   }
   14131           0 :   tmp->DisconnectAndClearGroupMessageManagers();
   14132           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroupMessageManagers)
   14133           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerForInitialContentBrowser)
   14134           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   14135             : 
   14136             : // QueryInterface implementation for nsGlobalChromeWindow
   14137       12275 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalChromeWindow)
   14138       12262 :   NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow)
   14139       12235 : NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
   14140             : 
   14141       16881 : NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow, nsGlobalWindow)
   14142       16677 : NS_IMPL_RELEASE_INHERITED(nsGlobalChromeWindow, nsGlobalWindow)
   14143             : 
   14144             : /* static */ already_AddRefed<nsGlobalChromeWindow>
   14145           7 : nsGlobalChromeWindow::Create(nsGlobalWindow *aOuterWindow)
   14146             : {
   14147          14 :   RefPtr<nsGlobalChromeWindow> window = new nsGlobalChromeWindow(aOuterWindow);
   14148           7 :   window->InitWasOffline();
   14149          14 :   return window.forget();
   14150             : }
   14151             : 
   14152             : NS_IMETHODIMP
   14153           0 : nsGlobalChromeWindow::GetWindowState(uint16_t* aWindowState)
   14154             : {
   14155           0 :   FORWARD_TO_INNER_CHROME(GetWindowState, (aWindowState), NS_ERROR_UNEXPECTED);
   14156             : 
   14157           0 :   *aWindowState = WindowState();
   14158           0 :   return NS_OK;
   14159             : }
   14160             : 
   14161             : uint16_t
   14162           4 : nsGlobalWindow::WindowState()
   14163             : {
   14164           4 :   MOZ_ASSERT(IsInnerWindow());
   14165           8 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   14166             : 
   14167           4 :   int32_t mode = widget ? widget->SizeMode() : 0;
   14168             : 
   14169           4 :   switch (mode) {
   14170             :     case nsSizeMode_Minimized:
   14171           0 :       return nsIDOMChromeWindow::STATE_MINIMIZED;
   14172             :     case nsSizeMode_Maximized:
   14173           3 :       return nsIDOMChromeWindow::STATE_MAXIMIZED;
   14174             :     case nsSizeMode_Fullscreen:
   14175           0 :       return nsIDOMChromeWindow::STATE_FULLSCREEN;
   14176             :     case nsSizeMode_Normal:
   14177           1 :       return nsIDOMChromeWindow::STATE_NORMAL;
   14178             :     default:
   14179           0 :       NS_WARNING("Illegal window state for this chrome window");
   14180           0 :       break;
   14181             :   }
   14182             : 
   14183           0 :   return nsIDOMChromeWindow::STATE_NORMAL;
   14184             : }
   14185             : 
   14186             : bool
   14187           3 : nsGlobalWindow::IsFullyOccluded()
   14188             : {
   14189           3 :   MOZ_ASSERT(IsInnerWindow());
   14190             : 
   14191           6 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   14192           6 :   return widget && widget->IsFullyOccluded();
   14193             : }
   14194             : 
   14195             : NS_IMETHODIMP
   14196           0 : nsGlobalChromeWindow::Maximize()
   14197             : {
   14198           0 :   FORWARD_TO_INNER_CHROME(Maximize, (), NS_ERROR_UNEXPECTED);
   14199             : 
   14200           0 :   nsGlobalWindow::Maximize();
   14201           0 :   return NS_OK;
   14202             : }
   14203             : 
   14204             : void
   14205           0 : nsGlobalWindow::Maximize()
   14206             : {
   14207           0 :   MOZ_ASSERT(IsInnerWindow());
   14208             : 
   14209           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   14210             : 
   14211           0 :   if (widget) {
   14212           0 :     widget->SetSizeMode(nsSizeMode_Maximized);
   14213             :   }
   14214           0 : }
   14215             : 
   14216             : NS_IMETHODIMP
   14217           0 : nsGlobalChromeWindow::Minimize()
   14218             : {
   14219           0 :   FORWARD_TO_INNER_CHROME(Minimize, (), NS_ERROR_UNEXPECTED);
   14220             : 
   14221           0 :   nsGlobalWindow::Minimize();
   14222           0 :   return NS_OK;
   14223             : }
   14224             : 
   14225             : void
   14226           0 : nsGlobalWindow::Minimize()
   14227             : {
   14228           0 :   MOZ_ASSERT(IsInnerWindow());
   14229             : 
   14230           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   14231             : 
   14232           0 :   if (widget) {
   14233           0 :     widget->SetSizeMode(nsSizeMode_Minimized);
   14234             :   }
   14235           0 : }
   14236             : 
   14237             : NS_IMETHODIMP
   14238           0 : nsGlobalChromeWindow::Restore()
   14239             : {
   14240           0 :   FORWARD_TO_INNER_CHROME(Restore, (), NS_ERROR_UNEXPECTED);
   14241             : 
   14242           0 :   nsGlobalWindow::Restore();
   14243           0 :   return NS_OK;
   14244             : }
   14245             : 
   14246             : void
   14247           0 : nsGlobalWindow::Restore()
   14248             : {
   14249           0 :   MOZ_ASSERT(IsInnerWindow());
   14250             : 
   14251           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   14252             : 
   14253           0 :   if (widget) {
   14254           0 :     widget->SetSizeMode(nsSizeMode_Normal);
   14255             :   }
   14256           0 : }
   14257             : 
   14258             : NS_IMETHODIMP
   14259           0 : nsGlobalChromeWindow::GetAttention()
   14260             : {
   14261           0 :   FORWARD_TO_INNER_CHROME(GetAttention, (), NS_ERROR_UNEXPECTED);
   14262             : 
   14263           0 :   ErrorResult rv;
   14264           0 :   GetAttention(rv);
   14265           0 :   return rv.StealNSResult();
   14266             : }
   14267             : 
   14268             : void
   14269           0 : nsGlobalWindow::GetAttention(ErrorResult& aResult)
   14270             : {
   14271           0 :   MOZ_ASSERT(IsInnerWindow());
   14272           0 :   return GetAttentionWithCycleCount(-1, aResult);
   14273             : }
   14274             : 
   14275             : NS_IMETHODIMP
   14276           0 : nsGlobalChromeWindow::GetAttentionWithCycleCount(int32_t aCycleCount)
   14277             : {
   14278           0 :   FORWARD_TO_INNER_CHROME(GetAttentionWithCycleCount, (aCycleCount), NS_ERROR_UNEXPECTED);
   14279             : 
   14280           0 :   ErrorResult rv;
   14281           0 :   GetAttentionWithCycleCount(aCycleCount, rv);
   14282           0 :   return rv.StealNSResult();
   14283             : }
   14284             : 
   14285             : void
   14286           0 : nsGlobalWindow::GetAttentionWithCycleCount(int32_t aCycleCount,
   14287             :                                            ErrorResult& aError)
   14288             : {
   14289           0 :   MOZ_ASSERT(IsInnerWindow());
   14290             : 
   14291           0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   14292             : 
   14293           0 :   if (widget) {
   14294           0 :     aError = widget->GetAttention(aCycleCount);
   14295             :   }
   14296           0 : }
   14297             : 
   14298             : NS_IMETHODIMP
   14299           0 : nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElement* aPanel)
   14300             : {
   14301           0 :   FORWARD_TO_INNER_CHROME(BeginWindowMove, (aMouseDownEvent, aPanel), NS_ERROR_UNEXPECTED);
   14302             : 
   14303           0 :   NS_ENSURE_TRUE(aMouseDownEvent, NS_ERROR_FAILURE);
   14304           0 :   Event* mouseDownEvent = aMouseDownEvent->InternalDOMEvent();
   14305           0 :   NS_ENSURE_TRUE(mouseDownEvent, NS_ERROR_FAILURE);
   14306             : 
   14307           0 :   nsCOMPtr<Element> panel = do_QueryInterface(aPanel);
   14308           0 :   NS_ENSURE_TRUE(panel || !aPanel, NS_ERROR_FAILURE);
   14309             : 
   14310           0 :   ErrorResult rv;
   14311           0 :   BeginWindowMove(*mouseDownEvent, panel, rv);
   14312           0 :   return rv.StealNSResult();
   14313             : }
   14314             : 
   14315             : void
   14316           0 : nsGlobalWindow::BeginWindowMove(Event& aMouseDownEvent, Element* aPanel,
   14317             :                                 ErrorResult& aError)
   14318             : {
   14319           0 :   MOZ_ASSERT(IsInnerWindow());
   14320             : 
   14321           0 :   nsCOMPtr<nsIWidget> widget;
   14322             : 
   14323             :   // if a panel was supplied, use its widget instead.
   14324             : #ifdef MOZ_XUL
   14325           0 :   if (aPanel) {
   14326           0 :     nsIFrame* frame = aPanel->GetPrimaryFrame();
   14327           0 :     if (!frame || !frame->IsMenuPopupFrame()) {
   14328           0 :       return;
   14329             :     }
   14330             : 
   14331           0 :     widget = (static_cast<nsMenuPopupFrame*>(frame))->GetWidget();
   14332             :   }
   14333             :   else {
   14334             : #endif
   14335           0 :     widget = GetMainWidget();
   14336             : #ifdef MOZ_XUL
   14337             :   }
   14338             : #endif
   14339             : 
   14340           0 :   if (!widget) {
   14341           0 :     return;
   14342             :   }
   14343             : 
   14344             :   WidgetMouseEvent* mouseEvent =
   14345           0 :     aMouseDownEvent.WidgetEventPtr()->AsMouseEvent();
   14346           0 :   if (!mouseEvent || mouseEvent->mClass != eMouseEventClass) {
   14347           0 :     aError.Throw(NS_ERROR_FAILURE);
   14348           0 :     return;
   14349             :   }
   14350             : 
   14351           0 :   aError = widget->BeginMoveDrag(mouseEvent);
   14352             : }
   14353             : 
   14354             : already_AddRefed<nsWindowRoot>
   14355           0 : nsGlobalWindow::GetWindowRootOuter()
   14356             : {
   14357           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14358           0 :   nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
   14359           0 :   return root.forget().downcast<nsWindowRoot>();
   14360             : }
   14361             : 
   14362             : already_AddRefed<nsWindowRoot>
   14363           0 : nsGlobalWindow::GetWindowRoot(mozilla::ErrorResult& aError)
   14364             : {
   14365           0 :   FORWARD_TO_OUTER_OR_THROW(GetWindowRootOuter, (), aError, nullptr);
   14366             : }
   14367             : 
   14368             : //Note: This call will lock the cursor, it will not change as it moves.
   14369             : //To unlock, the cursor must be set back to CURSOR_AUTO.
   14370             : NS_IMETHODIMP
   14371           0 : nsGlobalChromeWindow::SetCursor(const nsAString& aCursor)
   14372             : {
   14373           0 :   FORWARD_TO_INNER_CHROME(SetCursor, (aCursor), NS_ERROR_UNEXPECTED);
   14374             : 
   14375           0 :   ErrorResult rv;
   14376           0 :   SetCursor(aCursor, rv);
   14377           0 :   return rv.StealNSResult();
   14378             : }
   14379             : 
   14380             : void
   14381           0 : nsGlobalWindow::SetCursorOuter(const nsAString& aCursor, ErrorResult& aError)
   14382             : {
   14383           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14384             : 
   14385             :   int32_t cursor;
   14386             : 
   14387           0 :   if (aCursor.EqualsLiteral("auto"))
   14388           0 :     cursor = NS_STYLE_CURSOR_AUTO;
   14389             :   else {
   14390           0 :     nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(aCursor);
   14391           0 :     if (!nsCSSProps::FindKeyword(keyword, nsCSSProps::kCursorKTable, cursor)) {
   14392           0 :       return;
   14393             :     }
   14394             :   }
   14395             : 
   14396           0 :   RefPtr<nsPresContext> presContext;
   14397           0 :   if (mDocShell) {
   14398           0 :     mDocShell->GetPresContext(getter_AddRefs(presContext));
   14399             :   }
   14400             : 
   14401           0 :   if (presContext) {
   14402             :     // Need root widget.
   14403           0 :     nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
   14404           0 :     if (!presShell) {
   14405           0 :       aError.Throw(NS_ERROR_FAILURE);
   14406           0 :       return;
   14407             :     }
   14408             : 
   14409           0 :     nsViewManager* vm = presShell->GetViewManager();
   14410           0 :     if (!vm) {
   14411           0 :       aError.Throw(NS_ERROR_FAILURE);
   14412           0 :       return;
   14413             :     }
   14414             : 
   14415           0 :     nsView* rootView = vm->GetRootView();
   14416           0 :     if (!rootView) {
   14417           0 :       aError.Throw(NS_ERROR_FAILURE);
   14418           0 :       return;
   14419             :     }
   14420             : 
   14421           0 :     nsIWidget* widget = rootView->GetNearestWidget(nullptr);
   14422           0 :     if (!widget) {
   14423           0 :       aError.Throw(NS_ERROR_FAILURE);
   14424           0 :       return;
   14425             :     }
   14426             : 
   14427             :     // Call esm and set cursor.
   14428           0 :     aError = presContext->EventStateManager()->SetCursor(cursor, nullptr,
   14429             :                                                          false, 0.0f, 0.0f,
   14430           0 :                                                          widget, true);
   14431             :   }
   14432             : }
   14433             : 
   14434             : void
   14435           0 : nsGlobalWindow::SetCursor(const nsAString& aCursor, ErrorResult& aError)
   14436             : {
   14437           0 :   FORWARD_TO_OUTER_OR_THROW(SetCursorOuter, (aCursor, aError), aError, );
   14438             : }
   14439             : 
   14440             : NS_IMETHODIMP
   14441           2 : nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow)
   14442             : {
   14443           2 :   FORWARD_TO_INNER_CHROME(GetBrowserDOMWindow, (aBrowserWindow), NS_ERROR_UNEXPECTED);
   14444             : 
   14445           2 :   ErrorResult rv;
   14446           1 :   NS_IF_ADDREF(*aBrowserWindow = GetBrowserDOMWindow(rv));
   14447           1 :   return rv.StealNSResult();
   14448             : }
   14449             : 
   14450             : nsIBrowserDOMWindow*
   14451           1 : nsGlobalWindow::GetBrowserDOMWindowOuter()
   14452             : {
   14453           1 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14454           1 :   MOZ_ASSERT(IsChromeWindow());
   14455           1 :   return static_cast<nsGlobalChromeWindow*>(this)->mBrowserDOMWindow;
   14456             : }
   14457             : 
   14458             : nsIBrowserDOMWindow*
   14459           1 : nsGlobalWindow::GetBrowserDOMWindow(ErrorResult& aError)
   14460             : {
   14461           1 :   FORWARD_TO_OUTER_OR_THROW(GetBrowserDOMWindowOuter, (), aError, nullptr);
   14462             : }
   14463             : 
   14464             : NS_IMETHODIMP
   14465           0 : nsGlobalChromeWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow *aBrowserWindow)
   14466             : {
   14467           0 :   FORWARD_TO_INNER_CHROME(SetBrowserDOMWindow, (aBrowserWindow), NS_ERROR_UNEXPECTED);
   14468             : 
   14469           0 :   ErrorResult rv;
   14470           0 :   SetBrowserDOMWindow(aBrowserWindow, rv);
   14471           0 :   return rv.StealNSResult();
   14472             : }
   14473             : 
   14474             : void
   14475           1 : nsGlobalWindow::SetBrowserDOMWindowOuter(nsIBrowserDOMWindow* aBrowserWindow)
   14476             : {
   14477           1 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14478           1 :   MOZ_ASSERT(IsChromeWindow());
   14479           1 :   static_cast<nsGlobalChromeWindow*>(this)->mBrowserDOMWindow = aBrowserWindow;
   14480           1 : }
   14481             : 
   14482             : void
   14483           1 : nsGlobalWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserWindow,
   14484             :                                     ErrorResult& aError)
   14485             : {
   14486           1 :   FORWARD_TO_OUTER_OR_THROW(SetBrowserDOMWindowOuter, (aBrowserWindow), aError, );
   14487             : }
   14488             : 
   14489             : NS_IMETHODIMP
   14490           0 : nsGlobalChromeWindow::NotifyDefaultButtonLoaded(nsIDOMElement* aDefaultButton)
   14491             : {
   14492           0 :   FORWARD_TO_INNER_CHROME(NotifyDefaultButtonLoaded,
   14493             :                           (aDefaultButton), NS_ERROR_UNEXPECTED);
   14494             : 
   14495           0 :   nsCOMPtr<Element> defaultButton = do_QueryInterface(aDefaultButton);
   14496           0 :   NS_ENSURE_ARG(defaultButton);
   14497             : 
   14498           0 :   ErrorResult rv;
   14499           0 :   NotifyDefaultButtonLoaded(*defaultButton, rv);
   14500           0 :   return rv.StealNSResult();
   14501             : }
   14502             : 
   14503             : void
   14504           0 : nsGlobalWindow::NotifyDefaultButtonLoaded(Element& aDefaultButton,
   14505             :                                           ErrorResult& aError)
   14506             : {
   14507           0 :   MOZ_ASSERT(IsInnerWindow());
   14508             : #ifdef MOZ_XUL
   14509             :   // Don't snap to a disabled button.
   14510             :   nsCOMPtr<nsIDOMXULControlElement> xulControl =
   14511           0 :                                       do_QueryInterface(&aDefaultButton);
   14512           0 :   if (!xulControl) {
   14513           0 :     aError.Throw(NS_ERROR_FAILURE);
   14514           0 :     return;
   14515             :   }
   14516             :   bool disabled;
   14517           0 :   aError = xulControl->GetDisabled(&disabled);
   14518           0 :   if (aError.Failed() || disabled) {
   14519           0 :     return;
   14520             :   }
   14521             : 
   14522             :   // Get the button rect in screen coordinates.
   14523           0 :   nsIFrame *frame = aDefaultButton.GetPrimaryFrame();
   14524           0 :   if (!frame) {
   14525           0 :     aError.Throw(NS_ERROR_FAILURE);
   14526           0 :     return;
   14527             :   }
   14528             :   LayoutDeviceIntRect buttonRect =
   14529             :     LayoutDeviceIntRect::FromAppUnitsToNearest(
   14530           0 :       frame->GetScreenRectInAppUnits(),
   14531           0 :       frame->PresContext()->AppUnitsPerDevPixel());
   14532             : 
   14533             :   // Get the widget rect in screen coordinates.
   14534           0 :   nsIWidget *widget = GetNearestWidget();
   14535           0 :   if (!widget) {
   14536           0 :     aError.Throw(NS_ERROR_FAILURE);
   14537           0 :     return;
   14538             :   }
   14539           0 :   LayoutDeviceIntRect widgetRect = widget->GetScreenBounds();
   14540             : 
   14541             :   // Convert the buttonRect coordinates from screen to the widget.
   14542           0 :   buttonRect -= widgetRect.TopLeft();
   14543           0 :   nsresult rv = widget->OnDefaultButtonLoaded(buttonRect);
   14544           0 :   if (NS_FAILED(rv) && rv != NS_ERROR_NOT_IMPLEMENTED) {
   14545           0 :     aError.Throw(rv);
   14546             :   }
   14547             : #else
   14548             :   aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
   14549             : #endif
   14550             : }
   14551             : 
   14552             : NS_IMETHODIMP
   14553           4 : nsGlobalChromeWindow::GetMessageManager(nsIMessageBroadcaster** aManager)
   14554             : {
   14555           4 :   FORWARD_TO_INNER_CHROME(GetMessageManager, (aManager), NS_ERROR_UNEXPECTED);
   14556             : 
   14557           4 :   ErrorResult rv;
   14558           2 :   NS_IF_ADDREF(*aManager = GetMessageManager(rv));
   14559           2 :   return rv.StealNSResult();
   14560             : }
   14561             : 
   14562             : nsIMessageBroadcaster*
   14563          29 : nsGlobalWindow::GetMessageManager(ErrorResult& aError)
   14564             : {
   14565          29 :   MOZ_ASSERT(IsChromeWindow());
   14566          29 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   14567          29 :   nsGlobalChromeWindow* myself = static_cast<nsGlobalChromeWindow*>(this);
   14568          29 :   if (!myself->mMessageManager) {
   14569             :     nsCOMPtr<nsIMessageBroadcaster> globalMM =
   14570           2 :       do_GetService("@mozilla.org/globalmessagemanager;1");
   14571             :     myself->mMessageManager =
   14572           1 :       new nsFrameMessageManager(nullptr,
   14573           1 :                                 static_cast<nsFrameMessageManager*>(globalMM.get()),
   14574           2 :                                 MM_CHROME | MM_BROADCASTER);
   14575             :   }
   14576          29 :   return myself->mMessageManager;
   14577             : }
   14578             : 
   14579             : NS_IMETHODIMP
   14580           4 : nsGlobalChromeWindow::GetGroupMessageManager(const nsAString& aGroup,
   14581             :                                              nsIMessageBroadcaster** aManager)
   14582             : {
   14583           4 :   FORWARD_TO_INNER_CHROME(GetGroupMessageManager, (aGroup, aManager), NS_ERROR_UNEXPECTED);
   14584             : 
   14585           4 :   ErrorResult rv;
   14586           2 :   NS_IF_ADDREF(*aManager = GetGroupMessageManager(aGroup, rv));
   14587           2 :   return rv.StealNSResult();
   14588             : }
   14589             : 
   14590             : nsIMessageBroadcaster*
   14591           7 : nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup,
   14592             :                                        ErrorResult& aError)
   14593             : {
   14594           7 :   MOZ_ASSERT(IsChromeWindow());
   14595           7 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   14596             : 
   14597           7 :   nsGlobalChromeWindow* myself = static_cast<nsGlobalChromeWindow*>(this);
   14598             :   nsCOMPtr<nsIMessageBroadcaster> messageManager =
   14599          14 :     myself->mGroupMessageManagers.LookupForAdd(aGroup).OrInsert(
   14600           1 :       [this, &aError] () {
   14601             :         nsFrameMessageManager* parent =
   14602           1 :           static_cast<nsFrameMessageManager*>(GetMessageManager(aError));
   14603             : 
   14604             :         return new nsFrameMessageManager(nullptr,
   14605             :                                          parent,
   14606           1 :                                          MM_CHROME | MM_BROADCASTER);
   14607          21 :       });
   14608          14 :   return messageManager;
   14609             : }
   14610             : 
   14611             : nsresult
   14612           0 : nsGlobalChromeWindow::SetOpenerForInitialContentBrowser(mozIDOMWindowProxy* aOpenerWindow)
   14613             : {
   14614           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14615           0 :   MOZ_ASSERT(!mOpenerForInitialContentBrowser);
   14616           0 :   mOpenerForInitialContentBrowser = aOpenerWindow;
   14617           0 :   return NS_OK;
   14618             : }
   14619             : 
   14620             : nsresult
   14621           2 : nsGlobalChromeWindow::TakeOpenerForInitialContentBrowser(mozIDOMWindowProxy** aOpenerWindow)
   14622             : {
   14623           2 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14624             :   // Intentionally forget our own member
   14625           2 :   mOpenerForInitialContentBrowser.forget(aOpenerWindow);
   14626           2 :   return NS_OK;
   14627             : }
   14628             : 
   14629             : // nsGlobalModalWindow implementation
   14630             : 
   14631             : // QueryInterface implementation for nsGlobalModalWindow
   14632           0 : NS_INTERFACE_MAP_BEGIN(nsGlobalModalWindow)
   14633           0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow)
   14634           0 : NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
   14635             : 
   14636           0 : NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
   14637           0 : NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
   14638             : 
   14639             : 
   14640             : void
   14641           0 : nsGlobalWindow::GetDialogArgumentsOuter(JSContext* aCx,
   14642             :                                         JS::MutableHandle<JS::Value> aRetval,
   14643             :                                         nsIPrincipal& aSubjectPrincipal,
   14644             :                                         ErrorResult& aError)
   14645             : {
   14646           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14647           0 :   MOZ_ASSERT(IsModalContentWindow(),
   14648             :              "This should only be called on modal windows!");
   14649             : 
   14650           0 :   if (!mDialogArguments) {
   14651           0 :     MOZ_ASSERT(mIsClosed, "This window should be closed!");
   14652           0 :     aRetval.setUndefined();
   14653           0 :     return;
   14654             :   }
   14655             : 
   14656             :   // This does an internal origin check, and returns undefined if the subject
   14657             :   // does not subsumes the origin of the arguments.
   14658           0 :   JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
   14659           0 :   JSAutoCompartment ac(aCx, wrapper);
   14660           0 :   mDialogArguments->Get(aCx, wrapper, &aSubjectPrincipal, aRetval, aError);
   14661             : }
   14662             : 
   14663             : void
   14664           0 : nsGlobalWindow::GetDialogArguments(JSContext* aCx,
   14665             :                                    JS::MutableHandle<JS::Value> aRetval,
   14666             :                                    nsIPrincipal& aSubjectPrincipal,
   14667             :                                    ErrorResult& aError)
   14668             : {
   14669           0 :   FORWARD_TO_OUTER_OR_THROW(GetDialogArgumentsOuter,
   14670             :                             (aCx, aRetval, aSubjectPrincipal, aError),
   14671             :                             aError, );
   14672             : }
   14673             : 
   14674             : /* static */ already_AddRefed<nsGlobalModalWindow>
   14675           0 : nsGlobalModalWindow::Create(nsGlobalWindow *aOuterWindow)
   14676             : {
   14677           0 :   RefPtr<nsGlobalModalWindow> window = new nsGlobalModalWindow(aOuterWindow);
   14678           0 :   window->InitWasOffline();
   14679           0 :   return window.forget();
   14680             : }
   14681             : 
   14682             : NS_IMETHODIMP
   14683           0 : nsGlobalModalWindow::GetDialogArguments(nsIVariant **aArguments)
   14684             : {
   14685           0 :   FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetDialogArguments, (aArguments),
   14686             :                                         NS_ERROR_NOT_INITIALIZED);
   14687             : 
   14688             :   // This does an internal origin check, and returns undefined if the subject
   14689             :   // does not subsumes the origin of the arguments.
   14690           0 :   return mDialogArguments->Get(nsContentUtils::SubjectPrincipal(), aArguments);
   14691             : }
   14692             : 
   14693             : /* static */ already_AddRefed<nsGlobalWindow>
   14694           5 : nsGlobalWindow::Create(nsGlobalWindow *aOuterWindow)
   14695             : {
   14696          10 :   RefPtr<nsGlobalWindow> window = new nsGlobalWindow(aOuterWindow);
   14697           5 :   window->InitWasOffline();
   14698          10 :   return window.forget();
   14699             : }
   14700             : 
   14701             : void
   14702          12 : nsGlobalWindow::InitWasOffline()
   14703             : {
   14704          12 :   mWasOffline = NS_IsOffline();
   14705          12 : }
   14706             : 
   14707             : void
   14708           0 : nsGlobalWindow::GetReturnValueOuter(JSContext* aCx,
   14709             :                                     JS::MutableHandle<JS::Value> aReturnValue,
   14710             :                                     nsIPrincipal& aSubjectPrincipal,
   14711             :                                     ErrorResult& aError)
   14712             : {
   14713           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14714           0 :   MOZ_ASSERT(IsModalContentWindow(),
   14715             :              "This should only be called on modal windows!");
   14716             : 
   14717           0 :   if (mReturnValue) {
   14718           0 :     JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
   14719           0 :     JSAutoCompartment ac(aCx, wrapper);
   14720           0 :     mReturnValue->Get(aCx, wrapper, &aSubjectPrincipal, aReturnValue, aError);
   14721             :   } else {
   14722           0 :     aReturnValue.setUndefined();
   14723             :   }
   14724           0 : }
   14725             : 
   14726             : void
   14727           0 : nsGlobalWindow::GetReturnValue(JSContext* aCx,
   14728             :                                JS::MutableHandle<JS::Value> aReturnValue,
   14729             :                                nsIPrincipal& aSubjectPrincipal,
   14730             :                                ErrorResult& aError)
   14731             : {
   14732           0 :   FORWARD_TO_OUTER_OR_THROW(GetReturnValueOuter,
   14733             :                             (aCx, aReturnValue, aSubjectPrincipal, aError),
   14734             :                             aError, );
   14735             : }
   14736             : 
   14737             : NS_IMETHODIMP
   14738           0 : nsGlobalModalWindow::GetReturnValue(nsIVariant **aRetVal)
   14739             : {
   14740           0 :   FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetReturnValue, (aRetVal), NS_OK);
   14741             : 
   14742           0 :   if (!mReturnValue) {
   14743           0 :     nsCOMPtr<nsIVariant> variant = CreateVoidVariant();
   14744           0 :     variant.forget(aRetVal);
   14745           0 :     return NS_OK;
   14746             :   }
   14747           0 :   return mReturnValue->Get(nsContentUtils::SubjectPrincipal(), aRetVal);
   14748             : }
   14749             : 
   14750             : void
   14751           0 : nsGlobalWindow::SetReturnValueOuter(JSContext* aCx,
   14752             :                                     JS::Handle<JS::Value> aReturnValue,
   14753             :                                     nsIPrincipal& aSubjectPrincipal,
   14754             :                                     ErrorResult& aError)
   14755             : {
   14756           0 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14757           0 :   MOZ_ASSERT(IsModalContentWindow(),
   14758             :              "This should only be called on modal windows!");
   14759             : 
   14760           0 :   nsCOMPtr<nsIVariant> returnValue;
   14761           0 :   aError =
   14762           0 :     nsContentUtils::XPConnect()->JSToVariant(aCx, aReturnValue,
   14763           0 :                                              getter_AddRefs(returnValue));
   14764           0 :   if (!aError.Failed()) {
   14765           0 :     mReturnValue = new DialogValueHolder(&aSubjectPrincipal, returnValue);
   14766             :   }
   14767           0 : }
   14768             : 
   14769             : void
   14770           0 : nsGlobalWindow::SetReturnValue(JSContext* aCx,
   14771             :                                JS::Handle<JS::Value> aReturnValue,
   14772             :                                nsIPrincipal& aSubjectPrincipal,
   14773             :                                ErrorResult& aError)
   14774             : {
   14775           0 :   FORWARD_TO_OUTER_OR_THROW(SetReturnValueOuter,
   14776             :                             (aCx, aReturnValue, aSubjectPrincipal, aError),
   14777             :                             aError, );
   14778             : }
   14779             : 
   14780             : NS_IMETHODIMP
   14781           0 : nsGlobalModalWindow::SetReturnValue(nsIVariant *aRetVal)
   14782             : {
   14783           0 :   FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(SetReturnValue, (aRetVal), NS_OK);
   14784             : 
   14785           0 :   mReturnValue = new DialogValueHolder(nsContentUtils::SubjectPrincipal(),
   14786           0 :                                        aRetVal);
   14787           0 :   return NS_OK;
   14788             : }
   14789             : 
   14790             : /* static */
   14791             : bool
   14792           7 : nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
   14793             : {
   14794           7 :   return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
   14795             : }
   14796             : 
   14797             : #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
   14798             : int16_t
   14799             : nsGlobalWindow::Orientation(CallerType aCallerType) const
   14800             : {
   14801             :   return nsContentUtils::ResistFingerprinting(aCallerType) ?
   14802             :            0 : WindowOrientationObserver::OrientationAngle();
   14803             : }
   14804             : #endif
   14805             : 
   14806             : Console*
   14807           1 : nsGlobalWindow::GetConsole(ErrorResult& aRv)
   14808             : {
   14809           1 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   14810             : 
   14811           1 :   if (!mConsole) {
   14812           1 :     mConsole = Console::Create(AsInner(), aRv);
   14813           1 :     if (NS_WARN_IF(aRv.Failed())) {
   14814           0 :       return nullptr;
   14815             :     }
   14816             :   }
   14817             : 
   14818           1 :   return mConsole;
   14819             : }
   14820             : 
   14821             : bool
   14822           0 : nsGlobalWindow::IsSecureContext() const
   14823             : {
   14824           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   14825             : 
   14826           0 :   return JS_GetIsSecureContext(js::GetObjectCompartment(GetWrapperPreserveColor()));
   14827             : }
   14828             : 
   14829             : bool
   14830           0 : nsGlobalWindow::IsSecureContextIfOpenerIgnored() const
   14831             : {
   14832           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   14833             : 
   14834           0 :   return mIsSecureContextIfOpenerIgnored;
   14835             : }
   14836             : 
   14837             : already_AddRefed<External>
   14838           0 : nsGlobalWindow::GetExternal(ErrorResult& aRv)
   14839             : {
   14840           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   14841             : 
   14842             : #ifdef HAVE_SIDEBAR
   14843           0 :   if (!mExternal) {
   14844           0 :     AutoJSContext cx;
   14845           0 :     JS::Rooted<JSObject*> jsImplObj(cx);
   14846           0 :     ConstructJSImplementation("@mozilla.org/sidebar;1", this, &jsImplObj, aRv);
   14847           0 :     if (aRv.Failed()) {
   14848           0 :       return nullptr;
   14849             :     }
   14850           0 :     mExternal = new External(jsImplObj, this);
   14851             :   }
   14852             : 
   14853           0 :   RefPtr<External> external = static_cast<External*>(mExternal.get());
   14854           0 :   return external.forget();
   14855             : #else
   14856             :   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   14857             :   return nullptr;
   14858             : #endif
   14859             : }
   14860             : 
   14861             : void
   14862           0 : nsGlobalWindow::GetSidebar(OwningExternalOrWindowProxy& aResult,
   14863             :                            ErrorResult& aRv)
   14864             : {
   14865           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   14866             : 
   14867             : #ifdef HAVE_SIDEBAR
   14868             :   // First check for a named frame named "sidebar"
   14869           0 :   nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetChildWindow(NS_LITERAL_STRING("sidebar"));
   14870           0 :   if (domWindow) {
   14871           0 :     aResult.SetAsWindowProxy() = domWindow.forget();
   14872           0 :     return;
   14873             :   }
   14874             : 
   14875           0 :   RefPtr<External> external = GetExternal(aRv);
   14876           0 :   if (external) {
   14877           0 :     aResult.SetAsExternal() = external;
   14878             :   }
   14879             : #else
   14880             :   aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   14881             : #endif
   14882             : }
   14883             : 
   14884             : void
   14885           8 : nsGlobalWindow::ClearDocumentDependentSlots(JSContext* aCx)
   14886             : {
   14887           8 :   MOZ_ASSERT(IsInnerWindow());
   14888             : 
   14889             :   // If JSAPI OOMs here, there is basically nothing we can do to recover safely.
   14890          16 :   if (!WindowBinding::ClearCachedDocumentValue(aCx, this) ||
   14891           8 :       !WindowBinding::ClearCachedPerformanceValue(aCx, this)) {
   14892           0 :     MOZ_CRASH("Unhandlable OOM while clearing document dependent slots.");
   14893             :   }
   14894           8 : }
   14895             : 
   14896             : /* static */
   14897             : JSObject*
   14898           7 : nsGlobalWindow::CreateNamedPropertiesObject(JSContext *aCx,
   14899             :                                             JS::Handle<JSObject*> aProto)
   14900             : {
   14901           7 :   return WindowNamedPropertiesHandler::Create(aCx, aProto);
   14902             : }
   14903             : 
   14904             : bool
   14905           1 : nsGlobalWindow::GetIsPrerendered()
   14906             : {
   14907           1 :   nsIDocShell* docShell = GetDocShell();
   14908           1 :   return docShell && docShell->GetIsPrerendered();
   14909             : }
   14910             : 
   14911             : void
   14912           0 : nsPIDOMWindowOuter::SetLargeAllocStatus(LargeAllocStatus aStatus)
   14913             : {
   14914           0 :   MOZ_ASSERT(mLargeAllocStatus == LargeAllocStatus::NONE);
   14915           0 :   mLargeAllocStatus = aStatus;
   14916           0 : }
   14917             : 
   14918             : bool
   14919           0 : nsPIDOMWindowOuter::IsTopLevelWindow()
   14920             : {
   14921           0 :   return nsGlobalWindow::Cast(this)->IsTopLevelWindow();
   14922             : }
   14923             : 
   14924             : bool
   14925           0 : nsPIDOMWindowOuter::HadOriginalOpener() const
   14926             : {
   14927           0 :   return nsGlobalWindow::Cast(this)->HadOriginalOpener();
   14928             : }
   14929             : 
   14930             : void
   14931           8 : nsGlobalWindow::ReportLargeAllocStatus()
   14932             : {
   14933           8 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   14934             : 
   14935           8 :   uint32_t errorFlags = nsIScriptError::warningFlag;
   14936           8 :   const char* message = nullptr;
   14937             : 
   14938           8 :   switch (mLargeAllocStatus) {
   14939             :     case LargeAllocStatus::SUCCESS:
   14940             :       // Override the error flags such that the success message isn't reported
   14941             :       // as a warning.
   14942           0 :       errorFlags = nsIScriptError::infoFlag;
   14943           0 :       message = "LargeAllocationSuccess";
   14944           0 :       break;
   14945             :     case LargeAllocStatus::NON_WIN32:
   14946           0 :       errorFlags = nsIScriptError::infoFlag;
   14947           0 :       message = "LargeAllocationNonWin32";
   14948           0 :       break;
   14949             :     case LargeAllocStatus::NON_GET:
   14950           0 :       message = "LargeAllocationNonGetRequest";
   14951           0 :       break;
   14952             :     case LargeAllocStatus::NON_E10S:
   14953           0 :       message = "LargeAllocationNonE10S";
   14954           0 :       break;
   14955             :     case LargeAllocStatus::NOT_ONLY_TOPLEVEL_IN_TABGROUP:
   14956           0 :       message = "LargeAllocationNotOnlyToplevelInTabGroup";
   14957           0 :       break;
   14958             :     default: // LargeAllocStatus::NONE
   14959           8 :       return; // Don't report a message to the console
   14960             :   }
   14961             : 
   14962           0 :   nsContentUtils::ReportToConsole(errorFlags,
   14963           0 :                                   NS_LITERAL_CSTRING("DOM"),
   14964             :                                   mDoc,
   14965             :                                   nsContentUtils::eDOM_PROPERTIES,
   14966           0 :                                   message);
   14967             : }
   14968             : 
   14969             : #ifdef MOZ_B2G
   14970             : void
   14971             : nsGlobalWindow::EnableNetworkEvent(EventMessage aEventMessage)
   14972             : {
   14973             :   MOZ_ASSERT(IsInnerWindow());
   14974             : 
   14975             :   nsCOMPtr<nsIPermissionManager> permMgr =
   14976             :     services::GetPermissionManager();
   14977             :   if (!permMgr) {
   14978             :     NS_ERROR("No PermissionManager available!");
   14979             :     return;
   14980             :   }
   14981             : 
   14982             :   uint32_t permission = nsIPermissionManager::DENY_ACTION;
   14983             :   permMgr->TestExactPermissionFromPrincipal(GetPrincipal(), "network-events",
   14984             :                                             &permission);
   14985             : 
   14986             :   if (permission != nsIPermissionManager::ALLOW_ACTION) {
   14987             :     return;
   14988             :   }
   14989             : 
   14990             :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   14991             :   if (!os) {
   14992             :     NS_ERROR("ObserverService should be available!");
   14993             :     return;
   14994             :   }
   14995             : 
   14996             :   switch (aEventMessage) {
   14997             :     case eNetworkUpload:
   14998             :       if (!mNetworkUploadObserverEnabled) {
   14999             :         mNetworkUploadObserverEnabled = true;
   15000             :         os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC, false);
   15001             :       }
   15002             :       break;
   15003             :     case eNetworkDownload:
   15004             :       if (!mNetworkDownloadObserverEnabled) {
   15005             :         mNetworkDownloadObserverEnabled = true;
   15006             :         os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC, false);
   15007             :       }
   15008             :       break;
   15009             :     default:
   15010             :       break;
   15011             :   }
   15012             : }
   15013             : 
   15014             : void
   15015             : nsGlobalWindow::DisableNetworkEvent(EventMessage aEventMessage)
   15016             : {
   15017             :   MOZ_ASSERT(IsInnerWindow());
   15018             : 
   15019             :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   15020             :   if (!os) {
   15021             :     return;
   15022             :   }
   15023             : 
   15024             :   switch (aEventMessage) {
   15025             :     case eNetworkUpload:
   15026             :       if (mNetworkUploadObserverEnabled) {
   15027             :         mNetworkUploadObserverEnabled = false;
   15028             :         os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC);
   15029             :       }
   15030             :       break;
   15031             :     case eNetworkDownload:
   15032             :       if (mNetworkDownloadObserverEnabled) {
   15033             :         mNetworkDownloadObserverEnabled = false;
   15034             :         os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC);
   15035             :       }
   15036             :       break;
   15037             :     default:
   15038             :       break;
   15039             :   }
   15040             : }
   15041             : #endif // MOZ_B2G
   15042             : 
   15043             : void
   15044           0 : nsGlobalWindow::RedefineProperty(JSContext* aCx, const char* aPropName,
   15045             :                                  JS::Handle<JS::Value> aValue,
   15046             :                                  ErrorResult& aError)
   15047             : {
   15048           0 :   JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
   15049           0 :   if (!thisObj) {
   15050           0 :     aError.Throw(NS_ERROR_UNEXPECTED);
   15051           0 :     return;
   15052             :   }
   15053             : 
   15054           0 :   if (!JS_WrapObject(aCx, &thisObj) ||
   15055           0 :       !JS_DefineProperty(aCx, thisObj, aPropName, aValue, JSPROP_ENUMERATE,
   15056             :                          JS_STUBGETTER, JS_STUBSETTER)) {
   15057           0 :     aError.Throw(NS_ERROR_FAILURE);
   15058             :   }
   15059             : }
   15060             : 
   15061             : void
   15062           0 : nsGlobalWindow::GetReplaceableWindowCoord(JSContext* aCx,
   15063             :                                           nsGlobalWindow::WindowCoordGetter aGetter,
   15064             :                                           JS::MutableHandle<JS::Value> aRetval,
   15065             :                                           CallerType aCallerType,
   15066             :                                           ErrorResult& aError)
   15067             : {
   15068           0 :   MOZ_ASSERT(IsInnerWindow());
   15069             : 
   15070           0 :   int32_t coord = (this->*aGetter)(aCallerType, aError);
   15071           0 :   if (!aError.Failed() &&
   15072           0 :       !ToJSValue(aCx, coord, aRetval)) {
   15073           0 :     aError.Throw(NS_ERROR_FAILURE);
   15074             :   }
   15075           0 : }
   15076             : 
   15077             : void
   15078           0 : nsGlobalWindow::SetReplaceableWindowCoord(JSContext* aCx,
   15079             :                                           nsGlobalWindow::WindowCoordSetter aSetter,
   15080             :                                           JS::Handle<JS::Value> aValue,
   15081             :                                           const char* aPropName,
   15082             :                                           CallerType aCallerType,
   15083             :                                           ErrorResult& aError)
   15084             : {
   15085           0 :   MOZ_ASSERT(IsInnerWindow());
   15086             : 
   15087             :   /*
   15088             :    * If caller is not chrome and the user has not explicitly exempted the site,
   15089             :    * just treat this the way we would an IDL replaceable property.
   15090             :    */
   15091           0 :   nsGlobalWindow* outer = GetOuterWindowInternal();
   15092           0 :   if (!outer ||
   15093           0 :       !outer->CanMoveResizeWindows(aCallerType) ||
   15094           0 :       outer->IsFrame()) {
   15095           0 :     RedefineProperty(aCx, aPropName, aValue, aError);
   15096           0 :     return;
   15097             :   }
   15098             : 
   15099             :   int32_t value;
   15100           0 :   if (!ValueToPrimitive<int32_t, eDefault>(aCx, aValue, &value)) {
   15101           0 :     aError.Throw(NS_ERROR_UNEXPECTED);
   15102           0 :     return;
   15103             :   }
   15104             : 
   15105           0 :   if (nsContentUtils::ShouldResistFingerprinting(GetDocShell())) {
   15106           0 :     bool innerWidthSpecified = false;
   15107           0 :     bool innerHeightSpecified = false;
   15108           0 :     bool outerWidthSpecified = false;
   15109           0 :     bool outerHeightSpecified = false;
   15110             : 
   15111           0 :     if (strcmp(aPropName, "innerWidth") == 0) {
   15112           0 :       innerWidthSpecified = true;
   15113           0 :     } else if (strcmp(aPropName, "innerHeight") == 0) {
   15114           0 :       innerHeightSpecified = true;
   15115           0 :     } else if (strcmp(aPropName, "outerWidth") == 0) {
   15116           0 :       outerWidthSpecified = true;
   15117           0 :     } else if (strcmp(aPropName, "outerHeight") == 0) {
   15118           0 :       outerHeightSpecified = true;
   15119             :     }
   15120             : 
   15121           0 :     if (innerWidthSpecified || innerHeightSpecified ||
   15122           0 :         outerWidthSpecified || outerHeightSpecified)
   15123             :     {
   15124           0 :       nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = outer->GetTreeOwnerWindow();
   15125           0 :       nsCOMPtr<nsIScreen> screen;
   15126             :       nsCOMPtr<nsIScreenManager> screenMgr(
   15127           0 :         do_GetService("@mozilla.org/gfx/screenmanager;1"));
   15128           0 :       int32_t winLeft   = 0;
   15129           0 :       int32_t winTop    = 0;
   15130           0 :       int32_t winWidth  = 0;
   15131           0 :       int32_t winHeight = 0;
   15132           0 :       double scale = 1.0;
   15133             : 
   15134             : 
   15135           0 :       if (treeOwnerAsWin && screenMgr) {
   15136             :         // Acquire current window size.
   15137           0 :         treeOwnerAsWin->GetUnscaledDevicePixelsPerCSSPixel(&scale);
   15138           0 :         treeOwnerAsWin->GetPositionAndSize(&winLeft, &winTop, &winWidth, &winHeight);
   15139           0 :         winLeft = NSToIntRound(winHeight / scale);
   15140           0 :         winTop = NSToIntRound(winWidth / scale);
   15141           0 :         winWidth = NSToIntRound(winWidth / scale);
   15142           0 :         winHeight = NSToIntRound(winHeight / scale);
   15143             : 
   15144             :         // Acquire content window size.
   15145           0 :         CSSIntSize contentSize;
   15146           0 :         outer->GetInnerSize(contentSize);
   15147             : 
   15148           0 :         screenMgr->ScreenForRect(winLeft, winTop, winWidth, winHeight,
   15149           0 :                                  getter_AddRefs(screen));
   15150             : 
   15151           0 :         if (screen) {
   15152           0 :           int32_t* targetContentWidth  = nullptr;
   15153           0 :           int32_t* targetContentHeight = nullptr;
   15154           0 :           int32_t screenWidth  = 0;
   15155           0 :           int32_t screenHeight = 0;
   15156           0 :           int32_t chromeWidth  = 0;
   15157           0 :           int32_t chromeHeight = 0;
   15158           0 :           int32_t inputWidth   = 0;
   15159           0 :           int32_t inputHeight  = 0;
   15160           0 :           int32_t unused = 0;
   15161             : 
   15162             :           // Get screen dimensions (in device pixels)
   15163           0 :           screen->GetAvailRect(&unused, &unused, &screenWidth,
   15164           0 :                                &screenHeight);
   15165             :           // Convert them to CSS pixels
   15166           0 :           screenWidth = NSToIntRound(screenWidth / scale);
   15167           0 :           screenHeight = NSToIntRound(screenHeight / scale);
   15168             : 
   15169             :           // Calculate the chrome UI size.
   15170           0 :           chromeWidth = winWidth - contentSize.width;
   15171           0 :           chromeHeight = winHeight - contentSize.height;
   15172             : 
   15173           0 :           if (innerWidthSpecified || outerWidthSpecified) {
   15174           0 :             inputWidth = value;
   15175           0 :             targetContentWidth = &value;
   15176           0 :             targetContentHeight = &unused;
   15177           0 :           } else if (innerHeightSpecified || outerHeightSpecified) {
   15178           0 :             inputHeight = value;
   15179           0 :             targetContentWidth = &unused;
   15180           0 :             targetContentHeight = &value;
   15181             :           }
   15182             : 
   15183           0 :           nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
   15184             :             chromeWidth,
   15185             :             chromeHeight,
   15186             :             screenWidth,
   15187             :             screenHeight,
   15188             :             inputWidth,
   15189             :             inputHeight,
   15190             :             outerWidthSpecified,
   15191             :             outerHeightSpecified,
   15192             :             targetContentWidth,
   15193             :             targetContentHeight
   15194           0 :           );
   15195             :         }
   15196             :       }
   15197             :     }
   15198             :   }
   15199             : 
   15200           0 :   (this->*aSetter)(value, aCallerType, aError);
   15201             : }
   15202             : 
   15203             : void
   15204           7 : nsGlobalWindow::FireOnNewGlobalObject()
   15205             : {
   15206           7 :   MOZ_ASSERT(IsInnerWindow());
   15207             : 
   15208             :   // AutoEntryScript required to invoke debugger hook, which is a
   15209             :   // Gecko-specific concept at present.
   15210          14 :   AutoEntryScript aes(this, "nsGlobalWindow report new global");
   15211          14 :   JS::Rooted<JSObject*> global(aes.cx(), GetWrapper());
   15212           7 :   JS_FireOnNewGlobalObject(aes.cx(), global);
   15213           7 : }
   15214             : 
   15215             : #ifdef _WINDOWS_
   15216             : #error "Never include windows.h in this file!"
   15217             : #endif
   15218             : 
   15219             : already_AddRefed<Promise>
   15220           0 : nsGlobalWindow::CreateImageBitmap(JSContext* aCx,
   15221             :                                   const ImageBitmapSource& aImage,
   15222             :                                   ErrorResult& aRv)
   15223             : {
   15224           0 :   if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
   15225           0 :     aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   15226           0 :     return nullptr;
   15227             :   }
   15228             : 
   15229           0 :   return ImageBitmap::Create(this, aImage, Nothing(), aRv);
   15230             : }
   15231             : 
   15232             : already_AddRefed<Promise>
   15233           0 : nsGlobalWindow::CreateImageBitmap(JSContext* aCx,
   15234             :                                   const ImageBitmapSource& aImage,
   15235             :                                   int32_t aSx, int32_t aSy, int32_t aSw, int32_t aSh,
   15236             :                                   ErrorResult& aRv)
   15237             : {
   15238           0 :   if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
   15239           0 :     aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   15240           0 :     return nullptr;
   15241             :   }
   15242             : 
   15243           0 :   return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
   15244             : }
   15245             : 
   15246             : already_AddRefed<mozilla::dom::Promise>
   15247           0 : nsGlobalWindow::CreateImageBitmap(JSContext* aCx,
   15248             :                                   const ImageBitmapSource& aImage,
   15249             :                                   int32_t aOffset, int32_t aLength,
   15250             :                                   ImageBitmapFormat aFormat,
   15251             :                                   const Sequence<ChannelPixelLayout>& aLayout,
   15252             :                                   ErrorResult& aRv)
   15253             : {
   15254           0 :   if (!ImageBitmap::ExtensionsEnabled(aCx)) {
   15255           0 :     aRv.Throw(NS_ERROR_TYPE_ERR);
   15256           0 :     return nullptr;
   15257             :   }
   15258           0 :   if (aImage.IsArrayBuffer() || aImage.IsArrayBufferView()) {
   15259             :     return ImageBitmap::Create(this, aImage, aOffset, aLength, aFormat, aLayout,
   15260           0 :                                aRv);
   15261             :   }
   15262           0 :   aRv.Throw(NS_ERROR_TYPE_ERR);
   15263           0 :   return nullptr;
   15264             : }
   15265             : 
   15266             : // Helper called by methods that move/resize the window,
   15267             : // to ensure the presContext (if any) is aware of resolution
   15268             : // change that may happen in multi-monitor configuration.
   15269             : void
   15270           0 : nsGlobalWindow::CheckForDPIChange()
   15271             : {
   15272           0 :   if (mDocShell) {
   15273           0 :     RefPtr<nsPresContext> presContext;
   15274           0 :     mDocShell->GetPresContext(getter_AddRefs(presContext));
   15275           0 :     if (presContext) {
   15276           0 :       if (presContext->DeviceContext()->CheckDPIChange()) {
   15277           0 :         presContext->UIResolutionChanged();
   15278             :       }
   15279             :     }
   15280             :   }
   15281           0 : }
   15282             : 
   15283             : mozilla::dom::TabGroup*
   15284          27 : nsGlobalWindow::TabGroupOuter()
   15285             : {
   15286          27 :   MOZ_RELEASE_ASSERT(IsOuterWindow());
   15287             : 
   15288             :   // Outer windows lazily join TabGroups when requested. This is usually done
   15289             :   // because a document is getting its NodePrincipal, and asking for the
   15290             :   // TabGroup to determine its DocGroup.
   15291          27 :   if (!mTabGroup) {
   15292             :     // Get mOpener ourselves, instead of relying on GetOpenerWindowOuter,
   15293             :     // because that way we dodge the LegacyIsCallerChromeOrNativeCode() call
   15294             :     // which we want to return false.
   15295          10 :     nsCOMPtr<nsPIDOMWindowOuter> piOpener = do_QueryReferent(mOpener);
   15296           5 :     nsPIDOMWindowOuter* opener = GetSanitizedOpener(piOpener);
   15297           5 :     nsPIDOMWindowOuter* parent = GetScriptableParentOrNull();
   15298           5 :     MOZ_ASSERT(!parent || !opener, "Only one of parent and opener may be provided");
   15299             : 
   15300           5 :     mozilla::dom::TabGroup* toJoin = nullptr;
   15301           5 :     if (GetDocShell()->ItemType() == nsIDocShellTreeItem::typeChrome) {
   15302           3 :       toJoin = TabGroup::GetChromeTabGroup();
   15303           2 :     } else if (opener) {
   15304           0 :       toJoin = opener->TabGroup();
   15305           2 :     } else if (parent) {
   15306           0 :       toJoin = parent->TabGroup();
   15307             :     } else {
   15308           2 :       toJoin = TabGroup::GetFromWindow(AsOuter());
   15309             :     }
   15310             : 
   15311             : #ifdef DEBUG
   15312             :     // Make sure that, if we have a tab group from the actor, it matches the one
   15313             :     // we're planning to join.
   15314           5 :     mozilla::dom::TabGroup* testGroup = TabGroup::GetFromWindow(AsOuter());
   15315           5 :     MOZ_ASSERT_IF(testGroup, testGroup == toJoin);
   15316             : #endif
   15317             : 
   15318           5 :     mTabGroup = mozilla::dom::TabGroup::Join(AsOuter(), toJoin);
   15319             :   }
   15320          27 :   MOZ_ASSERT(mTabGroup);
   15321             : 
   15322             : #ifdef DEBUG
   15323             :   // Ensure that we don't recurse forever
   15324          27 :   if (!mIsValidatingTabGroup) {
   15325          27 :     mIsValidatingTabGroup = true;
   15326             :     // We only need to do this check if we aren't in the chrome tab group
   15327          27 :     if (mIsChrome) {
   15328          13 :       MOZ_ASSERT(mTabGroup == TabGroup::GetChromeTabGroup());
   15329             :     } else {
   15330             :       // Sanity check that our tabgroup matches our opener or parent.
   15331          28 :       RefPtr<nsPIDOMWindowOuter> parent = GetScriptableParentOrNull();
   15332          14 :       MOZ_ASSERT_IF(parent, parent->TabGroup() == mTabGroup);
   15333          28 :       nsCOMPtr<nsPIDOMWindowOuter> piOpener = do_QueryReferent(mOpener);
   15334          14 :       nsPIDOMWindowOuter* opener = GetSanitizedOpener(piOpener);
   15335          14 :       MOZ_ASSERT_IF(opener && Cast(opener) != this, opener->TabGroup() == mTabGroup);
   15336             :     }
   15337          27 :     mIsValidatingTabGroup = false;
   15338             :   }
   15339             : #endif
   15340             : 
   15341          27 :   return mTabGroup;
   15342             : }
   15343             : 
   15344             : mozilla::dom::TabGroup*
   15345           9 : nsGlobalWindow::TabGroupInner()
   15346             : {
   15347           9 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   15348             : 
   15349             :   // If we don't have a TabGroup yet, try to get it from the outer window and
   15350             :   // cache it.
   15351           9 :   if (!mTabGroup) {
   15352           7 :     nsGlobalWindow* outer = GetOuterWindowInternal();
   15353             :     // This will never be called without either an outer window, or a cached tab group.
   15354             :     // This is because of the following:
   15355             :     // * This method is only called on inner windows
   15356             :     // * This method is called as a document is attached to it's script global
   15357             :     //   by the document
   15358             :     // * Inner windows are created in nsGlobalWindow::SetNewDocument, which
   15359             :     //   immediately sets a document, which will call this method, causing
   15360             :     //   the TabGroup to be cached.
   15361           7 :     MOZ_RELEASE_ASSERT(outer, "Inner window without outer window has no cached tab group!");
   15362           7 :     mTabGroup = outer->TabGroup();
   15363             :   }
   15364           9 :   MOZ_ASSERT(mTabGroup);
   15365             : 
   15366             : #ifdef DEBUG
   15367           9 :   nsGlobalWindow* outer = GetOuterWindowInternal();
   15368           9 :   MOZ_ASSERT_IF(outer, outer->TabGroup() == mTabGroup);
   15369             : #endif
   15370             : 
   15371           9 :   return mTabGroup;
   15372             : }
   15373             : 
   15374             : template<typename T>
   15375             : mozilla::dom::TabGroup*
   15376          36 : nsPIDOMWindow<T>::TabGroup()
   15377             : {
   15378             :   nsGlobalWindow* globalWindow =
   15379             :     static_cast<nsGlobalWindow*>(
   15380          36 :         reinterpret_cast<nsPIDOMWindow<nsISupports>*>(this));
   15381             : 
   15382          36 :   if (IsInnerWindow()) {
   15383           9 :     return globalWindow->TabGroupInner();
   15384             :   }
   15385          27 :   return globalWindow->TabGroupOuter();
   15386             : }
   15387             : 
   15388             : template<typename T>
   15389             : mozilla::dom::DocGroup*
   15390         686 : nsPIDOMWindow<T>::GetDocGroup() const
   15391             : {
   15392         686 :   nsIDocument* doc = GetExtantDoc();
   15393         686 :   if (doc) {
   15394         686 :     return doc->GetDocGroup();
   15395             :   }
   15396           0 :   return nullptr;
   15397             : }
   15398             : 
   15399             : nsresult
   15400          20 : nsGlobalWindow::Dispatch(const char* aName,
   15401             :                          TaskCategory aCategory,
   15402             :                          already_AddRefed<nsIRunnable>&& aRunnable)
   15403             : {
   15404          20 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   15405          20 :   if (GetDocGroup()) {
   15406          20 :     return GetDocGroup()->Dispatch(aName, aCategory, Move(aRunnable));
   15407             :   }
   15408           0 :   return DispatcherTrait::Dispatch(aName, aCategory, Move(aRunnable));
   15409             : }
   15410             : 
   15411             : nsISerialEventTarget*
   15412          16 : nsGlobalWindow::EventTargetFor(TaskCategory aCategory) const
   15413             : {
   15414          16 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   15415          16 :   if (GetDocGroup()) {
   15416          16 :     return GetDocGroup()->EventTargetFor(aCategory);
   15417             :   }
   15418           0 :   return DispatcherTrait::EventTargetFor(aCategory);
   15419             : }
   15420             : 
   15421             : AbstractThread*
   15422           0 : nsGlobalWindow::AbstractMainThreadFor(TaskCategory aCategory)
   15423             : {
   15424           0 :   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   15425           0 :   if (GetDocGroup()) {
   15426           0 :     return GetDocGroup()->AbstractMainThreadFor(aCategory);
   15427             :   }
   15428           0 :   return DispatcherTrait::AbstractMainThreadFor(aCategory);
   15429             : }
   15430             : 
   15431           5 : nsGlobalWindow::TemporarilyDisableDialogs::TemporarilyDisableDialogs(
   15432           5 :   nsGlobalWindow* aWindow MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   15433             : {
   15434           5 :   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
   15435             : 
   15436           5 :   MOZ_ASSERT(aWindow);
   15437           5 :   nsGlobalWindow* topWindow = aWindow->GetScriptableTopInternal();
   15438           5 :   if (!topWindow) {
   15439           0 :     NS_ERROR("nsGlobalWindow::TemporarilyDisableDialogs used without a top "
   15440             :              "window?");
   15441           0 :     return;
   15442             :   }
   15443             : 
   15444             :   // TODO: Warn if no top window?
   15445           5 :   topWindow = topWindow->GetCurrentInnerWindowInternal();
   15446           5 :   if (topWindow) {
   15447           5 :     mTopWindow = topWindow;
   15448           5 :     mSavedDialogsEnabled = mTopWindow->mAreDialogsEnabled;
   15449           5 :     mTopWindow->mAreDialogsEnabled = false;
   15450             :   }
   15451             : }
   15452             : 
   15453          10 : nsGlobalWindow::TemporarilyDisableDialogs::~TemporarilyDisableDialogs()
   15454             : {
   15455           5 :   if (mTopWindow) {
   15456           5 :     mTopWindow->mAreDialogsEnabled = mSavedDialogsEnabled;
   15457             :   }
   15458           5 : }
   15459             : 
   15460             : Worklet*
   15461           0 : nsGlobalWindow::GetAudioWorklet(ErrorResult& aRv)
   15462             : {
   15463           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   15464             : 
   15465           0 :   if (!mAudioWorklet) {
   15466           0 :     nsIPrincipal* principal = GetPrincipal();
   15467           0 :     if (!principal) {
   15468           0 :       aRv.Throw(NS_ERROR_FAILURE);
   15469           0 :       return nullptr;
   15470             :     }
   15471             : 
   15472           0 :     mAudioWorklet = new Worklet(AsInner(), principal, Worklet::eAudioWorklet);
   15473             :   }
   15474             : 
   15475           0 :   return mAudioWorklet;
   15476             : }
   15477             : 
   15478             : Worklet*
   15479           0 : nsGlobalWindow::GetPaintWorklet(ErrorResult& aRv)
   15480             : {
   15481           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   15482             : 
   15483           0 :   if (!mPaintWorklet) {
   15484           0 :     nsIPrincipal* principal = GetPrincipal();
   15485           0 :     if (!principal) {
   15486           0 :       aRv.Throw(NS_ERROR_FAILURE);
   15487           0 :       return nullptr;
   15488             :     }
   15489             : 
   15490           0 :     mPaintWorklet = new Worklet(AsInner(), principal, Worklet::ePaintWorklet);
   15491             :   }
   15492             : 
   15493           0 :   return mPaintWorklet;
   15494             : }
   15495             : 
   15496             : void
   15497           0 : nsGlobalWindow::GetAppLocalesAsBCP47(nsTArray<nsString>& aLocales)
   15498             : {
   15499           0 :   nsTArray<nsCString> appLocales;
   15500           0 :   mozilla::intl::LocaleService::GetInstance()->GetAppLocalesAsBCP47(appLocales);
   15501             : 
   15502           0 :   for (uint32_t i = 0; i < appLocales.Length(); i++) {
   15503           0 :     aLocales.AppendElement(NS_ConvertUTF8toUTF16(appLocales[i]));
   15504             :   }
   15505           0 : }
   15506             : 
   15507             : #ifdef ENABLE_INTL_API
   15508             : IntlUtils*
   15509           0 : nsGlobalWindow::GetIntlUtils(ErrorResult& aError)
   15510             : {
   15511           0 :   MOZ_RELEASE_ASSERT(IsInnerWindow());
   15512             : 
   15513           0 :   if (!mIntlUtils) {
   15514           0 :     mIntlUtils = new IntlUtils(AsInner());
   15515             :   }
   15516             : 
   15517           0 :   return mIntlUtils;
   15518             : }
   15519             : #endif
   15520             : 
   15521             : template class nsPIDOMWindow<mozIDOMWindowProxy>;
   15522             : template class nsPIDOMWindow<mozIDOMWindow>;
   15523             : template class nsPIDOMWindow<nsISupports>;

Generated by: LCOV version 1.13