LCOV - code coverage report
Current view: top level - xpfe/appshell - nsXULWindow.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 380 1116 34.1 %
Date: 2017-07-14 16:53:18 Functions: 47 98 48.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 ci et: */
       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 "mozilla/MathAlgorithms.h"
       8             : 
       9             : // Local includes
      10             : #include "nsXULWindow.h"
      11             : #include <algorithm>
      12             : 
      13             : // Helper classes
      14             : #include "nsPrintfCString.h"
      15             : #include "nsString.h"
      16             : #include "nsWidgetsCID.h"
      17             : #include "nsThreadUtils.h"
      18             : #include "nsNetCID.h"
      19             : #include "nsQueryObject.h"
      20             : #include "mozilla/Sprintf.h"
      21             : 
      22             : //Interfaces needed to be included
      23             : #include "nsIAppShell.h"
      24             : #include "nsIAppShellService.h"
      25             : #include "nsIServiceManager.h"
      26             : #include "nsIContentViewer.h"
      27             : #include "nsIDocument.h"
      28             : #include "nsIDOMDocument.h"
      29             : #include "nsIDOMXULDocument.h"
      30             : #include "nsIDOMElement.h"
      31             : #include "nsIDOMXULElement.h"
      32             : #include "nsPIDOMWindow.h"
      33             : #include "nsIDOMScreen.h"
      34             : #include "nsIEmbeddingSiteWindow.h"
      35             : #include "nsIInterfaceRequestor.h"
      36             : #include "nsIInterfaceRequestorUtils.h"
      37             : #include "nsIIOService.h"
      38             : #include "nsILoadContext.h"
      39             : #include "nsIObserverService.h"
      40             : #include "nsIWindowMediator.h"
      41             : #include "nsIScreenManager.h"
      42             : #include "nsIScreen.h"
      43             : #include "nsIScrollable.h"
      44             : #include "nsIScriptSecurityManager.h"
      45             : #include "nsIWindowWatcher.h"
      46             : #include "nsIURI.h"
      47             : #include "nsIDOMCSSStyleDeclaration.h"
      48             : #include "nsAppShellCID.h"
      49             : #include "nsReadableUtils.h"
      50             : #include "nsStyleConsts.h"
      51             : #include "nsPresContext.h"
      52             : #include "nsContentUtils.h"
      53             : #include "nsWebShellWindow.h" // get rid of this one, too...
      54             : #include "nsGlobalWindow.h"
      55             : 
      56             : #include "prenv.h"
      57             : #include "mozilla/AutoRestore.h"
      58             : #include "mozilla/Preferences.h"
      59             : #include "mozilla/Services.h"
      60             : #include "mozilla/dom/BarProps.h"
      61             : #include "mozilla/dom/Element.h"
      62             : #include "mozilla/dom/Event.h"
      63             : #include "mozilla/dom/ScriptSettings.h"
      64             : #include "mozilla/dom/TabParent.h"
      65             : 
      66             : using namespace mozilla;
      67             : using dom::AutoNoJSAPI;
      68             : 
      69             : #define SIZEMODE_NORMAL     NS_LITERAL_STRING("normal")
      70             : #define SIZEMODE_MAXIMIZED  NS_LITERAL_STRING("maximized")
      71             : #define SIZEMODE_MINIMIZED  NS_LITERAL_STRING("minimized")
      72             : #define SIZEMODE_FULLSCREEN NS_LITERAL_STRING("fullscreen")
      73             : 
      74             : #define WINDOWTYPE_ATTRIBUTE NS_LITERAL_STRING("windowtype")
      75             : 
      76             : #define PERSIST_ATTRIBUTE  NS_LITERAL_STRING("persist")
      77             : #define SCREENX_ATTRIBUTE  NS_LITERAL_STRING("screenX")
      78             : #define SCREENY_ATTRIBUTE  NS_LITERAL_STRING("screenY")
      79             : #define WIDTH_ATTRIBUTE    NS_LITERAL_STRING("width")
      80             : #define HEIGHT_ATTRIBUTE   NS_LITERAL_STRING("height")
      81             : #define MODE_ATTRIBUTE     NS_LITERAL_STRING("sizemode")
      82             : #define ZLEVEL_ATTRIBUTE   NS_LITERAL_STRING("zlevel")
      83             : 
      84             : 
      85             : //*****************************************************************************
      86             : //***    nsXULWindow: Object Management
      87             : //*****************************************************************************
      88             : 
      89           2 : nsXULWindow::nsXULWindow(uint32_t aChromeFlags)
      90             :   : mChromeTreeOwner(nullptr),
      91             :     mContentTreeOwner(nullptr),
      92             :     mPrimaryContentTreeOwner(nullptr),
      93             :     mModalStatus(NS_OK),
      94             :     mContinueModalLoop(false),
      95             :     mDebuting(false),
      96             :     mChromeLoaded(false),
      97             :     mShowAfterLoad(false),
      98             :     mIntrinsicallySized(false),
      99             :     mCenterAfterLoad(false),
     100             :     mIsHiddenWindow(false),
     101             :     mLockedUntilChromeLoad(false),
     102             :     mIgnoreXULSize(false),
     103             :     mIgnoreXULPosition(false),
     104             :     mChromeFlagsFrozen(false),
     105             :     mIgnoreXULSizeMode(false),
     106             :     mDestroying(false),
     107             :     mRegistered(false),
     108             :     mPersistentAttributesDirty(0),
     109             :     mPersistentAttributesMask(0),
     110             :     mChromeFlags(aChromeFlags),
     111           2 :     mNextTabParentId(0)
     112             : {
     113           2 : }
     114             : 
     115           0 : nsXULWindow::~nsXULWindow()
     116             : {
     117           0 :   Destroy();
     118           0 : }
     119             : 
     120             : //*****************************************************************************
     121             : // nsXULWindow::nsISupports
     122             : //*****************************************************************************
     123             : 
     124          44 : NS_IMPL_ADDREF(nsXULWindow)
     125          40 : NS_IMPL_RELEASE(nsXULWindow)
     126             : 
     127          29 : NS_INTERFACE_MAP_BEGIN(nsXULWindow)
     128          29 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULWindow)
     129          28 :   NS_INTERFACE_MAP_ENTRY(nsIXULWindow)
     130          11 :   NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
     131          11 :   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
     132           8 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     133           6 :   if (aIID.Equals(NS_GET_IID(nsXULWindow)))
     134           0 :     foundInterface = reinterpret_cast<nsISupports*>(this);
     135             :   else
     136           6 : NS_INTERFACE_MAP_END
     137             : 
     138             : //*****************************************************************************
     139             : // nsXULWindow::nsIIntefaceRequestor
     140             : //*****************************************************************************
     141             : 
     142          17 : NS_IMETHODIMP nsXULWindow::GetInterface(const nsIID& aIID, void** aSink)
     143             : {
     144             :   nsresult rv;
     145             : 
     146          17 :   NS_ENSURE_ARG_POINTER(aSink);
     147             : 
     148          17 :   if (aIID.Equals(NS_GET_IID(nsIPrompt))) {
     149           0 :     rv = EnsurePrompter();
     150           0 :     if (NS_FAILED(rv)) return rv;
     151           0 :     return mPrompter->QueryInterface(aIID, aSink);
     152             :   }
     153          17 :   if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
     154           0 :     rv = EnsureAuthPrompter();
     155           0 :     if (NS_FAILED(rv)) return rv;
     156           0 :     return mAuthPrompter->QueryInterface(aIID, aSink);
     157             :   }
     158          17 :   if (aIID.Equals(NS_GET_IID(mozIDOMWindowProxy))) {
     159           2 :     return GetWindowDOMWindow(reinterpret_cast<mozIDOMWindowProxy**>(aSink));
     160             :   }
     161          15 :   if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
     162           0 :     nsCOMPtr<mozIDOMWindowProxy> window = nullptr;
     163           0 :     rv = GetWindowDOMWindow(getter_AddRefs(window));
     164           0 :     nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(window);
     165           0 :     domWindow.forget(aSink);
     166           0 :     return rv;
     167             :   }
     168          15 :   if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) {
     169           0 :     nsCOMPtr<mozIDOMWindowProxy> window = nullptr;
     170           0 :     rv = GetWindowDOMWindow(getter_AddRefs(window));
     171           0 :     nsCOMPtr<nsIDOMWindowInternal> domWindowInternal = do_QueryInterface(window);
     172           0 :     domWindowInternal.forget(aSink);
     173           0 :     return rv;
     174             :   }
     175          45 :   if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome)) &&
     176          30 :     NS_SUCCEEDED(EnsureContentTreeOwner()) &&
     177          15 :     NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
     178          15 :     return NS_OK;
     179             : 
     180           0 :   if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow)) &&
     181           0 :     NS_SUCCEEDED(EnsureContentTreeOwner()) &&
     182           0 :     NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
     183           0 :     return NS_OK;
     184             : 
     185           0 :   return QueryInterface(aIID, aSink);
     186             : }
     187             : 
     188             : //*****************************************************************************
     189             : // nsXULWindow::nsIXULWindow
     190             : //*****************************************************************************
     191             : 
     192          13 : NS_IMETHODIMP nsXULWindow::GetDocShell(nsIDocShell** aDocShell)
     193             : {
     194          13 :   NS_ENSURE_ARG_POINTER(aDocShell);
     195             : 
     196          13 :   *aDocShell = mDocShell;
     197          13 :   NS_IF_ADDREF(*aDocShell);
     198          13 :   return NS_OK;
     199             : }
     200             : 
     201           1 : NS_IMETHODIMP nsXULWindow::GetZLevel(uint32_t *outLevel)
     202             : {
     203           2 :   nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
     204           1 :   if (mediator)
     205           1 :     mediator->GetZLevel(this, outLevel);
     206             :   else
     207           0 :     *outLevel = normalZ;
     208           2 :   return NS_OK;
     209             : }
     210             : 
     211           1 : NS_IMETHODIMP nsXULWindow::SetZLevel(uint32_t aLevel)
     212             : {
     213           2 :   nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
     214           1 :   if (!mediator)
     215           0 :     return NS_ERROR_FAILURE;
     216             : 
     217             :   uint32_t zLevel;
     218           1 :   mediator->GetZLevel(this, &zLevel);
     219           1 :   if (zLevel == aLevel)
     220           1 :     return NS_OK;
     221             : 
     222             :   /* refuse to raise a maximized window above the normal browser level,
     223             :      for fear it could hide newly opened browser windows */
     224           0 :   if (aLevel > nsIXULWindow::normalZ && mWindow) {
     225           0 :     nsSizeMode sizeMode = mWindow->SizeMode();
     226           0 :     if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) {
     227           0 :       return NS_ERROR_FAILURE;
     228             :     }
     229             :   }
     230             : 
     231             :   // do it
     232           0 :   mediator->SetZLevel(this, aLevel);
     233           0 :   PersistentAttributesDirty(PAD_MISC);
     234           0 :   SavePersistentAttributes();
     235             : 
     236           0 :   nsCOMPtr<nsIContentViewer> cv;
     237           0 :   mDocShell->GetContentViewer(getter_AddRefs(cv));
     238           0 :   if (cv) {
     239           0 :     nsCOMPtr<nsIDocument> doc = cv->GetDocument();
     240           0 :     if (doc) {
     241           0 :       ErrorResult rv;
     242             :       RefPtr<dom::Event> event =
     243           0 :         doc->CreateEvent(NS_LITERAL_STRING("Events"), dom::CallerType::System,
     244           0 :                          rv);
     245           0 :       if (event) {
     246           0 :         event->InitEvent(NS_LITERAL_STRING("windowZLevel"), true, false);
     247             : 
     248           0 :         event->SetTrusted(true);
     249             : 
     250             :         bool defaultActionEnabled;
     251           0 :         doc->DispatchEvent(event, &defaultActionEnabled);
     252             :       }
     253             :     }
     254             :   }
     255           0 :   return NS_OK;
     256             : }
     257             : 
     258          11 : NS_IMETHODIMP nsXULWindow::GetChromeFlags(uint32_t *aChromeFlags)
     259             : {
     260          11 :   NS_ENSURE_ARG_POINTER(aChromeFlags);
     261          11 :   *aChromeFlags = mChromeFlags;
     262             :   /* mChromeFlags is kept up to date, except for scrollbar visibility.
     263             :      That can be changed directly by the content DOM window, which
     264             :      doesn't know to update the chrome window. So that we must check
     265             :      separately. */
     266             : 
     267             :   // however, it's pointless to ask if the window isn't set up yet
     268          11 :   if (!mChromeLoaded)
     269           9 :     return NS_OK;
     270             : 
     271           2 :   if (GetContentScrollbarVisibility())
     272           2 :     *aChromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS;
     273             :   else
     274           0 :     *aChromeFlags &= ~nsIWebBrowserChrome::CHROME_SCROLLBARS;
     275             : 
     276           2 :   return NS_OK;
     277             : }
     278             : 
     279           0 : NS_IMETHODIMP nsXULWindow::SetChromeFlags(uint32_t aChromeFlags)
     280             : {
     281           0 :   NS_ASSERTION(!mChromeFlagsFrozen,
     282             :                "SetChromeFlags() after AssumeChromeFlagsAreFrozen()!");
     283             : 
     284           0 :   mChromeFlags = aChromeFlags;
     285           0 :   if (mChromeLoaded)
     286           0 :     NS_ENSURE_SUCCESS(ApplyChromeFlags(), NS_ERROR_FAILURE);
     287           0 :   return NS_OK;
     288             : }
     289             : 
     290           0 : NS_IMETHODIMP nsXULWindow::AssumeChromeFlagsAreFrozen()
     291             : {
     292           0 :   mChromeFlagsFrozen = true;
     293           0 :   return NS_OK;
     294             : }
     295             : 
     296           1 : NS_IMETHODIMP nsXULWindow::SetIntrinsicallySized(bool aIntrinsicallySized)
     297             : {
     298           1 :   mIntrinsicallySized = aIntrinsicallySized;
     299           1 :   return NS_OK;
     300             : }
     301             : 
     302           0 : NS_IMETHODIMP nsXULWindow::GetIntrinsicallySized(bool* aIntrinsicallySized)
     303             : {
     304           0 :   NS_ENSURE_ARG_POINTER(aIntrinsicallySized);
     305             : 
     306           0 :   *aIntrinsicallySized = mIntrinsicallySized;
     307           0 :   return NS_OK;
     308             : }
     309             : 
     310          26 : NS_IMETHODIMP nsXULWindow::GetPrimaryContentShell(nsIDocShellTreeItem**
     311             :    aDocShellTreeItem)
     312             : {
     313          26 :   NS_ENSURE_ARG_POINTER(aDocShellTreeItem);
     314          26 :   NS_IF_ADDREF(*aDocShellTreeItem = mPrimaryContentShell);
     315          26 :   return NS_OK;
     316             : }
     317             : 
     318             : NS_IMETHODIMP
     319           1 : nsXULWindow::TabParentAdded(nsITabParent* aTab, bool aPrimary)
     320             : {
     321           1 :   if (aPrimary) {
     322           1 :     mPrimaryTabParent = aTab;
     323           1 :     mPrimaryContentShell = nullptr;
     324           0 :   } else if (mPrimaryTabParent == aTab) {
     325           0 :     mPrimaryTabParent = nullptr;
     326             :   }
     327             : 
     328           1 :   return NS_OK;
     329             : }
     330             : 
     331             : NS_IMETHODIMP
     332           1 : nsXULWindow::TabParentRemoved(nsITabParent* aTab)
     333             : {
     334           1 :   if (aTab == mPrimaryTabParent) {
     335           0 :     mPrimaryTabParent = nullptr;
     336             :   }
     337             : 
     338           1 :   return NS_OK;
     339             : }
     340             : 
     341             : NS_IMETHODIMP
     342           0 : nsXULWindow::GetPrimaryTabParent(nsITabParent** aTab)
     343             : {
     344           0 :   nsCOMPtr<nsITabParent> tab = mPrimaryTabParent;
     345           0 :   tab.forget(aTab);
     346           0 :   return NS_OK;
     347             : }
     348             : 
     349             : nsTArray<RefPtr<mozilla::LiveResizeListener>>
     350           0 : nsXULWindow::GetLiveResizeListeners()
     351             : {
     352           0 :   nsTArray<RefPtr<mozilla::LiveResizeListener>> listeners;
     353           0 :   if (mPrimaryTabParent) {
     354           0 :     TabParent* parent = static_cast<TabParent*>(mPrimaryTabParent.get());
     355           0 :     listeners.AppendElement(parent);
     356             :   }
     357           0 :   return listeners;
     358             : }
     359             : 
     360           0 : NS_IMETHODIMP nsXULWindow::AddChildWindow(nsIXULWindow *aChild)
     361             : {
     362             :   // we're not really keeping track of this right now
     363           0 :   return NS_OK;
     364             : }
     365             : 
     366           0 : NS_IMETHODIMP nsXULWindow::RemoveChildWindow(nsIXULWindow *aChild)
     367             : {
     368             :   // we're not really keeping track of this right now
     369           0 :   return NS_OK;
     370             : }
     371             : 
     372           0 : NS_IMETHODIMP nsXULWindow::ShowModal()
     373             : {
     374           0 :   AUTO_PROFILER_LABEL("nsXULWindow::ShowModal", OTHER);
     375             : 
     376             :   // Store locally so it doesn't die on us
     377           0 :   nsCOMPtr<nsIWidget> window = mWindow;
     378           0 :   nsCOMPtr<nsIXULWindow> tempRef = this;
     379             : 
     380           0 :   window->SetModal(true);
     381           0 :   mContinueModalLoop = true;
     382           0 :   EnableParent(false);
     383             : 
     384             :   {
     385           0 :     AutoNoJSAPI nojsapi;
     386           0 :     SpinEventLoopUntil([&]() { return !mContinueModalLoop; });
     387             :   }
     388             : 
     389           0 :   mContinueModalLoop = false;
     390           0 :   window->SetModal(false);
     391             :   /*   Note there's no EnableParent(true) here to match the false one
     392             :      above. That's done in ExitModalLoop. It's important that the parent
     393             :      be re-enabled before this window is made invisible; to do otherwise
     394             :      causes bizarre z-ordering problems. At this point, the window is
     395             :      already invisible.
     396             :        No known current implementation of Enable would have a problem with
     397             :      re-enabling the parent twice, so we could do it again here without
     398             :      breaking any current implementation. But that's unnecessary if the
     399             :      modal loop is always exited using ExitModalLoop (the other way would be
     400             :      to change the protected member variable directly.)
     401             :   */
     402             : 
     403           0 :   return mModalStatus;
     404             : }
     405             : 
     406             : //*****************************************************************************
     407             : // nsXULWindow::nsIBaseWindow
     408             : //*****************************************************************************
     409             : 
     410           0 : NS_IMETHODIMP nsXULWindow::InitWindow(nativeWindow aParentNativeWindow,
     411             :    nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy)
     412             : {
     413             :   //XXX First Check In
     414           0 :   NS_ASSERTION(false, "Not Yet Implemented");
     415           0 :   return NS_OK;
     416             : }
     417             : 
     418           0 : NS_IMETHODIMP nsXULWindow::Create()
     419             : {
     420             :   //XXX First Check In
     421           0 :   NS_ASSERTION(false, "Not Yet Implemented");
     422           0 :   return NS_OK;
     423             : }
     424             : 
     425           0 : NS_IMETHODIMP nsXULWindow::Destroy()
     426             : {
     427           0 :   if (!mWindow)
     428           0 :      return NS_OK;
     429             : 
     430             :   // Ensure we don't reenter this code
     431           0 :   if (mDestroying)
     432           0 :     return NS_OK;
     433             : 
     434           0 :   mozilla::AutoRestore<bool> guard(mDestroying);
     435           0 :   mDestroying = true;
     436             : 
     437           0 :   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
     438           0 :   NS_ASSERTION(appShell, "Couldn't get appShell... xpcom shutdown?");
     439           0 :   if (appShell)
     440           0 :     appShell->UnregisterTopLevelWindow(static_cast<nsIXULWindow*>(this));
     441             : 
     442           0 :   nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow));
     443           0 :   if (parentWindow)
     444           0 :     parentWindow->RemoveChildWindow(this);
     445             : 
     446             :   // let's make sure the window doesn't get deleted out from under us
     447             :   // while we are trying to close....this can happen if the docshell
     448             :   // we close ends up being the last owning reference to this xulwindow
     449             : 
     450             :   // XXXTAB This shouldn't be an issue anymore because the ownership model
     451             :   // only goes in one direction.  When webshell container is fully removed
     452             :   // try removing this...
     453             : 
     454           0 :   nsCOMPtr<nsIXULWindow> placeHolder = this;
     455             : 
     456             :   // Remove modality (if any) and hide while destroying. More than
     457             :   // a convenience, the hide prevents user interaction with the partially
     458             :   // destroyed window. This is especially necessary when the eldest window
     459             :   // in a stack of modal windows is destroyed first. It happens.
     460           0 :   ExitModalLoop(NS_OK);
     461             :   // XXX: Skip unmapping the window on Linux due to GLX hangs on the compositor
     462             :   // thread with NVIDIA driver 310.32. We don't need to worry about user
     463             :   // interactions with destroyed windows on X11 either.
     464             : #ifndef MOZ_WIDGET_GTK
     465             :   if (mWindow)
     466             :     mWindow->Show(false);
     467             : #endif
     468             : 
     469             : #if defined(XP_WIN)
     470             :   // We need to explicitly set the focus on Windows, but
     471             :   // only if the parent is visible.
     472             :   nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
     473             :   if (parent) {
     474             :     nsCOMPtr<nsIWidget> parentWidget;
     475             :     parent->GetMainWidget(getter_AddRefs(parentWidget));
     476             :     if (!parentWidget || parentWidget->IsVisible()) {
     477             :       nsCOMPtr<nsIBaseWindow> baseHiddenWindow;
     478             :       if (appShell) {
     479             :         nsCOMPtr<nsIXULWindow> hiddenWindow;
     480             :         appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
     481             :         if (hiddenWindow)
     482             :           baseHiddenWindow = do_GetInterface(hiddenWindow);
     483             :       }
     484             :       // somebody screwed up somewhere. hiddenwindow shouldn't be anybody's
     485             :       // parent. still, when it happens, skip activating it.
     486             :       if (baseHiddenWindow != parent) {
     487             :         nsCOMPtr<nsIWidget> parentWidget;
     488             :         parent->GetMainWidget(getter_AddRefs(parentWidget));
     489             :         if (parentWidget)
     490             :           parentWidget->PlaceBehind(eZPlacementTop, 0, true);
     491             :       }
     492             :     }
     493             :   }
     494             : #endif
     495             : 
     496           0 :   mDOMWindow = nullptr;
     497           0 :   if (mDocShell) {
     498           0 :     nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
     499           0 :     shellAsWin->Destroy();
     500           0 :     mDocShell = nullptr; // this can cause reentrancy of this function
     501             :   }
     502             : 
     503           0 :   mPrimaryContentShell = nullptr;
     504             : 
     505           0 :   if (mContentTreeOwner) {
     506           0 :     mContentTreeOwner->XULWindow(nullptr);
     507           0 :     NS_RELEASE(mContentTreeOwner);
     508             :   }
     509           0 :   if (mPrimaryContentTreeOwner) {
     510           0 :     mPrimaryContentTreeOwner->XULWindow(nullptr);
     511           0 :     NS_RELEASE(mPrimaryContentTreeOwner);
     512             :   }
     513           0 :   if (mChromeTreeOwner) {
     514           0 :     mChromeTreeOwner->XULWindow(nullptr);
     515           0 :     NS_RELEASE(mChromeTreeOwner);
     516             :   }
     517           0 :   if (mWindow) {
     518           0 :     mWindow->SetWidgetListener(nullptr); // nsWebShellWindow hackery
     519           0 :     mWindow->Destroy();
     520           0 :     mWindow = nullptr;
     521             :   }
     522             : 
     523           0 :   if (!mIsHiddenWindow && mRegistered) {
     524             :     /* Inform appstartup we've destroyed this window and it could
     525             :        quit now if it wanted. This must happen at least after mDocShell
     526             :        is destroyed, because onunload handlers fire then, and those being
     527             :        script, anything could happen. A new window could open, even.
     528             :        See bug 130719. */
     529           0 :     nsCOMPtr<nsIObserverService> obssvc = services::GetObserverService();
     530           0 :     NS_ASSERTION(obssvc, "Couldn't get observer service?");
     531             : 
     532           0 :     if (obssvc)
     533           0 :       obssvc->NotifyObservers(nullptr, "xul-window-destroyed", nullptr);
     534             :   }
     535             : 
     536           0 :   return NS_OK;
     537             : }
     538             : 
     539           0 : NS_IMETHODIMP nsXULWindow::GetDevicePixelsPerDesktopPixel(double *aScale)
     540             : {
     541           0 :   *aScale = mWindow ? mWindow->GetDesktopToDeviceScale().scale : 1.0;
     542           0 :   return NS_OK;
     543             : }
     544             : 
     545           1 : NS_IMETHODIMP nsXULWindow::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
     546             : {
     547           1 :   *aScale = mWindow ? mWindow->GetDefaultScale().scale : 1.0;
     548           1 :   return NS_OK;
     549             : }
     550             : 
     551           0 : NS_IMETHODIMP nsXULWindow::SetPositionDesktopPix(int32_t aX, int32_t aY)
     552             : {
     553           0 :   mWindow->Move(aX, aY);
     554           0 :   if (!mChromeLoaded) {
     555             :     // If we're called before the chrome is loaded someone obviously wants this
     556             :     // window at this position. We don't persist this one-time position.
     557           0 :     mIgnoreXULPosition = true;
     558           0 :     return NS_OK;
     559             :   }
     560           0 :   PersistentAttributesDirty(PAD_POSITION);
     561           0 :   SavePersistentAttributes();
     562           0 :   return NS_OK;
     563             : }
     564             : 
     565             : // The parameters here are device pixels; do the best we can to convert to
     566             : // desktop px, using the window's current scale factor (if available).
     567           0 : NS_IMETHODIMP nsXULWindow::SetPosition(int32_t aX, int32_t aY)
     568             : {
     569             :   // Don't reset the window's size mode here - platforms that don't want to move
     570             :   // maximized windows should reset it in their respective Move implementation.
     571           0 :   DesktopToLayoutDeviceScale currScale = mWindow->GetDesktopToDeviceScale();
     572           0 :   DesktopPoint pos = LayoutDeviceIntPoint(aX, aY) / currScale;
     573           0 :   return SetPositionDesktopPix(pos.x, pos.y);
     574             : }
     575             : 
     576           9 : NS_IMETHODIMP nsXULWindow::GetPosition(int32_t* aX, int32_t* aY)
     577             : {
     578           9 :   return GetPositionAndSize(aX, aY, nullptr, nullptr);
     579             : }
     580             : 
     581           1 : NS_IMETHODIMP nsXULWindow::SetSize(int32_t aCX, int32_t aCY, bool aRepaint)
     582             : {
     583             :   /* any attempt to set the window's size or position overrides the window's
     584             :      zoom state. this is important when these two states are competing while
     585             :      the window is being opened. but it should probably just always be so. */
     586           1 :   mWindow->SetSizeMode(nsSizeMode_Normal);
     587             : 
     588           1 :   mIntrinsicallySized = false;
     589             : 
     590           1 :   DesktopToLayoutDeviceScale scale = mWindow->GetDesktopToDeviceScale();
     591           1 :   DesktopSize size = LayoutDeviceIntSize(aCX, aCY) / scale;
     592           1 :   mWindow->Resize(size.width, size.height, aRepaint);
     593           1 :   if (!mChromeLoaded) {
     594             :     // If we're called before the chrome is loaded someone obviously wants this
     595             :     // window at this size & in the normal size mode (since it is the only mode
     596             :     // in which setting dimensions makes sense). We don't persist this one-time
     597             :     // size.
     598           0 :     mIgnoreXULSize = true;
     599           0 :     mIgnoreXULSizeMode = true;
     600           0 :     return NS_OK;
     601             :   }
     602           1 :   PersistentAttributesDirty(PAD_SIZE);
     603           1 :   SavePersistentAttributes();
     604           1 :   return NS_OK;
     605             : }
     606             : 
     607          10 : NS_IMETHODIMP nsXULWindow::GetSize(int32_t* aCX, int32_t* aCY)
     608             : {
     609          10 :   return GetPositionAndSize(nullptr, nullptr, aCX, aCY);
     610             : }
     611             : 
     612           0 : NS_IMETHODIMP nsXULWindow::SetPositionAndSize(int32_t aX, int32_t aY,
     613             :    int32_t aCX, int32_t aCY, uint32_t aFlags)
     614             : {
     615             :   /* any attempt to set the window's size or position overrides the window's
     616             :      zoom state. this is important when these two states are competing while
     617             :      the window is being opened. but it should probably just always be so. */
     618           0 :   mWindow->SetSizeMode(nsSizeMode_Normal);
     619             : 
     620           0 :   mIntrinsicallySized = false;
     621             : 
     622           0 :   DesktopToLayoutDeviceScale scale = mWindow->GetDesktopToDeviceScale();
     623           0 :   DesktopRect rect = LayoutDeviceIntRect(aX, aY, aCX, aCY) / scale;
     624           0 :   mWindow->Resize(rect.x, rect.y, rect.width, rect.height,
     625           0 :                   !!(aFlags & nsIBaseWindow::eRepaint));
     626           0 :   if (!mChromeLoaded) {
     627             :     // If we're called before the chrome is loaded someone obviously wants this
     628             :     // window at this size and position. We don't persist this one-time setting.
     629           0 :     mIgnoreXULPosition = true;
     630           0 :     mIgnoreXULSize = true;
     631           0 :     mIgnoreXULSizeMode = true;
     632           0 :     return NS_OK;
     633             :   }
     634           0 :   PersistentAttributesDirty(PAD_POSITION | PAD_SIZE);
     635           0 :   SavePersistentAttributes();
     636           0 :   return NS_OK;
     637             : }
     638             : 
     639          20 : NS_IMETHODIMP nsXULWindow::GetPositionAndSize(int32_t* x, int32_t* y, int32_t* cx,
     640             :    int32_t* cy)
     641             : {
     642             : 
     643          20 :   if (!mWindow)
     644           0 :     return NS_ERROR_FAILURE;
     645             : 
     646          20 :   LayoutDeviceIntRect rect = mWindow->GetScreenBounds();
     647             : 
     648          20 :   if (x)
     649          10 :     *x = rect.x;
     650          20 :   if (y)
     651          10 :     *y = rect.y;
     652          20 :   if (cx)
     653          11 :     *cx = rect.width;
     654          20 :   if (cy)
     655          11 :     *cy = rect.height;
     656             : 
     657          20 :   return NS_OK;
     658             : }
     659             : 
     660           0 : NS_IMETHODIMP nsXULWindow::Center(nsIXULWindow *aRelative, bool aScreen, bool aAlert)
     661             : {
     662             :   int32_t  left, top, width, height,
     663             :            ourWidth, ourHeight;
     664           0 :   bool     screenCoordinates =  false,
     665           0 :            windowCoordinates =  false;
     666             :   nsresult result;
     667             : 
     668           0 :   if (!mChromeLoaded) {
     669             :     // note we lose the parameters. at time of writing, this isn't a problem.
     670           0 :     mCenterAfterLoad = true;
     671           0 :     return NS_OK;
     672             :   }
     673             : 
     674           0 :   if (!aScreen && !aRelative)
     675           0 :     return NS_ERROR_INVALID_ARG;
     676             : 
     677           0 :   nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1", &result);
     678           0 :   if (NS_FAILED(result))
     679           0 :     return result;
     680             : 
     681           0 :   nsCOMPtr<nsIScreen> screen;
     682             : 
     683           0 :   if (aRelative) {
     684           0 :     nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aRelative, &result));
     685           0 :     if (base) {
     686             :       // get window rect
     687           0 :       result = base->GetPositionAndSize(&left, &top, &width, &height);
     688           0 :       if (NS_SUCCEEDED(result)) {
     689             :         double scale;
     690           0 :         if (NS_SUCCEEDED(base->GetDevicePixelsPerDesktopPixel(&scale))) {
     691           0 :           left = NSToIntRound(left / scale);
     692           0 :           top = NSToIntRound(top / scale);
     693           0 :           width = NSToIntRound(width / scale);
     694           0 :           height = NSToIntRound(height / scale);
     695             :         }
     696             :         // if centering on screen, convert that to the corresponding screen
     697           0 :         if (aScreen)
     698           0 :           screenmgr->ScreenForRect(left, top, width, height, getter_AddRefs(screen));
     699             :         else
     700           0 :           windowCoordinates = true;
     701             :       } else {
     702             :         // something's wrong with the reference window.
     703             :         // fall back to the primary screen
     704           0 :         aRelative = 0;
     705           0 :         aScreen = true;
     706             :       }
     707             :     }
     708             :   }
     709           0 :   if (!aRelative) {
     710           0 :     if (!mOpenerScreenRect.IsEmpty()) {
     711             :       // FIXME - check if these are device or display pixels
     712           0 :       screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
     713             :                                mOpenerScreenRect.width, mOpenerScreenRect.height,
     714           0 :                                getter_AddRefs(screen));
     715             :     } else {
     716           0 :       screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
     717             :     }
     718             :   }
     719             : 
     720           0 :   if (aScreen && screen) {
     721           0 :     screen->GetAvailRectDisplayPix(&left, &top, &width, &height);
     722           0 :     screenCoordinates = true;
     723             :   }
     724             : 
     725           0 :   if (screenCoordinates || windowCoordinates) {
     726           0 :     NS_ASSERTION(mWindow, "what, no window?");
     727           0 :     double scale = mWindow->GetDesktopToDeviceScale().scale;
     728           0 :     GetSize(&ourWidth, &ourHeight);
     729             :     int32_t scaledWidth, scaledHeight;
     730           0 :     scaledWidth = NSToIntRound(ourWidth / scale);
     731           0 :     scaledHeight = NSToIntRound(ourHeight / scale);
     732           0 :     left += (width - scaledWidth) / 2;
     733           0 :     top += (height - scaledHeight) / (aAlert ? 3 : 2);
     734           0 :     if (windowCoordinates) {
     735           0 :       mWindow->ConstrainPosition(false, &left, &top);
     736             :     }
     737           0 :     SetPosition(left * scale, top * scale);
     738             : 
     739             :     // If moving the window caused it to change size,
     740             :     // re-do the centering.
     741             :     int32_t newWidth, newHeight;
     742           0 :     GetSize(&newWidth, &newHeight);
     743           0 :     if (newWidth != ourWidth || newHeight != ourHeight) {
     744           0 :       return Center(aRelative, aScreen, aAlert);
     745             :     }
     746           0 :     return NS_OK;
     747             :   }
     748             : 
     749           0 :   return NS_ERROR_FAILURE;
     750             : }
     751             : 
     752           0 : NS_IMETHODIMP nsXULWindow::Repaint(bool aForce)
     753             : {
     754             :   //XXX First Check In
     755           0 :   NS_ASSERTION(false, "Not Yet Implemented");
     756           0 :   return NS_OK;
     757             : }
     758             : 
     759           0 : NS_IMETHODIMP nsXULWindow::GetParentWidget(nsIWidget** aParentWidget)
     760             : {
     761           0 :   NS_ENSURE_ARG_POINTER(aParentWidget);
     762           0 :   NS_ENSURE_STATE(mWindow);
     763             : 
     764           0 :   NS_IF_ADDREF(*aParentWidget = mWindow->GetParent());
     765           0 :   return NS_OK;
     766             : }
     767             : 
     768           0 : NS_IMETHODIMP nsXULWindow::SetParentWidget(nsIWidget* aParentWidget)
     769             : {
     770             :   //XXX First Check In
     771           0 :   NS_ASSERTION(false, "Not Yet Implemented");
     772           0 :   return NS_OK;
     773             : }
     774             : 
     775           0 : NS_IMETHODIMP nsXULWindow::GetParentNativeWindow(nativeWindow* aParentNativeWindow)
     776             : {
     777           0 :   NS_ENSURE_ARG_POINTER(aParentNativeWindow);
     778             : 
     779           0 :   nsCOMPtr<nsIWidget> parentWidget;
     780           0 :   NS_ENSURE_SUCCESS(GetParentWidget(getter_AddRefs(parentWidget)), NS_ERROR_FAILURE);
     781             : 
     782           0 :   if (parentWidget) {
     783           0 :     *aParentNativeWindow = parentWidget->GetNativeData(NS_NATIVE_WIDGET);
     784             :   }
     785             : 
     786           0 :   return NS_OK;
     787             : }
     788             : 
     789           0 : NS_IMETHODIMP nsXULWindow::SetParentNativeWindow(nativeWindow aParentNativeWindow)
     790             : {
     791             :   //XXX First Check In
     792           0 :   NS_ASSERTION(false, "Not Yet Implemented");
     793           0 :   return NS_OK;
     794             : }
     795             : 
     796           0 : NS_IMETHODIMP nsXULWindow::GetNativeHandle(nsAString& aNativeHandle)
     797             : {
     798           0 :   nsCOMPtr<nsIWidget> mainWidget;
     799           0 :   NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(mainWidget)), NS_ERROR_FAILURE);
     800             : 
     801           0 :   if (mainWidget) {
     802           0 :     nativeWindow nativeWindowPtr = mainWidget->GetNativeData(NS_NATIVE_WINDOW);
     803             :     /* the nativeWindow pointer is converted to and exposed as a string. This
     804             :        is a more reliable way not to lose information (as opposed to JS
     805             :        |Number| for instance) */
     806           0 :     aNativeHandle = NS_ConvertASCIItoUTF16(nsPrintfCString("0x%p", nativeWindowPtr));
     807             :   }
     808             : 
     809           0 :   return NS_OK;
     810             : }
     811             : 
     812           3 : NS_IMETHODIMP nsXULWindow::GetVisibility(bool* aVisibility)
     813             : {
     814           3 :   NS_ENSURE_ARG_POINTER(aVisibility);
     815             : 
     816             :   // Always claim to be visible for now. See bug
     817             :   // https://bugzilla.mozilla.org/show_bug.cgi?id=306245.
     818             : 
     819           3 :   *aVisibility = true;
     820             : 
     821           3 :   return NS_OK;
     822             : }
     823             : 
     824           2 : NS_IMETHODIMP nsXULWindow::SetVisibility(bool aVisibility)
     825             : {
     826           2 :   if (!mChromeLoaded) {
     827           1 :     mShowAfterLoad = aVisibility;
     828           1 :     return NS_OK;
     829             :   }
     830             : 
     831           1 :   if (mDebuting) {
     832           0 :     return NS_OK;
     833             :   }
     834           1 :   mDebuting = true;  // (Show / Focus is recursive)
     835             : 
     836             :   //XXXTAB Do we really need to show docshell and the window?  Isn't
     837             :   // the window good enough?
     838           2 :   nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
     839           1 :   shellAsWin->SetVisibility(aVisibility);
     840             :   // Store locally so it doesn't die on us. 'Show' can result in the window
     841             :   // being closed with nsXULWindow::Destroy being called. That would set
     842             :   // mWindow to null and posibly destroy the nsIWidget while its Show method
     843             :   // is on the stack. We need to keep it alive until Show finishes.
     844           2 :   nsCOMPtr<nsIWidget> window = mWindow;
     845           1 :   window->Show(aVisibility);
     846             : 
     847           2 :   nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
     848           1 :   if (windowMediator)
     849           1 :      windowMediator->UpdateWindowTimeStamp(static_cast<nsIXULWindow*>(this));
     850             : 
     851             :   // notify observers so that we can hide the splash screen if possible
     852           2 :   nsCOMPtr<nsIObserverService> obssvc = services::GetObserverService();
     853           1 :   NS_ASSERTION(obssvc, "Couldn't get observer service.");
     854           1 :   if (obssvc) {
     855           1 :     obssvc->NotifyObservers(nullptr, "xul-window-visible", nullptr);
     856             :   }
     857             : 
     858           1 :   mDebuting = false;
     859           1 :   return NS_OK;
     860             : }
     861             : 
     862           1 : NS_IMETHODIMP nsXULWindow::GetEnabled(bool *aEnabled)
     863             : {
     864           1 :   NS_ENSURE_ARG_POINTER(aEnabled);
     865             : 
     866           1 :   if (mWindow) {
     867           1 :     *aEnabled = mWindow->IsEnabled();
     868           1 :     return NS_OK;
     869             :   }
     870             : 
     871           0 :   *aEnabled = true; // better guess than most
     872           0 :   return NS_ERROR_FAILURE;
     873             : }
     874             : 
     875           0 : NS_IMETHODIMP nsXULWindow::SetEnabled(bool aEnable)
     876             : {
     877           0 :   if (mWindow) {
     878           0 :     mWindow->Enable(aEnable);
     879           0 :     return NS_OK;
     880             :   }
     881           0 :   return NS_ERROR_FAILURE;
     882             : }
     883             : 
     884           0 : NS_IMETHODIMP nsXULWindow::GetMainWidget(nsIWidget** aMainWidget)
     885             : {
     886           0 :   NS_ENSURE_ARG_POINTER(aMainWidget);
     887             : 
     888           0 :   *aMainWidget = mWindow;
     889           0 :   NS_IF_ADDREF(*aMainWidget);
     890           0 :   return NS_OK;
     891             : }
     892             : 
     893           0 : NS_IMETHODIMP nsXULWindow::SetFocus()
     894             : {
     895             :   //XXX First Check In
     896           0 :   NS_ASSERTION(false, "Not Yet Implemented");
     897           0 :   return NS_OK;
     898             : }
     899             : 
     900           0 : NS_IMETHODIMP nsXULWindow::GetTitle(char16_t** aTitle)
     901             : {
     902           0 :   NS_ENSURE_ARG_POINTER(aTitle);
     903             : 
     904           0 :   *aTitle = ToNewUnicode(mTitle);
     905           0 :   if (!*aTitle)
     906           0 :     return NS_ERROR_OUT_OF_MEMORY;
     907           0 :   return NS_OK;
     908             : }
     909             : 
     910           2 : NS_IMETHODIMP nsXULWindow::SetTitle(const char16_t* aTitle)
     911             : {
     912           2 :   NS_ENSURE_STATE(mWindow);
     913           2 :   mTitle.Assign(aTitle);
     914           2 :   mTitle.StripCRLF();
     915           2 :   NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE);
     916             : 
     917             :   // Tell the window mediator that a title has changed
     918           4 :   nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
     919           2 :   if (!windowMediator)
     920           0 :     return NS_OK;
     921             : 
     922           2 :   windowMediator->UpdateWindowTitle(static_cast<nsIXULWindow*>(this), aTitle);
     923             : 
     924           2 :   return NS_OK;
     925             : }
     926             : 
     927             : 
     928             : //*****************************************************************************
     929             : // nsXULWindow: Helpers
     930             : //*****************************************************************************
     931             : 
     932           2 : NS_IMETHODIMP nsXULWindow::EnsureChromeTreeOwner()
     933             : {
     934           2 :   if (mChromeTreeOwner)
     935           0 :     return NS_OK;
     936             : 
     937           2 :   mChromeTreeOwner = new nsChromeTreeOwner();
     938           2 :   NS_ADDREF(mChromeTreeOwner);
     939           2 :   mChromeTreeOwner->XULWindow(this);
     940             : 
     941           2 :   return NS_OK;
     942             : }
     943             : 
     944          17 : NS_IMETHODIMP nsXULWindow::EnsureContentTreeOwner()
     945             : {
     946          17 :   if (mContentTreeOwner)
     947          15 :     return NS_OK;
     948             : 
     949           2 :   mContentTreeOwner = new nsContentTreeOwner(false);
     950           2 :   NS_ADDREF(mContentTreeOwner);
     951           2 :   mContentTreeOwner->XULWindow(this);
     952             : 
     953           2 :   return NS_OK;
     954             : }
     955             : 
     956           1 : NS_IMETHODIMP nsXULWindow::EnsurePrimaryContentTreeOwner()
     957             : {
     958           1 :   if (mPrimaryContentTreeOwner)
     959           0 :     return NS_OK;
     960             : 
     961           1 :   mPrimaryContentTreeOwner = new nsContentTreeOwner(true);
     962           1 :   NS_ADDREF(mPrimaryContentTreeOwner);
     963           1 :   mPrimaryContentTreeOwner->XULWindow(this);
     964             : 
     965           1 :   return NS_OK;
     966             : }
     967             : 
     968           0 : NS_IMETHODIMP nsXULWindow::EnsurePrompter()
     969             : {
     970           0 :   if (mPrompter)
     971           0 :     return NS_OK;
     972             : 
     973           0 :   nsCOMPtr<mozIDOMWindowProxy> ourWindow;
     974           0 :   nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow));
     975           0 :   if (NS_SUCCEEDED(rv)) {
     976             :     nsCOMPtr<nsIWindowWatcher> wwatch =
     977           0 :         do_GetService(NS_WINDOWWATCHER_CONTRACTID);
     978           0 :     if (wwatch)
     979           0 :       wwatch->GetNewPrompter(ourWindow, getter_AddRefs(mPrompter));
     980             :   }
     981           0 :   return mPrompter ? NS_OK : NS_ERROR_FAILURE;
     982             : }
     983             : 
     984           0 : NS_IMETHODIMP nsXULWindow::EnsureAuthPrompter()
     985             : {
     986           0 :   if (mAuthPrompter)
     987           0 :     return NS_OK;
     988             : 
     989           0 :   nsCOMPtr<mozIDOMWindowProxy> ourWindow;
     990           0 :   nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow));
     991           0 :   if (NS_SUCCEEDED(rv)) {
     992           0 :     nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
     993           0 :     if (wwatch)
     994           0 :       wwatch->GetNewAuthPrompter(ourWindow, getter_AddRefs(mAuthPrompter));
     995             :   }
     996           0 :   return mAuthPrompter ? NS_OK : NS_ERROR_FAILURE;
     997             : }
     998             : 
     999           1 : NS_IMETHODIMP nsXULWindow::GetAvailScreenSize(int32_t* aAvailWidth, int32_t* aAvailHeight)
    1000             : {
    1001             :   nsresult rv;
    1002             : 
    1003           2 :   nsCOMPtr<mozIDOMWindowProxy> domWindow;
    1004           1 :   GetWindowDOMWindow(getter_AddRefs(domWindow));
    1005           1 :   NS_ENSURE_STATE(domWindow);
    1006             : 
    1007           1 :   auto* window = nsPIDOMWindowOuter::From(domWindow);
    1008           1 :   NS_ENSURE_STATE(window);
    1009             : 
    1010           2 :   nsCOMPtr<nsIDOMScreen> screen = window->GetScreen();
    1011           1 :   NS_ENSURE_STATE(screen);
    1012             : 
    1013           1 :   rv = screen->GetAvailWidth(aAvailWidth);
    1014           1 :   NS_ENSURE_SUCCESS(rv, rv);
    1015             : 
    1016           1 :   rv = screen->GetAvailHeight(aAvailHeight);
    1017           1 :   NS_ENSURE_SUCCESS(rv, rv);
    1018             : 
    1019           1 :   return NS_OK;
    1020             : }
    1021             : 
    1022             : // Rounds window size to 1000x1000, or, if there isn't enough available
    1023             : // screen space, to a multiple of 200x100.
    1024           0 : NS_IMETHODIMP nsXULWindow::ForceRoundedDimensions()
    1025             : {
    1026           0 :   if (mIsHiddenWindow) {
    1027           0 :     return NS_OK;
    1028             :   }
    1029             : 
    1030           0 :   int32_t availWidthCSS    = 0;
    1031           0 :   int32_t availHeightCSS   = 0;
    1032           0 :   int32_t contentWidthCSS  = 0;
    1033           0 :   int32_t contentHeightCSS = 0;
    1034           0 :   int32_t windowWidthCSS   = 0;
    1035           0 :   int32_t windowHeightCSS  = 0;
    1036           0 :   double devicePerCSSPixels = 1.0;
    1037             : 
    1038           0 :   GetUnscaledDevicePixelsPerCSSPixel(&devicePerCSSPixels);
    1039             : 
    1040           0 :   GetAvailScreenSize(&availWidthCSS, &availHeightCSS);
    1041             : 
    1042             :   // To get correct chrome size, we have to resize the window to a proper
    1043             :   // size first. So, here, we size it to its available size.
    1044           0 :   SetSpecifiedSize(availWidthCSS, availHeightCSS);
    1045             : 
    1046             :   // Get the current window size for calculating chrome UI size.
    1047           0 :   GetSize(&windowWidthCSS, &windowHeightCSS); // device pixels
    1048           0 :   windowWidthCSS = NSToIntRound(windowWidthCSS / devicePerCSSPixels);
    1049           0 :   windowHeightCSS = NSToIntRound(windowHeightCSS / devicePerCSSPixels);
    1050             : 
    1051             :   // Get the content size for calculating chrome UI size.
    1052           0 :   GetPrimaryContentSize(&contentWidthCSS, &contentHeightCSS);
    1053             : 
    1054             :   // Calculate the chrome UI size.
    1055           0 :   int32_t chromeWidth = 0, chromeHeight = 0;
    1056           0 :   chromeWidth = windowWidthCSS - contentWidthCSS;
    1057           0 :   chromeHeight = windowHeightCSS - contentHeightCSS;
    1058             : 
    1059           0 :   int32_t targetContentWidth = 0, targetContentHeight = 0;
    1060             : 
    1061             :   // Here, we use the available screen dimensions as the input dimensions to
    1062             :   // force the window to be rounded as the maximum available content size.
    1063             :   nsContentUtils::CalcRoundedWindowSizeForResistingFingerprinting(
    1064             :     chromeWidth,
    1065             :     chromeHeight,
    1066             :     availWidthCSS,
    1067             :     availHeightCSS,
    1068             :     availWidthCSS,
    1069             :     availHeightCSS,
    1070             :     false, // aSetOuterWidth
    1071             :     false, // aSetOuterHeight
    1072             :     &targetContentWidth,
    1073             :     &targetContentHeight
    1074           0 :   );
    1075             : 
    1076           0 :   targetContentWidth = NSToIntRound(targetContentWidth * devicePerCSSPixels);
    1077           0 :   targetContentHeight = NSToIntRound(targetContentHeight * devicePerCSSPixels);
    1078             : 
    1079           0 :   SetPrimaryContentSize(targetContentWidth, targetContentHeight);
    1080             : 
    1081           0 :   mIgnoreXULSize = true;
    1082           0 :   mIgnoreXULSizeMode = true;
    1083             : 
    1084           0 :   return NS_OK;
    1085             : }
    1086             : 
    1087           2 : void nsXULWindow::OnChromeLoaded()
    1088             : {
    1089           2 :   nsresult rv = EnsureContentTreeOwner();
    1090             : 
    1091           2 :   if (NS_SUCCEEDED(rv)) {
    1092           2 :     mChromeLoaded = true;
    1093           2 :     ApplyChromeFlags();
    1094           2 :     SyncAttributesToWidget();
    1095             : 
    1096           2 :     int32_t specWidth = -1, specHeight = -1;
    1097           2 :     bool gotSize = false;
    1098           2 :     bool isContent = false;
    1099             : 
    1100           2 :     GetHasPrimaryContent(&isContent);
    1101             : 
    1102             :     // If this window has a primary content and fingerprinting resistance is
    1103             :     // enabled, we enforce this window to rounded dimensions.
    1104           2 :     if (isContent && nsContentUtils::ShouldResistFingerprinting()) {
    1105           0 :       ForceRoundedDimensions();
    1106           2 :     } else if (!mIgnoreXULSize) {
    1107           2 :       gotSize = LoadSizeFromXUL(specWidth, specHeight);
    1108             :     }
    1109             : 
    1110           2 :     bool positionSet = !mIgnoreXULPosition;
    1111           4 :     nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow));
    1112             : #if defined(XP_UNIX) && !defined(XP_MACOSX)
    1113             :     // don't override WM placement on unix for independent, top-level windows
    1114             :     // (however, we think the benefits of intelligent dependent window placement
    1115             :     // trump that override.)
    1116           2 :     if (!parentWindow)
    1117           2 :       positionSet = false;
    1118             : #endif
    1119           2 :     if (positionSet) {
    1120             :       // We have to do this before sizing the window, because sizing depends
    1121             :       // on the resolution of the screen we're on. But positioning needs to
    1122             :       // know the size so that it can constrain to screen bounds.... as an
    1123             :       // initial guess here, we'll use the specified size (if any).
    1124           0 :       positionSet = LoadPositionFromXUL(specWidth, specHeight);
    1125             :     }
    1126             : 
    1127           2 :     if (gotSize) {
    1128           1 :       SetSpecifiedSize(specWidth, specHeight);
    1129             :     }
    1130             : 
    1131           2 :     if (mIntrinsicallySized) {
    1132             :       // (if LoadSizeFromXUL set the size, mIntrinsicallySized will be false)
    1133           0 :       nsCOMPtr<nsIContentViewer> cv;
    1134           0 :       mDocShell->GetContentViewer(getter_AddRefs(cv));
    1135           0 :       if (cv) {
    1136           0 :         nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = do_QueryInterface(mDocShell);
    1137           0 :         nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    1138           0 :         docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
    1139           0 :         if (treeOwner) {
    1140             :           // GetContentSize can fail, so initialise |width| and |height| to be
    1141             :           // on the safe side.
    1142           0 :           int32_t width = 0, height = 0;
    1143           0 :           if (NS_SUCCEEDED(cv->GetContentSize(&width, &height))) {
    1144           0 :             treeOwner->SizeShellTo(docShellAsItem, width, height);
    1145             :             // Update specified size for the final LoadPositionFromXUL call.
    1146           0 :             specWidth = width;
    1147           0 :             specHeight = height;
    1148             :           }
    1149             :         }
    1150             :       }
    1151             :     }
    1152             : 
    1153             :     // Now that we have set the window's final size, we can re-do its
    1154             :     // positioning so that it is properly constrained to the screen.
    1155           2 :     if (positionSet) {
    1156           0 :       LoadPositionFromXUL(specWidth, specHeight);
    1157             :     }
    1158             : 
    1159           2 :     LoadMiscPersistentAttributesFromXUL();
    1160             : 
    1161           2 :     if (mCenterAfterLoad && !positionSet) {
    1162           0 :       Center(parentWindow, parentWindow ? false : true, false);
    1163             :     }
    1164             : 
    1165           2 :     if (mShowAfterLoad) {
    1166           1 :       SetVisibility(true);
    1167             :       // At this point the window may have been closed during Show(), so
    1168             :       // nsXULWindow::Destroy may already have been called. Take care!
    1169             :     }
    1170             :   }
    1171           2 :   mPersistentAttributesMask |= PAD_POSITION | PAD_SIZE | PAD_MISC;
    1172           2 : }
    1173             : 
    1174             : // If aSpecWidth and/or aSpecHeight are > 0, we will use these CSS px sizes
    1175             : // to fit to the screen when staggering windows; if they're negative,
    1176             : // we use the window's current size instead.
    1177           0 : bool nsXULWindow::LoadPositionFromXUL(int32_t aSpecWidth, int32_t aSpecHeight)
    1178             : {
    1179           0 :   bool     gotPosition = false;
    1180             : 
    1181             :   // if we're the hidden window, don't try to validate our size/position. We're
    1182             :   // special.
    1183           0 :   if (mIsHiddenWindow)
    1184           0 :     return false;
    1185             : 
    1186           0 :   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
    1187           0 :   NS_ENSURE_TRUE(windowElement, false);
    1188             : 
    1189           0 :   int32_t currX = 0;
    1190           0 :   int32_t currY = 0;
    1191           0 :   int32_t currWidth = 0;
    1192           0 :   int32_t currHeight = 0;
    1193             :   nsresult errorCode;
    1194             :   int32_t temp;
    1195             : 
    1196           0 :   GetPositionAndSize(&currX, &currY, &currWidth, &currHeight);
    1197             : 
    1198             :   // Convert to global display pixels for consistent window management across
    1199             :   // screens with diverse resolutions
    1200           0 :   double devToDesktopScale = 1.0 / mWindow->GetDesktopToDeviceScale().scale;
    1201           0 :   currX = NSToIntRound(currX * devToDesktopScale);
    1202           0 :   currY = NSToIntRound(currY * devToDesktopScale);
    1203             : 
    1204             :   // For size, use specified value if > 0, else current value
    1205           0 :   double devToCSSScale = 1.0 / mWindow->GetDefaultScale().scale;
    1206             :   int32_t cssWidth =
    1207           0 :     aSpecWidth > 0 ? aSpecWidth : NSToIntRound(currWidth * devToCSSScale);
    1208             :   int32_t cssHeight =
    1209           0 :     aSpecHeight > 0 ? aSpecHeight : NSToIntRound(currHeight * devToCSSScale);
    1210             : 
    1211             :   // Obtain the position information from the <xul:window> element.
    1212           0 :   int32_t specX = currX;
    1213           0 :   int32_t specY = currY;
    1214           0 :   nsAutoString posString;
    1215             : 
    1216           0 :   windowElement->GetAttribute(SCREENX_ATTRIBUTE, posString);
    1217           0 :   temp = posString.ToInteger(&errorCode);
    1218           0 :   if (NS_SUCCEEDED(errorCode)) {
    1219           0 :     specX = temp;
    1220           0 :     gotPosition = true;
    1221             :   }
    1222           0 :   windowElement->GetAttribute(SCREENY_ATTRIBUTE, posString);
    1223           0 :   temp = posString.ToInteger(&errorCode);
    1224           0 :   if (NS_SUCCEEDED(errorCode)) {
    1225           0 :     specY = temp;
    1226           0 :     gotPosition = true;
    1227             :   }
    1228             : 
    1229           0 :   if (gotPosition) {
    1230             :     // our position will be relative to our parent, if any
    1231           0 :     nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
    1232           0 :     if (parent) {
    1233             :       int32_t parentX, parentY;
    1234           0 :       if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
    1235             :         double scale;
    1236           0 :         if (NS_SUCCEEDED(parent->GetDevicePixelsPerDesktopPixel(&scale))) {
    1237           0 :           parentX = NSToIntRound(parentX / scale);
    1238           0 :           parentY = NSToIntRound(parentY / scale);
    1239             :         }
    1240           0 :         specX += parentX;
    1241           0 :         specY += parentY;
    1242             :       }
    1243             :     }
    1244             :     else {
    1245           0 :       StaggerPosition(specX, specY, cssWidth, cssHeight);
    1246             :     }
    1247             :   }
    1248           0 :   mWindow->ConstrainPosition(false, &specX, &specY);
    1249           0 :   if (specX != currX || specY != currY) {
    1250           0 :     SetPositionDesktopPix(specX, specY);
    1251             :   }
    1252             : 
    1253           0 :   return gotPosition;
    1254             : }
    1255             : 
    1256             : bool
    1257           2 : nsXULWindow::LoadSizeFromXUL(int32_t& aSpecWidth, int32_t& aSpecHeight)
    1258             : {
    1259           2 :   bool     gotSize = false;
    1260             : 
    1261             :   // if we're the hidden window, don't try to validate our size/position. We're
    1262             :   // special.
    1263           2 :   if (mIsHiddenWindow) {
    1264           1 :     return false;
    1265             :   }
    1266             : 
    1267           2 :   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
    1268           1 :   NS_ENSURE_TRUE(windowElement, false);
    1269             : 
    1270             :   nsresult errorCode;
    1271             :   int32_t temp;
    1272             : 
    1273             :   // Obtain the sizing information from the <xul:window> element.
    1274           1 :   aSpecWidth = 100;
    1275           1 :   aSpecHeight = 100;
    1276           2 :   nsAutoString sizeString;
    1277             : 
    1278           1 :   windowElement->GetAttribute(WIDTH_ATTRIBUTE, sizeString);
    1279           1 :   temp = sizeString.ToInteger(&errorCode);
    1280           1 :   if (NS_SUCCEEDED(errorCode) && temp > 0) {
    1281           1 :     aSpecWidth = std::max(temp, 100);
    1282           1 :     gotSize = true;
    1283             :   }
    1284           1 :   windowElement->GetAttribute(HEIGHT_ATTRIBUTE, sizeString);
    1285           1 :   temp = sizeString.ToInteger(&errorCode);
    1286           1 :   if (NS_SUCCEEDED(errorCode) && temp > 0) {
    1287           1 :     aSpecHeight = std::max(temp, 100);
    1288           1 :     gotSize = true;
    1289             :   }
    1290             : 
    1291           1 :   return gotSize;
    1292             : }
    1293             : 
    1294             : void
    1295           1 : nsXULWindow::SetSpecifiedSize(int32_t aSpecWidth, int32_t aSpecHeight)
    1296             : {
    1297             :   // constrain to screen size
    1298             :   int32_t screenWidth;
    1299             :   int32_t screenHeight;
    1300             : 
    1301           1 :   if (NS_SUCCEEDED(GetAvailScreenSize(&screenWidth, &screenHeight))) {
    1302           1 :     if (aSpecWidth > screenWidth) {
    1303           0 :       aSpecWidth = screenWidth;
    1304             :     }
    1305           1 :     if (aSpecHeight > screenHeight) {
    1306           0 :       aSpecHeight = screenHeight;
    1307             :     }
    1308             :   }
    1309             : 
    1310           1 :   NS_ASSERTION(mWindow, "we expected to have a window already");
    1311             : 
    1312           1 :   int32_t currWidth = 0;
    1313           1 :   int32_t currHeight = 0;
    1314           1 :   GetSize(&currWidth, &currHeight); // returns device pixels
    1315             : 
    1316             :   // convert specified values to device pixels, and resize if needed
    1317           1 :   double cssToDevPx = mWindow ? mWindow->GetDefaultScale().scale : 1.0;
    1318           1 :   aSpecWidth = NSToIntRound(aSpecWidth * cssToDevPx);
    1319           1 :   aSpecHeight = NSToIntRound(aSpecHeight * cssToDevPx);
    1320           1 :   mIntrinsicallySized = false;
    1321           1 :   if (aSpecWidth != currWidth || aSpecHeight != currHeight) {
    1322           1 :     SetSize(aSpecWidth, aSpecHeight, false);
    1323             :   }
    1324           1 : }
    1325             : 
    1326             : /* Miscellaneous persistent attributes are attributes named in the
    1327             :    |persist| attribute, other than size and position. Those are special
    1328             :    because it's important to load those before one of the misc
    1329             :    attributes (sizemode) and they require extra processing. */
    1330           2 : bool nsXULWindow::LoadMiscPersistentAttributesFromXUL()
    1331             : {
    1332           2 :   bool     gotState = false;
    1333             : 
    1334             :   /* There are no misc attributes of interest to the hidden window.
    1335             :      It's especially important not to try to validate that window's
    1336             :      size or position, because some platforms (Mac OS X) need to
    1337             :      make it visible and offscreen. */
    1338           2 :   if (mIsHiddenWindow)
    1339           1 :     return false;
    1340             : 
    1341           2 :   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
    1342           1 :   NS_ENSURE_TRUE(windowElement, false);
    1343             : 
    1344           2 :   nsAutoString stateString;
    1345             : 
    1346             :   // sizemode
    1347           1 :   windowElement->GetAttribute(MODE_ATTRIBUTE, stateString);
    1348           1 :   nsSizeMode sizeMode = nsSizeMode_Normal;
    1349             :   /* ignore request to minimize, to not confuse novices
    1350             :   if (stateString.Equals(SIZEMODE_MINIMIZED))
    1351             :     sizeMode = nsSizeMode_Minimized;
    1352             :   */
    1353           5 :   if (!mIgnoreXULSizeMode &&
    1354           4 :       (stateString.Equals(SIZEMODE_MAXIMIZED) || stateString.Equals(SIZEMODE_FULLSCREEN))) {
    1355             :     /* Honor request to maximize only if the window is sizable.
    1356             :        An unsizable, unmaximizable, yet maximized window confuses
    1357             :        Windows OS and is something of a travesty, anyway. */
    1358           1 :     if (mChromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) {
    1359           1 :       mIntrinsicallySized = false;
    1360             : 
    1361           1 :       if (stateString.Equals(SIZEMODE_MAXIMIZED))
    1362           1 :         sizeMode = nsSizeMode_Maximized;
    1363             :       else
    1364           0 :         sizeMode = nsSizeMode_Fullscreen;
    1365             :     }
    1366             :   }
    1367             : 
    1368             :   // If we are told to ignore the size mode attribute update the
    1369             :   // document so the attribute and window are in sync.
    1370           1 :   if (mIgnoreXULSizeMode) {
    1371           0 :     nsAutoString sizeString;
    1372           0 :     if (sizeMode == nsSizeMode_Maximized)
    1373           0 :       sizeString.Assign(SIZEMODE_MAXIMIZED);
    1374           0 :     else if (sizeMode == nsSizeMode_Fullscreen)
    1375           0 :       sizeString.Assign(SIZEMODE_FULLSCREEN);
    1376           0 :     else if (sizeMode == nsSizeMode_Normal)
    1377           0 :       sizeString.Assign(SIZEMODE_NORMAL);
    1378           0 :     if (!sizeString.IsEmpty()) {
    1379           0 :       ErrorResult rv;
    1380           0 :       windowElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv);
    1381             :     }
    1382             :   }
    1383             : 
    1384           1 :   if (sizeMode == nsSizeMode_Fullscreen) {
    1385           0 :     nsCOMPtr<mozIDOMWindowProxy> ourWindow;
    1386           0 :     GetWindowDOMWindow(getter_AddRefs(ourWindow));
    1387           0 :     auto* piWindow = nsPIDOMWindowOuter::From(ourWindow);
    1388           0 :     piWindow->SetFullScreen(true);
    1389             :   } else {
    1390           1 :     mWindow->SetSizeMode(sizeMode);
    1391             :   }
    1392           1 :   gotState = true;
    1393             : 
    1394             :   // zlevel
    1395           1 :   windowElement->GetAttribute(ZLEVEL_ATTRIBUTE, stateString);
    1396           1 :   if (!stateString.IsEmpty()) {
    1397             :     nsresult errorCode;
    1398           0 :     int32_t zLevel = stateString.ToInteger(&errorCode);
    1399           0 :     if (NS_SUCCEEDED(errorCode) && zLevel >= lowestZ && zLevel <= highestZ)
    1400           0 :       SetZLevel(zLevel);
    1401             :   }
    1402             : 
    1403           1 :   return gotState;
    1404             : }
    1405             : 
    1406             : /* Stagger windows of the same type so they don't appear on top of each other.
    1407             :    This code does have a scary double loop -- it'll keep passing through
    1408             :    the entire list of open windows until it finds a non-collision. Doesn't
    1409             :    seem to be a problem, but it deserves watching.
    1410             :    The aRequested{X,Y} parameters here are in desktop pixels;
    1411             :    the aSpec{Width,Height} parameters are CSS pixel dimensions.
    1412             : */
    1413           0 : void nsXULWindow::StaggerPosition(int32_t &aRequestedX, int32_t &aRequestedY,
    1414             :                                   int32_t aSpecWidth, int32_t aSpecHeight)
    1415             : {
    1416             :   // These "constants" will be converted from CSS to desktop pixels
    1417             :   // for the appropriate screen, assuming we find a screen to use...
    1418             :   // hence they're not actually declared const here.
    1419           0 :   int32_t kOffset = 22;
    1420           0 :   uint32_t kSlop  = 4;
    1421             : 
    1422             :   bool     keepTrying;
    1423           0 :   int      bouncedX = 0, // bounced off vertical edge of screen
    1424           0 :            bouncedY = 0; // bounced off horizontal edge
    1425             : 
    1426             :   // look for any other windows of this type
    1427           0 :   nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
    1428           0 :   if (!wm)
    1429           0 :     return;
    1430             : 
    1431           0 :   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
    1432           0 :   if (!windowElement)
    1433           0 :     return;
    1434             : 
    1435           0 :   nsCOMPtr<nsIXULWindow> ourXULWindow(this);
    1436             : 
    1437           0 :   nsAutoString windowType;
    1438           0 :   windowElement->GetAttribute(WINDOWTYPE_ATTRIBUTE, windowType);
    1439             : 
    1440           0 :   int32_t screenTop = 0,    // it's pointless to initialize these ...
    1441           0 :           screenRight = 0,  // ... but to prevent oversalubrious and ...
    1442           0 :           screenBottom = 0, // ... underbright compilers from ...
    1443           0 :           screenLeft = 0;   // ... issuing warnings.
    1444           0 :   bool    gotScreen = false;
    1445             : 
    1446             :   { // fetch screen coordinates
    1447             :     nsCOMPtr<nsIScreenManager> screenMgr(do_GetService(
    1448           0 :                                          "@mozilla.org/gfx/screenmanager;1"));
    1449           0 :     if (screenMgr) {
    1450           0 :       nsCOMPtr<nsIScreen> ourScreen;
    1451             :       // the coordinates here are already display pixels
    1452           0 :       screenMgr->ScreenForRect(aRequestedX, aRequestedY,
    1453             :                                aSpecWidth, aSpecHeight,
    1454           0 :                                getter_AddRefs(ourScreen));
    1455           0 :       if (ourScreen) {
    1456             :         int32_t screenWidth, screenHeight;
    1457           0 :         ourScreen->GetAvailRectDisplayPix(&screenLeft, &screenTop,
    1458           0 :                                           &screenWidth, &screenHeight);
    1459           0 :         screenBottom = screenTop + screenHeight;
    1460           0 :         screenRight = screenLeft + screenWidth;
    1461             :         // Get the screen's scaling factors and convert staggering constants
    1462             :         // from CSS px to desktop pixel units
    1463           0 :         double desktopToDeviceScale = 1.0, cssToDeviceScale = 1.0;
    1464           0 :         ourScreen->GetContentsScaleFactor(&desktopToDeviceScale);
    1465           0 :         ourScreen->GetDefaultCSSScaleFactor(&cssToDeviceScale);
    1466           0 :         double cssToDesktopFactor = cssToDeviceScale / desktopToDeviceScale;
    1467           0 :         kOffset = NSToIntRound(kOffset * cssToDesktopFactor);
    1468           0 :         kSlop = NSToIntRound(kSlop * cssToDesktopFactor);
    1469             :         // Convert dimensions from CSS to desktop pixels
    1470           0 :         aSpecWidth = NSToIntRound(aSpecWidth * cssToDesktopFactor);
    1471           0 :         aSpecHeight = NSToIntRound(aSpecHeight * cssToDesktopFactor);
    1472           0 :         gotScreen = true;
    1473             :       }
    1474             :     }
    1475             :   }
    1476             : 
    1477             :   // One full pass through all windows of this type, repeat until no collisions.
    1478           0 :   do {
    1479           0 :     keepTrying = false;
    1480           0 :     nsCOMPtr<nsISimpleEnumerator> windowList;
    1481           0 :     wm->GetXULWindowEnumerator(windowType.get(), getter_AddRefs(windowList));
    1482             : 
    1483           0 :     if (!windowList)
    1484           0 :       break;
    1485             : 
    1486             :     // One full pass through all windows of this type, offset and stop on collision.
    1487             :     do {
    1488             :       bool more;
    1489           0 :       windowList->HasMoreElements(&more);
    1490           0 :       if (!more)
    1491           0 :         break;
    1492             : 
    1493           0 :       nsCOMPtr<nsISupports> supportsWindow;
    1494           0 :       windowList->GetNext(getter_AddRefs(supportsWindow));
    1495             : 
    1496           0 :       nsCOMPtr<nsIXULWindow> listXULWindow(do_QueryInterface(supportsWindow));
    1497           0 :       if (listXULWindow != ourXULWindow) {
    1498             :         int32_t listX, listY;
    1499           0 :         nsCOMPtr<nsIBaseWindow> listBaseWindow(do_QueryInterface(supportsWindow));
    1500           0 :         listBaseWindow->GetPosition(&listX, &listY);
    1501             :         double scale;
    1502           0 :         if (NS_SUCCEEDED(listBaseWindow->GetDevicePixelsPerDesktopPixel(&scale))) {
    1503           0 :           listX = NSToIntRound(listX / scale);
    1504           0 :           listY = NSToIntRound(listY / scale);
    1505             :         }
    1506             : 
    1507           0 :         if (Abs(listX - aRequestedX) <= kSlop && Abs(listY - aRequestedY) <= kSlop) {
    1508             :           // collision! offset and start over
    1509           0 :           if (bouncedX & 0x1)
    1510           0 :             aRequestedX -= kOffset;
    1511             :           else
    1512           0 :             aRequestedX += kOffset;
    1513           0 :           aRequestedY += kOffset;
    1514             : 
    1515           0 :           if (gotScreen) {
    1516             :             // if we're moving to the right and we need to bounce...
    1517           0 :             if (!(bouncedX & 0x1) && ((aRequestedX + aSpecWidth) > screenRight)) {
    1518           0 :               aRequestedX = screenRight - aSpecWidth;
    1519           0 :               ++bouncedX;
    1520             :             }
    1521             : 
    1522             :             // if we're moving to the left and we need to bounce...
    1523           0 :             if ((bouncedX & 0x1) && aRequestedX < screenLeft) {
    1524           0 :               aRequestedX = screenLeft;
    1525           0 :               ++bouncedX;
    1526             :             }
    1527             : 
    1528             :             // if we hit the bottom then bounce to the top
    1529           0 :             if (aRequestedY + aSpecHeight > screenBottom) {
    1530           0 :               aRequestedY = screenTop;
    1531           0 :               ++bouncedY;
    1532             :             }
    1533             :           }
    1534             : 
    1535             :           /* loop around again,
    1536             :              but it's time to give up once we've covered the screen.
    1537             :              there's a potential infinite loop with lots of windows. */
    1538           0 :           keepTrying = bouncedX < 2 || bouncedY == 0;
    1539           0 :           break;
    1540             :         }
    1541           0 :       }
    1542             :     } while(1);
    1543             :   } while (keepTrying);
    1544             : }
    1545             : 
    1546           2 : void nsXULWindow::SyncAttributesToWidget()
    1547             : {
    1548           4 :   nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
    1549           2 :   if (!windowElement)
    1550           0 :     return;
    1551             : 
    1552           4 :   nsAutoString attr;
    1553             : 
    1554             :   // "hidechrome" attribute
    1555           2 :   if (windowElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidechrome,
    1556             :                                  nsGkAtoms::_true, eCaseMatters)) {
    1557           0 :     mWindow->HideWindowChrome(true);
    1558             :   }
    1559             : 
    1560             :   // "chromemargin" attribute
    1561           2 :   nsIntMargin margins;
    1562           2 :   windowElement->GetAttribute(NS_LITERAL_STRING("chromemargin"), attr);
    1563           2 :   if (nsContentUtils::ParseIntMarginValue(attr, margins)) {
    1564           0 :     LayoutDeviceIntMargin tmp = LayoutDeviceIntMargin::FromUnknownMargin(margins);
    1565           0 :     mWindow->SetNonClientMargins(tmp);
    1566             :   }
    1567             : 
    1568             :   // "windowtype" attribute
    1569           2 :   windowElement->GetAttribute(WINDOWTYPE_ATTRIBUTE, attr);
    1570           2 :   if (!attr.IsEmpty()) {
    1571           1 :     mWindow->SetWindowClass(attr);
    1572             :   }
    1573             : 
    1574             :   // "id" attribute for icon
    1575           2 :   windowElement->GetAttribute(NS_LITERAL_STRING("id"), attr);
    1576           2 :   if (attr.IsEmpty()) {
    1577           1 :     attr.AssignLiteral("default");
    1578             :   }
    1579           2 :   mWindow->SetIcon(attr);
    1580             : 
    1581             :   // "drawtitle" attribute
    1582           2 :   windowElement->GetAttribute(NS_LITERAL_STRING("drawtitle"), attr);
    1583           2 :   mWindow->SetDrawsTitle(attr.LowerCaseEqualsLiteral("true"));
    1584             : 
    1585             :   // "toggletoolbar" attribute
    1586           2 :   windowElement->GetAttribute(NS_LITERAL_STRING("toggletoolbar"), attr);
    1587           2 :   mWindow->SetShowsToolbarButton(attr.LowerCaseEqualsLiteral("true"));
    1588             : 
    1589             :   // "fullscreenbutton" attribute
    1590           2 :   windowElement->GetAttribute(NS_LITERAL_STRING("fullscreenbutton"), attr);
    1591           2 :   mWindow->SetShowsFullScreenButton(attr.LowerCaseEqualsLiteral("true"));
    1592             : 
    1593             :   // "macanimationtype" attribute
    1594           2 :   windowElement->GetAttribute(NS_LITERAL_STRING("macanimationtype"), attr);
    1595           2 :   if (attr.EqualsLiteral("document")) {
    1596           1 :     mWindow->SetWindowAnimationType(nsIWidget::eDocumentWindowAnimation);
    1597             :   }
    1598             : }
    1599             : 
    1600           3 : NS_IMETHODIMP nsXULWindow::SavePersistentAttributes()
    1601             : {
    1602             :   // can happen when the persistence timer fires at an inopportune time
    1603             :   // during window shutdown
    1604           3 :   if (!mDocShell)
    1605           0 :     return NS_ERROR_FAILURE;
    1606             : 
    1607           6 :   nsCOMPtr<dom::Element> docShellElement = GetWindowDOMElement();
    1608           3 :   if (!docShellElement)
    1609           0 :     return NS_ERROR_FAILURE;
    1610             : 
    1611           6 :   nsAutoString   persistString;
    1612           3 :   docShellElement->GetAttribute(PERSIST_ATTRIBUTE, persistString);
    1613           3 :   if (persistString.IsEmpty()) { // quick check which sometimes helps
    1614           0 :     mPersistentAttributesDirty = 0;
    1615           0 :     return NS_OK;
    1616             :   }
    1617             : 
    1618           3 :   bool isFullscreen = false;
    1619           3 :   if (nsPIDOMWindowOuter* domWindow = mDocShell->GetWindow()) {
    1620           3 :     isFullscreen = domWindow->GetFullScreen();
    1621             :   }
    1622             : 
    1623             :   // get our size, position and mode to persist
    1624           3 :   LayoutDeviceIntRect rect;
    1625           3 :   bool gotRestoredBounds = NS_SUCCEEDED(mWindow->GetRestoredBounds(rect));
    1626             : 
    1627             :   // we use CSS pixels for size, but desktop pixels for position
    1628           3 :   CSSToLayoutDeviceScale sizeScale = mWindow->GetDefaultScale();
    1629           3 :   DesktopToLayoutDeviceScale posScale = mWindow->GetDesktopToDeviceScale();
    1630             : 
    1631             :   // make our position relative to our parent, if any
    1632           6 :   nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
    1633           3 :   if (parent && gotRestoredBounds) {
    1634             :     int32_t parentX, parentY;
    1635           0 :     if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
    1636           0 :       rect.x -= parentX;
    1637           0 :       rect.y -= parentY;
    1638             :     }
    1639             :   }
    1640             : 
    1641             :   char                        sizeBuf[10];
    1642           6 :   nsAutoString                sizeString;
    1643           6 :   nsAutoString                windowElementId;
    1644           6 :   nsCOMPtr<nsIDOMXULDocument> ownerXULDoc;
    1645             : 
    1646             :   // fetch docShellElement's ID and XUL owner document
    1647           3 :   ownerXULDoc = do_QueryInterface(docShellElement->OwnerDoc());
    1648           3 :   if (docShellElement->IsXULElement()) {
    1649           3 :     docShellElement->GetId(windowElementId);
    1650             :   }
    1651             : 
    1652           3 :   bool shouldPersist = !isFullscreen && ownerXULDoc;
    1653           6 :   ErrorResult rv;
    1654             :   // (only for size elements which are persisted)
    1655           3 :   if ((mPersistentAttributesDirty & PAD_POSITION) && gotRestoredBounds) {
    1656           0 :     if (persistString.Find("screenX") >= 0) {
    1657           0 :       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.x / posScale.scale));
    1658           0 :       sizeString.AssignWithConversion(sizeBuf);
    1659           0 :       docShellElement->SetAttribute(SCREENX_ATTRIBUTE, sizeString, rv);
    1660           0 :       if (shouldPersist) {
    1661           0 :         ownerXULDoc->Persist(windowElementId, SCREENX_ATTRIBUTE);
    1662             :       }
    1663             :     }
    1664           0 :     if (persistString.Find("screenY") >= 0) {
    1665           0 :       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.y / posScale.scale));
    1666           0 :       sizeString.AssignWithConversion(sizeBuf);
    1667           0 :       docShellElement->SetAttribute(SCREENY_ATTRIBUTE, sizeString, rv);
    1668           0 :       if (shouldPersist) {
    1669           0 :         ownerXULDoc->Persist(windowElementId, SCREENY_ATTRIBUTE);
    1670             :       }
    1671             :     }
    1672             :   }
    1673             : 
    1674           3 :   if ((mPersistentAttributesDirty & PAD_SIZE) && gotRestoredBounds) {
    1675           0 :     if (persistString.Find("width") >= 0) {
    1676           0 :       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.width / sizeScale.scale));
    1677           0 :       sizeString.AssignWithConversion(sizeBuf);
    1678           0 :       docShellElement->SetAttribute(WIDTH_ATTRIBUTE, sizeString, rv);
    1679           0 :       if (shouldPersist) {
    1680           0 :         ownerXULDoc->Persist(windowElementId, WIDTH_ATTRIBUTE);
    1681             :       }
    1682             :     }
    1683           0 :     if (persistString.Find("height") >= 0) {
    1684           0 :       SprintfLiteral(sizeBuf, "%d", NSToIntRound(rect.height / sizeScale.scale));
    1685           0 :       sizeString.AssignWithConversion(sizeBuf);
    1686           0 :       docShellElement->SetAttribute(HEIGHT_ATTRIBUTE, sizeString, rv);
    1687           0 :       if (shouldPersist) {
    1688           0 :         ownerXULDoc->Persist(windowElementId, HEIGHT_ATTRIBUTE);
    1689             :       }
    1690             :     }
    1691             :   }
    1692             : 
    1693           3 :   if (mPersistentAttributesDirty & PAD_MISC) {
    1694           2 :     nsSizeMode sizeMode = mWindow->SizeMode();
    1695             : 
    1696           2 :     if (sizeMode != nsSizeMode_Minimized) {
    1697           2 :       if (sizeMode == nsSizeMode_Maximized)
    1698           2 :         sizeString.Assign(SIZEMODE_MAXIMIZED);
    1699           0 :       else if (sizeMode == nsSizeMode_Fullscreen)
    1700           0 :         sizeString.Assign(SIZEMODE_FULLSCREEN);
    1701             :       else
    1702           0 :         sizeString.Assign(SIZEMODE_NORMAL);
    1703           2 :       docShellElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv);
    1704           2 :       if (shouldPersist && persistString.Find("sizemode") >= 0) {
    1705           2 :         ownerXULDoc->Persist(windowElementId, MODE_ATTRIBUTE);
    1706             :       }
    1707             :     }
    1708           2 :     if (persistString.Find("zlevel") >= 0) {
    1709             :       uint32_t zLevel;
    1710           0 :       nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
    1711           0 :       if (mediator) {
    1712           0 :         mediator->GetZLevel(this, &zLevel);
    1713           0 :         SprintfLiteral(sizeBuf, "%" PRIu32, zLevel);
    1714           0 :         sizeString.AssignWithConversion(sizeBuf);
    1715           0 :         docShellElement->SetAttribute(ZLEVEL_ATTRIBUTE, sizeString, rv);
    1716           0 :         if (shouldPersist) {
    1717           0 :           ownerXULDoc->Persist(windowElementId, ZLEVEL_ATTRIBUTE);
    1718             :         }
    1719             :       }
    1720             :     }
    1721             :   }
    1722             : 
    1723           3 :   mPersistentAttributesDirty = 0;
    1724           3 :   return NS_OK;
    1725             : }
    1726             : 
    1727           3 : NS_IMETHODIMP nsXULWindow::GetWindowDOMWindow(mozIDOMWindowProxy** aDOMWindow)
    1728             : {
    1729           3 :   NS_ENSURE_STATE(mDocShell);
    1730             : 
    1731           3 :   if (!mDOMWindow)
    1732           2 :     mDOMWindow = mDocShell->GetWindow();
    1733           3 :   NS_ENSURE_TRUE(mDOMWindow, NS_ERROR_FAILURE);
    1734             : 
    1735           3 :   *aDOMWindow = mDOMWindow;
    1736           3 :   NS_ADDREF(*aDOMWindow);
    1737           3 :   return NS_OK;
    1738             : }
    1739             : 
    1740             : dom::Element*
    1741          11 : nsXULWindow::GetWindowDOMElement() const
    1742             : {
    1743          11 :   NS_ENSURE_TRUE(mDocShell, nullptr);
    1744             : 
    1745          22 :   nsCOMPtr<nsIContentViewer> cv;
    1746          11 :   mDocShell->GetContentViewer(getter_AddRefs(cv));
    1747          11 :   NS_ENSURE_TRUE(cv, nullptr);
    1748             : 
    1749          11 :   const nsIDocument* document = cv->GetDocument();
    1750          11 :   NS_ENSURE_TRUE(document, nullptr);
    1751             : 
    1752          11 :   return document->GetRootElement();
    1753             : }
    1754             : 
    1755           1 : nsresult nsXULWindow::ContentShellAdded(nsIDocShellTreeItem* aContentShell,
    1756             :    bool aPrimary)
    1757             : {
    1758             :   // Set the default content tree owner
    1759           1 :   if (aPrimary) {
    1760           1 :     NS_ENSURE_SUCCESS(EnsurePrimaryContentTreeOwner(), NS_ERROR_FAILURE);
    1761           1 :     aContentShell->SetTreeOwner(mPrimaryContentTreeOwner);
    1762           1 :     mPrimaryContentShell = aContentShell;
    1763           1 :     mPrimaryTabParent = nullptr;
    1764             :   }
    1765             :   else {
    1766           0 :     NS_ENSURE_SUCCESS(EnsureContentTreeOwner(), NS_ERROR_FAILURE);
    1767           0 :     aContentShell->SetTreeOwner(mContentTreeOwner);
    1768           0 :     if (mPrimaryContentShell == aContentShell)
    1769           0 :       mPrimaryContentShell = nullptr;
    1770             :   }
    1771             : 
    1772           1 :   return NS_OK;
    1773             : }
    1774             : 
    1775           1 : nsresult nsXULWindow::ContentShellRemoved(nsIDocShellTreeItem* aContentShell)
    1776             : {
    1777           1 :   if (mPrimaryContentShell == aContentShell) {
    1778           1 :     mPrimaryContentShell = nullptr;
    1779             :   }
    1780           1 :   return NS_OK;
    1781             : }
    1782             : 
    1783             : NS_IMETHODIMP
    1784           0 : nsXULWindow::GetPrimaryContentSize(int32_t* aWidth,
    1785             :                                    int32_t* aHeight)
    1786             : {
    1787           0 :   if (mPrimaryTabParent) {
    1788           0 :     return GetPrimaryTabParentSize(aWidth, aHeight);
    1789           0 :   } else if (mPrimaryContentShell) {
    1790           0 :     return GetPrimaryContentShellSize(aWidth, aHeight);
    1791             :   }
    1792           0 :   return NS_ERROR_UNEXPECTED;
    1793             : }
    1794             : 
    1795             : nsresult
    1796           0 : nsXULWindow::GetPrimaryTabParentSize(int32_t* aWidth,
    1797             :                                      int32_t* aHeight)
    1798             : {
    1799           0 :   TabParent* tabParent = TabParent::GetFrom(mPrimaryTabParent);
    1800           0 :   Element* element = tabParent->GetOwnerElement();
    1801           0 :   NS_ENSURE_STATE(element);
    1802             : 
    1803           0 :   *aWidth = element->ClientWidth();
    1804           0 :   *aHeight = element->ClientHeight();
    1805           0 :   return NS_OK;
    1806             : }
    1807             : 
    1808             : nsresult
    1809           0 : nsXULWindow::GetPrimaryContentShellSize(int32_t* aWidth,
    1810             :                                         int32_t* aHeight)
    1811             : {
    1812           0 :   NS_ENSURE_STATE(mPrimaryContentShell);
    1813             : 
    1814           0 :   nsCOMPtr<nsIBaseWindow> shellWindow(do_QueryInterface(mPrimaryContentShell));
    1815           0 :   NS_ENSURE_STATE(shellWindow);
    1816             : 
    1817             :   int32_t devicePixelWidth, devicePixelHeight;
    1818           0 :   double shellScale = 1.0;
    1819             :   // We want to return CSS pixels. First, we get device pixels
    1820             :   // from the content area...
    1821           0 :   shellWindow->GetSize(&devicePixelWidth, &devicePixelHeight);
    1822             :   // And then get the device pixel scaling factor. Dividing device
    1823             :   // pixels by this scaling factor gives us CSS pixels.
    1824           0 :   shellWindow->GetUnscaledDevicePixelsPerCSSPixel(&shellScale);
    1825           0 :   *aWidth = NSToIntRound(devicePixelWidth / shellScale);
    1826           0 :   *aHeight = NSToIntRound(devicePixelHeight / shellScale);
    1827           0 :   return NS_OK;
    1828             : }
    1829             : 
    1830             : NS_IMETHODIMP
    1831           0 : nsXULWindow::SetPrimaryContentSize(int32_t aWidth,
    1832             :                                    int32_t aHeight)
    1833             : {
    1834           0 :   if (mPrimaryTabParent) {
    1835           0 :     return SetPrimaryTabParentSize(aWidth, aHeight);
    1836           0 :   } else if (mPrimaryContentShell) {
    1837           0 :     return SizeShellTo(mPrimaryContentShell, aWidth, aHeight);
    1838             :   }
    1839           0 :   return NS_ERROR_UNEXPECTED;
    1840             : }
    1841             : 
    1842             : nsresult
    1843           0 : nsXULWindow::SetPrimaryTabParentSize(int32_t aWidth,
    1844             :                                      int32_t aHeight)
    1845             : {
    1846             :   int32_t shellWidth, shellHeight;
    1847           0 :   GetPrimaryTabParentSize(&shellWidth, &shellHeight);
    1848             : 
    1849           0 :   double scale = 1.0;
    1850           0 :   GetUnscaledDevicePixelsPerCSSPixel(&scale);
    1851             : 
    1852           0 :   SizeShellToWithLimit(aWidth, aHeight,
    1853           0 :                        shellWidth * scale, shellHeight * scale);
    1854           0 :   return NS_OK;
    1855             : }
    1856             : 
    1857             : nsresult
    1858           1 : nsXULWindow::GetRootShellSize(int32_t* aWidth,
    1859             :                               int32_t* aHeight)
    1860             : {
    1861           2 :   nsCOMPtr<nsIBaseWindow> shellAsWin = do_QueryInterface(mDocShell);
    1862           1 :   NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE);
    1863           1 :   return shellAsWin->GetSize(aWidth, aHeight);
    1864             : }
    1865             : 
    1866             : nsresult
    1867           0 : nsXULWindow::SetRootShellSize(int32_t aWidth,
    1868             :                               int32_t aHeight)
    1869             : {
    1870           0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = do_QueryInterface(mDocShell);
    1871           0 :   return SizeShellTo(docShellAsItem, aWidth, aHeight);
    1872             : }
    1873             : 
    1874           0 : NS_IMETHODIMP nsXULWindow::SizeShellTo(nsIDocShellTreeItem* aShellItem,
    1875             :    int32_t aCX, int32_t aCY)
    1876             : {
    1877             :   // XXXTAB This is wrong, we should actually reflow based on the passed in
    1878             :   // shell.  For now we are hacking and doing delta sizing.  This is bad
    1879             :   // because it assumes all size we add will go to the shell which probably
    1880             :   // won't happen.
    1881             : 
    1882           0 :   nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(aShellItem));
    1883           0 :   NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE);
    1884             : 
    1885           0 :   int32_t width = 0;
    1886           0 :   int32_t height = 0;
    1887           0 :   shellAsWin->GetSize(&width, &height);
    1888             : 
    1889           0 :   SizeShellToWithLimit(aCX, aCY, width, height);
    1890             : 
    1891           0 :   return NS_OK;
    1892             : }
    1893             : 
    1894           0 : NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus)
    1895             : {
    1896           0 :   if (mContinueModalLoop)
    1897           0 :     EnableParent(true);
    1898           0 :   mContinueModalLoop = false;
    1899           0 :   mModalStatus = aStatus;
    1900           0 :   return NS_OK;
    1901             : }
    1902             : 
    1903             : // top-level function to create a new window
    1904           0 : NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags,
    1905             :                                            nsITabParent *aOpeningTab,
    1906             :                                            mozIDOMWindowProxy *aOpener,
    1907             :                                            uint64_t aNextTabParentId,
    1908             :                                            nsIXULWindow **_retval)
    1909             : {
    1910           0 :   NS_ENSURE_ARG_POINTER(_retval);
    1911             : 
    1912           0 :   if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) {
    1913           0 :     MOZ_RELEASE_ASSERT(aNextTabParentId == 0,
    1914             :                        "Unexpected next tab parent ID, should never have a non-zero nextTabParentId when creating a new chrome window");
    1915           0 :     return CreateNewChromeWindow(aChromeFlags, aOpeningTab, aOpener, _retval);
    1916             :   }
    1917           0 :   return CreateNewContentWindow(aChromeFlags, aOpeningTab, aOpener, aNextTabParentId, _retval);
    1918             : }
    1919             : 
    1920           0 : NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags,
    1921             :                                                  nsITabParent *aOpeningTab,
    1922             :                                                  mozIDOMWindowProxy *aOpener,
    1923             :                                                  nsIXULWindow **_retval)
    1924             : {
    1925           0 :   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
    1926           0 :   NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
    1927             : 
    1928             :   // Just do a normal create of a window and return.
    1929           0 :   nsCOMPtr<nsIXULWindow> newWindow;
    1930           0 :   appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags,
    1931             :                                  nsIAppShellService::SIZE_TO_CONTENT,
    1932             :                                  nsIAppShellService::SIZE_TO_CONTENT,
    1933             :                                  aOpeningTab, aOpener,
    1934           0 :                                  getter_AddRefs(newWindow));
    1935             : 
    1936           0 :   NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
    1937             : 
    1938           0 :   *_retval = newWindow;
    1939           0 :   NS_ADDREF(*_retval);
    1940             : 
    1941           0 :   return NS_OK;
    1942             : }
    1943             : 
    1944           0 : NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
    1945             :                                                   nsITabParent *aOpeningTab,
    1946             :                                                   mozIDOMWindowProxy *aOpener,
    1947             :                                                   uint64_t aNextTabParentId,
    1948             :                                                   nsIXULWindow **_retval)
    1949             : {
    1950           0 :   nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
    1951           0 :   NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
    1952             : 
    1953             :   // We need to create a new top level window and then enter a nested
    1954             :   // loop. Eventually the new window will be told that it has loaded,
    1955             :   // at which time we know it is safe to spin out of the nested loop
    1956             :   // and allow the opening code to proceed.
    1957             : 
    1958           0 :   nsCOMPtr<nsIURI> uri;
    1959             : 
    1960           0 :   nsAdoptingCString urlStr = Preferences::GetCString("browser.chromeURL");
    1961           0 :   if (urlStr.IsEmpty()) {
    1962           0 :     urlStr.AssignLiteral("chrome://navigator/content/navigator.xul");
    1963             :   }
    1964             : 
    1965           0 :   nsCOMPtr<nsIIOService> service(do_GetService(NS_IOSERVICE_CONTRACTID));
    1966           0 :   if (service) {
    1967           0 :     service->NewURI(urlStr, nullptr, nullptr, getter_AddRefs(uri));
    1968             :   }
    1969           0 :   NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
    1970             : 
    1971             :   // We need to create a chrome window to contain the content window we're about
    1972             :   // to pass back. The subject principal needs to be system while we're creating
    1973             :   // it to make things work right, so force a system caller. See bug 799348
    1974             :   // comment 13 for a description of what happens when we don't.
    1975           0 :   nsCOMPtr<nsIXULWindow> newWindow;
    1976             :   {
    1977           0 :     AutoNoJSAPI nojsapi;
    1978             :     // We actually want this toplevel window which we are creating to have a
    1979             :     // null opener, as we will be creating the content xul:browser window inside
    1980             :     // of it, so we pass nullptr as our aOpener.
    1981           0 :     appShell->CreateTopLevelWindow(this, uri,
    1982             :                                    aChromeFlags, 615, 480,
    1983             :                                    aOpeningTab, nullptr,
    1984           0 :                                    getter_AddRefs(newWindow));
    1985           0 :     NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
    1986             :   }
    1987             : 
    1988             :   // Specify that we want the window to remain locked until the chrome has loaded.
    1989           0 :   nsXULWindow *xulWin = static_cast<nsXULWindow*>
    1990           0 :                                    (static_cast<nsIXULWindow*>
    1991           0 :                                                (newWindow));
    1992             : 
    1993           0 :   if (aNextTabParentId) {
    1994           0 :     xulWin->mNextTabParentId = aNextTabParentId;
    1995             :   }
    1996             : 
    1997           0 :   if (aOpener) {
    1998           0 :     nsCOMPtr<nsIDocShell> docShell;
    1999           0 :     xulWin->GetDocShell(getter_AddRefs(docShell));
    2000           0 :     MOZ_ASSERT(docShell);
    2001             :     nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
    2002           0 :       do_QueryInterface(docShell->GetWindow());
    2003           0 :     MOZ_ASSERT(chromeWindow);
    2004             : 
    2005           0 :     chromeWindow->SetOpenerForInitialContentBrowser(aOpener);
    2006             :   }
    2007             : 
    2008           0 :   xulWin->LockUntilChromeLoad();
    2009             : 
    2010             :   {
    2011           0 :     AutoNoJSAPI nojsapi;
    2012           0 :     SpinEventLoopUntil([&]() { return !xulWin->IsLocked(); });
    2013             :   }
    2014             : 
    2015           0 :   NS_ENSURE_STATE(xulWin->mPrimaryContentShell || xulWin->mPrimaryTabParent);
    2016           0 :   MOZ_ASSERT_IF(xulWin->mPrimaryContentShell, aNextTabParentId == 0);
    2017             : 
    2018           0 :   *_retval = newWindow;
    2019           0 :   NS_ADDREF(*_retval);
    2020             : 
    2021           0 :   return NS_OK;
    2022             : }
    2023             : 
    2024           3 : NS_IMETHODIMP nsXULWindow::GetHasPrimaryContent(bool* aResult)
    2025             : {
    2026           3 :   *aResult = mPrimaryTabParent || mPrimaryContentShell;
    2027           3 :   return NS_OK;
    2028             : }
    2029             : 
    2030           0 : void nsXULWindow::EnableParent(bool aEnable)
    2031             : {
    2032           0 :   nsCOMPtr<nsIBaseWindow> parentWindow;
    2033           0 :   nsCOMPtr<nsIWidget>     parentWidget;
    2034             : 
    2035           0 :   parentWindow = do_QueryReferent(mParentWindow);
    2036           0 :   if (parentWindow)
    2037           0 :     parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
    2038           0 :   if (parentWidget)
    2039           0 :     parentWidget->Enable(aEnable);
    2040           0 : }
    2041             : 
    2042             : // Constrain the window to its proper z-level
    2043           0 : bool nsXULWindow::ConstrainToZLevel(bool        aImmediate,
    2044             :                                       nsWindowZ  *aPlacement,
    2045             :                                       nsIWidget  *aReqBelow,
    2046             :                                       nsIWidget **aActualBelow)
    2047             : {
    2048             : #if 0
    2049             :   /* Do we have a parent window? This means our z-order is already constrained,
    2050             :      since we're a dependent window. Our window list isn't hierarchical,
    2051             :      so we can't properly calculate placement for such a window.
    2052             :      Should we just abort? */
    2053             :   nsCOMPtr<nsIBaseWindow> parentWindow = do_QueryReferent(mParentWindow);
    2054             :   if (parentWindow)
    2055             :     return false;
    2056             : #endif
    2057             : 
    2058           0 :   nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
    2059           0 :   if (!mediator)
    2060           0 :     return false;
    2061             : 
    2062             :   bool           altered;
    2063             :   uint32_t       position,
    2064             :                  newPosition,
    2065             :                  zLevel;
    2066           0 :   nsIXULWindow  *us = this;
    2067             : 
    2068           0 :   altered = false;
    2069           0 :   mediator->GetZLevel(this, &zLevel);
    2070             : 
    2071             :   // translate from WidgetGUIEvent to nsIWindowMediator constants
    2072           0 :   position = nsIWindowMediator::zLevelTop;
    2073           0 :   if (*aPlacement == nsWindowZBottom || zLevel == nsIXULWindow::lowestZ)
    2074           0 :     position = nsIWindowMediator::zLevelBottom;
    2075           0 :   else if (*aPlacement == nsWindowZRelative)
    2076           0 :     position = nsIWindowMediator::zLevelBelow;
    2077             : 
    2078           0 :   if (NS_SUCCEEDED(mediator->CalculateZPosition(us, position, aReqBelow,
    2079             :                                &newPosition, aActualBelow, &altered))) {
    2080             :     /* If we were asked to move to the top but constrained to remain
    2081             :        below one of our other windows, first move all windows in that
    2082             :        window's layer and above to the top. This allows the user to
    2083             :        click a window which can't be topmost and still bring mozilla
    2084             :        to the foreground. */
    2085           0 :     if (altered &&
    2086           0 :         (position == nsIWindowMediator::zLevelTop ||
    2087           0 :          (position == nsIWindowMediator::zLevelBelow && aReqBelow == 0)))
    2088           0 :       PlaceWindowLayersBehind(zLevel + 1, nsIXULWindow::highestZ, 0);
    2089             : 
    2090           0 :     if (*aPlacement != nsWindowZBottom &&
    2091             :         position == nsIWindowMediator::zLevelBottom)
    2092           0 :       altered = true;
    2093           0 :     if (altered || aImmediate) {
    2094           0 :       if (newPosition == nsIWindowMediator::zLevelTop)
    2095           0 :         *aPlacement = nsWindowZTop;
    2096           0 :       else if (newPosition == nsIWindowMediator::zLevelBottom)
    2097           0 :         *aPlacement = nsWindowZBottom;
    2098             :       else
    2099           0 :         *aPlacement = nsWindowZRelative;
    2100             : 
    2101           0 :       if (aImmediate) {
    2102           0 :         nsCOMPtr<nsIBaseWindow> ourBase = do_QueryObject(this);
    2103           0 :         if (ourBase) {
    2104           0 :           nsCOMPtr<nsIWidget> ourWidget;
    2105           0 :           ourBase->GetMainWidget(getter_AddRefs(ourWidget));
    2106           0 :           ourWidget->PlaceBehind(*aPlacement == nsWindowZBottom ?
    2107             :                                    eZPlacementBottom : eZPlacementBelow,
    2108           0 :                                  *aActualBelow, false);
    2109             :         }
    2110             :       }
    2111             :     }
    2112             : 
    2113             :     /* CalculateZPosition can tell us to be below nothing, because it tries
    2114             :        not to change something it doesn't recognize. A request to verify
    2115             :        being below an unrecognized window, then, is treated as a request
    2116             :        to come to the top (below null) */
    2117           0 :     nsCOMPtr<nsIXULWindow> windowAbove;
    2118           0 :     if (newPosition == nsIWindowMediator::zLevelBelow && *aActualBelow) {
    2119           0 :       windowAbove = (*aActualBelow)->GetWidgetListener()->GetXULWindow();
    2120             :     }
    2121             : 
    2122           0 :     mediator->SetZPosition(us, newPosition, windowAbove);
    2123             :   }
    2124             : 
    2125           0 :   return altered;
    2126             : }
    2127             : 
    2128             : /* Re-z-position all windows in the layers from aLowLevel to aHighLevel,
    2129             :    inclusive, to be behind aBehind. aBehind of null means on top.
    2130             :    Note this method actually does nothing to our relative window positions.
    2131             :    (And therefore there's no need to inform WindowMediator we're moving
    2132             :    things, because we aren't.) This method is useful for, say, moving
    2133             :    a range of layers of our own windows relative to windows belonging to
    2134             :    external applications.
    2135             : */
    2136           0 : void nsXULWindow::PlaceWindowLayersBehind(uint32_t aLowLevel,
    2137             :                                           uint32_t aHighLevel,
    2138             :                                           nsIXULWindow *aBehind)
    2139             : {
    2140             :   // step through windows in z-order from top to bottommost window
    2141             : 
    2142           0 :   nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
    2143           0 :   if (!mediator)
    2144           0 :     return;
    2145             : 
    2146           0 :   nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
    2147           0 :   mediator->GetZOrderXULWindowEnumerator(0, true,
    2148           0 :               getter_AddRefs(windowEnumerator));
    2149           0 :   if (!windowEnumerator)
    2150           0 :     return;
    2151             : 
    2152             :   // each window will be moved behind previousHighWidget, itself
    2153             :   // a moving target. initialize it.
    2154           0 :   nsCOMPtr<nsIWidget> previousHighWidget;
    2155           0 :   if (aBehind) {
    2156           0 :     nsCOMPtr<nsIBaseWindow> highBase(do_QueryInterface(aBehind));
    2157           0 :     if (highBase)
    2158           0 :       highBase->GetMainWidget(getter_AddRefs(previousHighWidget));
    2159             :   }
    2160             : 
    2161             :   // get next lower window
    2162             :   bool more;
    2163           0 :   while (NS_SUCCEEDED(windowEnumerator->HasMoreElements(&more)) && more) {
    2164             :     uint32_t nextZ; // z-level of nextWindow
    2165           0 :     nsCOMPtr<nsISupports> nextWindow;
    2166           0 :     windowEnumerator->GetNext(getter_AddRefs(nextWindow));
    2167           0 :     nsCOMPtr<nsIXULWindow> nextXULWindow(do_QueryInterface(nextWindow));
    2168           0 :     nextXULWindow->GetZLevel(&nextZ);
    2169           0 :     if (nextZ < aLowLevel)
    2170           0 :       break; // we've processed all windows through aLowLevel
    2171             : 
    2172             :     // move it just below its next higher window
    2173           0 :     nsCOMPtr<nsIBaseWindow> nextBase(do_QueryInterface(nextXULWindow));
    2174           0 :     if (nextBase) {
    2175           0 :       nsCOMPtr<nsIWidget> nextWidget;
    2176           0 :       nextBase->GetMainWidget(getter_AddRefs(nextWidget));
    2177           0 :       if (nextZ <= aHighLevel)
    2178           0 :         nextWidget->PlaceBehind(eZPlacementBelow, previousHighWidget, false);
    2179           0 :       previousHighWidget = nextWidget;
    2180             :     }
    2181             :   }
    2182             : }
    2183             : 
    2184           2 : void nsXULWindow::SetContentScrollbarVisibility(bool aVisible)
    2185             : {
    2186           2 :   nsCOMPtr<nsPIDOMWindowOuter> contentWin(do_GetInterface(mPrimaryContentShell));
    2187           2 :   if (!contentWin) {
    2188           2 :     return;
    2189             :   }
    2190             : 
    2191           0 :   nsContentUtils::SetScrollbarsVisibility(contentWin->GetDocShell(), aVisible);
    2192             : }
    2193             : 
    2194           2 : bool nsXULWindow::GetContentScrollbarVisibility()
    2195             : {
    2196             :   // This code already exists in dom/src/base/nsBarProp.cpp, but we
    2197             :   // can't safely get to that from here as this function is called
    2198             :   // while the DOM window is being set up, and we need the DOM window
    2199             :   // to get to that code.
    2200           4 :   nsCOMPtr<nsIScrollable> scroller(do_QueryInterface(mPrimaryContentShell));
    2201             : 
    2202           2 :   if (scroller) {
    2203             :     int32_t prefValue;
    2204           0 :     scroller->GetDefaultScrollbarPreferences(
    2205           0 :                   nsIScrollable::ScrollOrientation_Y, &prefValue);
    2206           0 :     if (prefValue == nsIScrollable::Scrollbar_Never) // try the other way
    2207           0 :       scroller->GetDefaultScrollbarPreferences(
    2208           0 :                   nsIScrollable::ScrollOrientation_X, &prefValue);
    2209             : 
    2210           0 :     if (prefValue == nsIScrollable::Scrollbar_Never)
    2211           0 :       return false;
    2212             :   }
    2213             : 
    2214           2 :   return true;
    2215             : }
    2216             : 
    2217             : // during spinup, attributes that haven't been loaded yet can't be dirty
    2218          10 : void nsXULWindow::PersistentAttributesDirty(uint32_t aDirtyFlags)
    2219             : {
    2220          10 :   mPersistentAttributesDirty |= aDirtyFlags & mPersistentAttributesMask;
    2221          10 : }
    2222             : 
    2223           3 : NS_IMETHODIMP nsXULWindow::ApplyChromeFlags()
    2224             : {
    2225           6 :   nsCOMPtr<dom::Element> window = GetWindowDOMElement();
    2226           3 :   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
    2227             : 
    2228           3 :   if (mChromeLoaded) {
    2229             :     // The two calls in this block don't need to happen early because they
    2230             :     // don't cause a global restyle on the document.  Not only that, but the
    2231             :     // scrollbar stuff needs a content area to toggle the scrollbars on anyway.
    2232             :     // So just don't do these until mChromeLoaded is true.
    2233             : 
    2234             :     // Scrollbars have their own special treatment.
    2235           2 :     SetContentScrollbarVisibility(mChromeFlags &
    2236             :                                   nsIWebBrowserChrome::CHROME_SCROLLBARS ?
    2237           2 :                                     true : false);
    2238             :   }
    2239             : 
    2240             :   /* the other flags are handled together. we have style rules
    2241             :      in navigator.css that trigger visibility based on
    2242             :      the 'chromehidden' attribute of the <window> tag. */
    2243           6 :   nsAutoString newvalue;
    2244             : 
    2245           3 :   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR))
    2246           0 :     newvalue.AppendLiteral("menubar ");
    2247             : 
    2248           3 :   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR))
    2249           0 :     newvalue.AppendLiteral("toolbar ");
    2250             : 
    2251           3 :   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_LOCATIONBAR))
    2252           0 :     newvalue.AppendLiteral("location ");
    2253             : 
    2254           3 :   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR))
    2255           0 :     newvalue.AppendLiteral("directories ");
    2256             : 
    2257           3 :   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR))
    2258           0 :     newvalue.AppendLiteral("status ");
    2259             : 
    2260           3 :   if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_EXTRA))
    2261           0 :     newvalue.AppendLiteral("extrachrome ");
    2262             : 
    2263             :   // Note that if we're not actually changing the value this will be a no-op,
    2264             :   // so no need to compare to the old value.
    2265           6 :   ErrorResult rv;
    2266           3 :   window->SetAttribute(NS_LITERAL_STRING("chromehidden"), newvalue, rv);
    2267             : 
    2268           3 :   return NS_OK;
    2269             : }
    2270             : 
    2271           5 : NS_IMETHODIMP nsXULWindow::GetXULBrowserWindow(nsIXULBrowserWindow * *aXULBrowserWindow)
    2272             : {
    2273           5 :   NS_IF_ADDREF(*aXULBrowserWindow = mXULBrowserWindow);
    2274           5 :   return NS_OK;
    2275             : }
    2276             : 
    2277           1 : NS_IMETHODIMP nsXULWindow::SetXULBrowserWindow(nsIXULBrowserWindow * aXULBrowserWindow)
    2278             : {
    2279           1 :   mXULBrowserWindow = aXULBrowserWindow;
    2280           1 :   return NS_OK;
    2281             : }
    2282             : 
    2283           0 : void nsXULWindow::SizeShellToWithLimit(int32_t aDesiredWidth,
    2284             :                                        int32_t aDesiredHeight,
    2285             :                                        int32_t shellItemWidth,
    2286             :                                        int32_t shellItemHeight)
    2287             : {
    2288           0 :   int32_t widthDelta = aDesiredWidth - shellItemWidth;
    2289           0 :   int32_t heightDelta = aDesiredHeight - shellItemHeight;
    2290             : 
    2291           0 :   if (widthDelta || heightDelta) {
    2292           0 :     int32_t winWidth = 0;
    2293           0 :     int32_t winHeight = 0;
    2294             : 
    2295           0 :     GetSize(&winWidth, &winHeight);
    2296             :     // There's no point in trying to make the window smaller than the
    2297             :     // desired content area size --- that's not likely to work. This whole
    2298             :     // function assumes that the outer docshell is adding some constant
    2299             :     // "border" chrome to the content area.
    2300           0 :     winWidth = std::max(winWidth + widthDelta, aDesiredWidth);
    2301           0 :     winHeight = std::max(winHeight + heightDelta, aDesiredHeight);
    2302           0 :     SetSize(winWidth, winHeight, true);
    2303             :   }
    2304           0 : }
    2305             : 
    2306             : nsresult
    2307           0 : nsXULWindow::GetTabCount(uint32_t* aResult)
    2308             : {
    2309           0 :   if (mXULBrowserWindow) {
    2310           0 :     return mXULBrowserWindow->GetTabCount(aResult);
    2311             :   }
    2312             : 
    2313           0 :   *aResult = 0;
    2314           0 :   return NS_OK;
    2315             : }
    2316             : 
    2317             : nsresult
    2318           1 : nsXULWindow::GetNextTabParentId(uint64_t* aNextTabParentId)
    2319             : {
    2320           1 :   NS_ENSURE_ARG_POINTER(aNextTabParentId);
    2321           1 :   *aNextTabParentId = mNextTabParentId;
    2322           1 :   return NS_OK;
    2323           9 : }

Generated by: LCOV version 1.13