xpfe/appshell/src/nsXULWindow.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpfe/appshell/src/nsXULWindow.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2082 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim:set ts=2 sw=2 sts=2 ci et: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "mozilla/MathAlgorithms.h"
    1.11 +
    1.12 +// Local includes
    1.13 +#include "nsXULWindow.h"
    1.14 +#include <algorithm>
    1.15 +
    1.16 +// Helper classes
    1.17 +#include "nsPrintfCString.h"
    1.18 +#include "nsString.h"
    1.19 +#include "nsWidgetsCID.h"
    1.20 +#include "prprf.h"
    1.21 +#include "nsCRT.h"
    1.22 +#include "nsThreadUtils.h"
    1.23 +#include "nsNetCID.h"
    1.24 +
    1.25 +//Interfaces needed to be included
    1.26 +#include "nsIAppShell.h"
    1.27 +#include "nsIAppShellService.h"
    1.28 +#include "nsIServiceManager.h"
    1.29 +#include "nsIContentViewer.h"
    1.30 +#include "nsIDocument.h"
    1.31 +#include "nsIDOMDocument.h"
    1.32 +#include "nsIDOMXULDocument.h"
    1.33 +#include "nsIDOMElement.h"
    1.34 +#include "nsIDOMXULElement.h"
    1.35 +#include "nsPIDOMWindow.h"
    1.36 +#include "nsIDOMScreen.h"
    1.37 +#include "nsIEmbeddingSiteWindow.h"
    1.38 +#include "nsIInterfaceRequestor.h"
    1.39 +#include "nsIInterfaceRequestorUtils.h"
    1.40 +#include "nsIIOService.h"
    1.41 +#include "nsIMarkupDocumentViewer.h"
    1.42 +#include "nsIObserverService.h"
    1.43 +#include "nsIWindowMediator.h"
    1.44 +#include "nsIScreenManager.h"
    1.45 +#include "nsIScreen.h"
    1.46 +#include "nsIScrollable.h"
    1.47 +#include "nsIScriptSecurityManager.h"
    1.48 +#include "nsIWindowWatcher.h"
    1.49 +#include "nsIURI.h"
    1.50 +#include "nsIDOMCSSStyleDeclaration.h"
    1.51 +#include "nsAppShellCID.h"
    1.52 +#include "nsReadableUtils.h"
    1.53 +#include "nsStyleConsts.h"
    1.54 +#include "nsPresContext.h"
    1.55 +#include "nsContentUtils.h"
    1.56 +#include "nsWebShellWindow.h" // get rid of this one, too...
    1.57 +#include "nsGlobalWindow.h"
    1.58 +
    1.59 +#include "prenv.h"
    1.60 +#include "mozilla/AutoRestore.h"
    1.61 +#include "mozilla/Preferences.h"
    1.62 +#include "mozilla/dom/BarProps.h"
    1.63 +#include "mozilla/dom/Element.h"
    1.64 +#include "mozilla/dom/Event.h"
    1.65 +#include "mozilla/dom/ScriptSettings.h"
    1.66 +
    1.67 +using namespace mozilla;
    1.68 +using dom::AutoNoJSAPI;
    1.69 +
    1.70 +#define SIZEMODE_NORMAL     NS_LITERAL_STRING("normal")
    1.71 +#define SIZEMODE_MAXIMIZED  NS_LITERAL_STRING("maximized")
    1.72 +#define SIZEMODE_MINIMIZED  NS_LITERAL_STRING("minimized")
    1.73 +#define SIZEMODE_FULLSCREEN NS_LITERAL_STRING("fullscreen")
    1.74 +
    1.75 +#define WINDOWTYPE_ATTRIBUTE NS_LITERAL_STRING("windowtype")
    1.76 +
    1.77 +#define PERSIST_ATTRIBUTE  NS_LITERAL_STRING("persist")
    1.78 +#define SCREENX_ATTRIBUTE  NS_LITERAL_STRING("screenX")
    1.79 +#define SCREENY_ATTRIBUTE  NS_LITERAL_STRING("screenY")
    1.80 +#define WIDTH_ATTRIBUTE    NS_LITERAL_STRING("width")
    1.81 +#define HEIGHT_ATTRIBUTE   NS_LITERAL_STRING("height")
    1.82 +#define MODE_ATTRIBUTE     NS_LITERAL_STRING("sizemode")
    1.83 +#define ZLEVEL_ATTRIBUTE   NS_LITERAL_STRING("zlevel")
    1.84 +
    1.85 +
    1.86 +//*****************************************************************************
    1.87 +//***    nsXULWindow: Object Management
    1.88 +//*****************************************************************************
    1.89 +
    1.90 +nsXULWindow::nsXULWindow(uint32_t aChromeFlags)
    1.91 +  : mChromeTreeOwner(nullptr), 
    1.92 +    mContentTreeOwner(nullptr),
    1.93 +    mPrimaryContentTreeOwner(nullptr),
    1.94 +    mModalStatus(NS_OK),
    1.95 +    mContinueModalLoop(false),
    1.96 +    mDebuting(false),
    1.97 +    mChromeLoaded(false), 
    1.98 +    mShowAfterLoad(false),
    1.99 +    mIntrinsicallySized(false),
   1.100 +    mCenterAfterLoad(false),
   1.101 +    mIsHiddenWindow(false),
   1.102 +    mLockedUntilChromeLoad(false),
   1.103 +    mIgnoreXULSize(false),
   1.104 +    mIgnoreXULPosition(false),
   1.105 +    mChromeFlagsFrozen(false),
   1.106 +    mIgnoreXULSizeMode(false),
   1.107 +    mDestroying(false),
   1.108 +    mContextFlags(0),
   1.109 +    mPersistentAttributesDirty(0),
   1.110 +    mPersistentAttributesMask(0),
   1.111 +    mChromeFlags(aChromeFlags)
   1.112 +{
   1.113 +}
   1.114 +
   1.115 +nsXULWindow::~nsXULWindow()
   1.116 +{
   1.117 +  Destroy();
   1.118 +}
   1.119 +
   1.120 +//*****************************************************************************
   1.121 +// nsXULWindow::nsISupports
   1.122 +//*****************************************************************************
   1.123 +
   1.124 +NS_IMPL_ADDREF(nsXULWindow)
   1.125 +NS_IMPL_RELEASE(nsXULWindow)
   1.126 +
   1.127 +NS_INTERFACE_MAP_BEGIN(nsXULWindow)
   1.128 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULWindow)
   1.129 +  NS_INTERFACE_MAP_ENTRY(nsIXULWindow)
   1.130 +  NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
   1.131 +  NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   1.132 +  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   1.133 +  if (aIID.Equals(NS_GET_IID(nsXULWindow)))
   1.134 +    foundInterface = reinterpret_cast<nsISupports*>(this);
   1.135 +  else
   1.136 +NS_INTERFACE_MAP_END
   1.137 +
   1.138 +//*****************************************************************************
   1.139 +// nsXULWindow::nsIIntefaceRequestor
   1.140 +//*****************************************************************************   
   1.141 +
   1.142 +NS_IMETHODIMP nsXULWindow::GetInterface(const nsIID& aIID, void** aSink)
   1.143 +{
   1.144 +  nsresult rv;
   1.145 +
   1.146 +  NS_ENSURE_ARG_POINTER(aSink);
   1.147 +
   1.148 +  if (aIID.Equals(NS_GET_IID(nsIPrompt))) {
   1.149 +    rv = EnsurePrompter();
   1.150 +    if (NS_FAILED(rv)) return rv;
   1.151 +    return mPrompter->QueryInterface(aIID, aSink);
   1.152 +  }   
   1.153 +  if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
   1.154 +    rv = EnsureAuthPrompter();
   1.155 +    if (NS_FAILED(rv)) return rv;
   1.156 +    return mAuthPrompter->QueryInterface(aIID, aSink);
   1.157 +  }
   1.158 +  if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
   1.159 +    return GetWindowDOMWindow(reinterpret_cast<nsIDOMWindow**>(aSink));
   1.160 +  }
   1.161 +  if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) {
   1.162 +    nsIDOMWindow* domWindow = nullptr;
   1.163 +    rv = GetWindowDOMWindow(&domWindow);
   1.164 +    nsIDOMWindowInternal* domWindowInternal =
   1.165 +      static_cast<nsIDOMWindowInternal*>(domWindow);
   1.166 +    *aSink = domWindowInternal;
   1.167 +    return rv;
   1.168 +  }
   1.169 +  if (aIID.Equals(NS_GET_IID(nsIWebBrowserChrome)) && 
   1.170 +    NS_SUCCEEDED(EnsureContentTreeOwner()) &&
   1.171 +    NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
   1.172 +    return NS_OK;
   1.173 +
   1.174 +  if (aIID.Equals(NS_GET_IID(nsIEmbeddingSiteWindow)) && 
   1.175 +    NS_SUCCEEDED(EnsureContentTreeOwner()) &&
   1.176 +    NS_SUCCEEDED(mContentTreeOwner->QueryInterface(aIID, aSink)))
   1.177 +    return NS_OK;
   1.178 +
   1.179 +  return QueryInterface(aIID, aSink);
   1.180 +}
   1.181 +
   1.182 +//*****************************************************************************
   1.183 +// nsXULWindow::nsIXULWindow
   1.184 +//*****************************************************************************   
   1.185 +
   1.186 +NS_IMETHODIMP nsXULWindow::GetDocShell(nsIDocShell** aDocShell)
   1.187 +{
   1.188 +  NS_ENSURE_ARG_POINTER(aDocShell);
   1.189 +
   1.190 +  *aDocShell = mDocShell;
   1.191 +  NS_IF_ADDREF(*aDocShell);
   1.192 +  return NS_OK;
   1.193 +}
   1.194 +
   1.195 +NS_IMETHODIMP nsXULWindow::GetZLevel(uint32_t *outLevel)
   1.196 +{
   1.197 +  nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   1.198 +  if (mediator)
   1.199 +    mediator->GetZLevel(this, outLevel);
   1.200 +  else
   1.201 +    *outLevel = normalZ;
   1.202 +  return NS_OK;
   1.203 +}
   1.204 +
   1.205 +NS_IMETHODIMP nsXULWindow::SetZLevel(uint32_t aLevel)
   1.206 +{
   1.207 +  nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   1.208 +  if (!mediator)
   1.209 +    return NS_ERROR_FAILURE;
   1.210 +
   1.211 +  uint32_t zLevel;
   1.212 +  mediator->GetZLevel(this, &zLevel);
   1.213 +  if (zLevel == aLevel)
   1.214 +    return NS_OK;
   1.215 +
   1.216 +  /* refuse to raise a maximized window above the normal browser level,
   1.217 +     for fear it could hide newly opened browser windows */
   1.218 +  if (aLevel > nsIXULWindow::normalZ && mWindow) {
   1.219 +    int32_t sizeMode = mWindow->SizeMode();
   1.220 +    if (sizeMode == nsSizeMode_Maximized || sizeMode == nsSizeMode_Fullscreen) {
   1.221 +      return NS_ERROR_FAILURE;
   1.222 +    }
   1.223 +  }
   1.224 +
   1.225 +  // do it
   1.226 +  mediator->SetZLevel(this, aLevel);
   1.227 +  PersistentAttributesDirty(PAD_MISC);
   1.228 +  SavePersistentAttributes();
   1.229 +
   1.230 +  nsCOMPtr<nsIContentViewer> cv;
   1.231 +  mDocShell->GetContentViewer(getter_AddRefs(cv));
   1.232 +  if (cv) {
   1.233 +    nsCOMPtr<nsIDocument> doc = cv->GetDocument();
   1.234 +    if (doc) {
   1.235 +      ErrorResult rv;
   1.236 +      nsRefPtr<dom::Event> event =
   1.237 +        doc->CreateEvent(NS_LITERAL_STRING("Events"),rv);
   1.238 +      if (event) {
   1.239 +        event->InitEvent(NS_LITERAL_STRING("windowZLevel"), true, false);
   1.240 +
   1.241 +        event->SetTrusted(true);
   1.242 +
   1.243 +        bool defaultActionEnabled;
   1.244 +        doc->DispatchEvent(event, &defaultActionEnabled);
   1.245 +      }
   1.246 +    }
   1.247 +  }
   1.248 +  return NS_OK;
   1.249 +}
   1.250 +
   1.251 +NS_IMETHODIMP nsXULWindow::GetContextFlags(uint32_t *aContextFlags)
   1.252 +{
   1.253 +  NS_ENSURE_ARG_POINTER(aContextFlags);
   1.254 +  *aContextFlags = mContextFlags;
   1.255 +  return NS_OK;
   1.256 +}
   1.257 +
   1.258 +NS_IMETHODIMP nsXULWindow::SetContextFlags(uint32_t aContextFlags)
   1.259 +{
   1.260 +  mContextFlags = aContextFlags;
   1.261 +  return NS_OK;
   1.262 +}
   1.263 +
   1.264 +NS_IMETHODIMP nsXULWindow::GetChromeFlags(uint32_t *aChromeFlags)
   1.265 +{
   1.266 +  NS_ENSURE_ARG_POINTER(aChromeFlags);
   1.267 +  *aChromeFlags = mChromeFlags;
   1.268 +  /* mChromeFlags is kept up to date, except for scrollbar visibility.
   1.269 +     That can be changed directly by the content DOM window, which
   1.270 +     doesn't know to update the chrome window. So that we must check
   1.271 +     separately. */
   1.272 +
   1.273 +  // however, it's pointless to ask if the window isn't set up yet
   1.274 +  if (!mChromeLoaded)
   1.275 +    return NS_OK;
   1.276 +
   1.277 +  if (GetContentScrollbarVisibility())
   1.278 +    *aChromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS;
   1.279 +  else
   1.280 +    *aChromeFlags &= ~nsIWebBrowserChrome::CHROME_SCROLLBARS;
   1.281 +
   1.282 +  return NS_OK;
   1.283 +}
   1.284 +
   1.285 +NS_IMETHODIMP nsXULWindow::SetChromeFlags(uint32_t aChromeFlags)
   1.286 +{
   1.287 +  NS_ASSERTION(!mChromeFlagsFrozen,
   1.288 +               "SetChromeFlags() after AssumeChromeFlagsAreFrozen()!");
   1.289 +
   1.290 +  mChromeFlags = aChromeFlags;
   1.291 +  if (mChromeLoaded)
   1.292 +    NS_ENSURE_SUCCESS(ApplyChromeFlags(), NS_ERROR_FAILURE);
   1.293 +  return NS_OK;
   1.294 +}
   1.295 +
   1.296 +NS_IMETHODIMP nsXULWindow::AssumeChromeFlagsAreFrozen()
   1.297 +{
   1.298 +  mChromeFlagsFrozen = true;
   1.299 +  return NS_OK;
   1.300 +}
   1.301 +
   1.302 +NS_IMETHODIMP nsXULWindow::SetIntrinsicallySized(bool aIntrinsicallySized)
   1.303 +{
   1.304 +  mIntrinsicallySized = aIntrinsicallySized;
   1.305 +  return NS_OK;
   1.306 +}
   1.307 +
   1.308 +NS_IMETHODIMP nsXULWindow::GetIntrinsicallySized(bool* aIntrinsicallySized)
   1.309 +{
   1.310 +  NS_ENSURE_ARG_POINTER(aIntrinsicallySized);
   1.311 +
   1.312 +  *aIntrinsicallySized = mIntrinsicallySized;
   1.313 +  return NS_OK;
   1.314 +}
   1.315 +
   1.316 +NS_IMETHODIMP nsXULWindow::GetPrimaryContentShell(nsIDocShellTreeItem** 
   1.317 +   aDocShellTreeItem)
   1.318 +{
   1.319 +  NS_ENSURE_ARG_POINTER(aDocShellTreeItem);
   1.320 +  NS_IF_ADDREF(*aDocShellTreeItem = mPrimaryContentShell);
   1.321 +  return NS_OK;
   1.322 +}
   1.323 +
   1.324 +NS_IMETHODIMP nsXULWindow::GetContentShellById(const char16_t* aID, 
   1.325 +   nsIDocShellTreeItem** aDocShellTreeItem)
   1.326 +{
   1.327 +  NS_ENSURE_ARG_POINTER(aDocShellTreeItem);
   1.328 +  *aDocShellTreeItem = nullptr;
   1.329 +
   1.330 +  uint32_t count = mContentShells.Length();
   1.331 +  for (uint32_t i = 0; i < count; i++) {
   1.332 +    nsContentShellInfo* shellInfo = mContentShells.ElementAt(i);
   1.333 +    if (shellInfo->id.Equals(aID)) {
   1.334 +      *aDocShellTreeItem = nullptr;
   1.335 +      if (shellInfo->child)
   1.336 +        CallQueryReferent(shellInfo->child.get(), aDocShellTreeItem);
   1.337 +      return NS_OK;
   1.338 +    }
   1.339 +  }
   1.340 +  return NS_ERROR_FAILURE;
   1.341 +}
   1.342 +
   1.343 +NS_IMETHODIMP nsXULWindow::AddChildWindow(nsIXULWindow *aChild)
   1.344 +{
   1.345 +  // we're not really keeping track of this right now
   1.346 +  return NS_OK;
   1.347 +}
   1.348 +
   1.349 +NS_IMETHODIMP nsXULWindow::RemoveChildWindow(nsIXULWindow *aChild)
   1.350 +{
   1.351 +  // we're not really keeping track of this right now
   1.352 +  return NS_OK;
   1.353 +}
   1.354 +
   1.355 +NS_IMETHODIMP nsXULWindow::ShowModal()
   1.356 +{
   1.357 +  // Store locally so it doesn't die on us
   1.358 +  nsCOMPtr<nsIWidget> window = mWindow;
   1.359 +  nsCOMPtr<nsIXULWindow> tempRef = this;  
   1.360 +
   1.361 +  window->SetModal(true);
   1.362 +  mContinueModalLoop = true;
   1.363 +  EnableParent(false);
   1.364 +
   1.365 +  {
   1.366 +    AutoNoJSAPI nojsapi;
   1.367 +    nsIThread *thread = NS_GetCurrentThread();
   1.368 +    while (mContinueModalLoop) {
   1.369 +      if (!NS_ProcessNextEvent(thread))
   1.370 +        break;
   1.371 +    }
   1.372 +  }
   1.373 +
   1.374 +  mContinueModalLoop = false;
   1.375 +  window->SetModal(false);
   1.376 +  /*   Note there's no EnableParent(true) here to match the false one
   1.377 +     above. That's done in ExitModalLoop. It's important that the parent
   1.378 +     be re-enabled before this window is made invisible; to do otherwise
   1.379 +     causes bizarre z-ordering problems. At this point, the window is
   1.380 +     already invisible.
   1.381 +       No known current implementation of Enable would have a problem with
   1.382 +     re-enabling the parent twice, so we could do it again here without
   1.383 +     breaking any current implementation. But that's unnecessary if the
   1.384 +     modal loop is always exited using ExitModalLoop (the other way would be
   1.385 +     to change the protected member variable directly.)
   1.386 +  */
   1.387 +
   1.388 +  return mModalStatus;
   1.389 +}
   1.390 +
   1.391 +//*****************************************************************************
   1.392 +// nsXULWindow::nsIBaseWindow
   1.393 +//*****************************************************************************   
   1.394 +
   1.395 +NS_IMETHODIMP nsXULWindow::InitWindow(nativeWindow aParentNativeWindow,
   1.396 +   nsIWidget* parentWidget, int32_t x, int32_t y, int32_t cx, int32_t cy)   
   1.397 +{
   1.398 +  //XXX First Check In
   1.399 +  NS_ASSERTION(false, "Not Yet Implemented");
   1.400 +  return NS_OK;
   1.401 +}
   1.402 +
   1.403 +NS_IMETHODIMP nsXULWindow::Create()
   1.404 +{
   1.405 +  //XXX First Check In
   1.406 +  NS_ASSERTION(false, "Not Yet Implemented");
   1.407 +  return NS_OK;
   1.408 +}
   1.409 +
   1.410 +NS_IMETHODIMP nsXULWindow::Destroy()
   1.411 +{
   1.412 +  if (!mWindow)
   1.413 +     return NS_OK;
   1.414 +
   1.415 +  // Ensure we don't reenter this code
   1.416 +  if (mDestroying)
   1.417 +    return NS_OK;
   1.418 +
   1.419 +  mozilla::AutoRestore<bool> guard(mDestroying);
   1.420 +  mDestroying = true;
   1.421 +
   1.422 +  nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
   1.423 +  NS_ASSERTION(appShell, "Couldn't get appShell... xpcom shutdown?");
   1.424 +  if (appShell)
   1.425 +    appShell->UnregisterTopLevelWindow(static_cast<nsIXULWindow*>(this));
   1.426 +
   1.427 +  nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow));
   1.428 +  if (parentWindow)
   1.429 +    parentWindow->RemoveChildWindow(this);
   1.430 +
   1.431 +  // let's make sure the window doesn't get deleted out from under us
   1.432 +  // while we are trying to close....this can happen if the docshell
   1.433 +  // we close ends up being the last owning reference to this xulwindow
   1.434 +
   1.435 +  // XXXTAB This shouldn't be an issue anymore because the ownership model
   1.436 +  // only goes in one direction.  When webshell container is fully removed
   1.437 +  // try removing this...
   1.438 +
   1.439 +  nsCOMPtr<nsIXULWindow> placeHolder = this;
   1.440 +
   1.441 +  // Remove modality (if any) and hide while destroying. More than
   1.442 +  // a convenience, the hide prevents user interaction with the partially
   1.443 +  // destroyed window. This is especially necessary when the eldest window
   1.444 +  // in a stack of modal windows is destroyed first. It happens.
   1.445 +  ExitModalLoop(NS_OK);
   1.446 +  if (mWindow)
   1.447 +    mWindow->Show(false);
   1.448 +
   1.449 +#if defined(XP_WIN)
   1.450 +  // We need to explicitly set the focus on Windows, but 
   1.451 +  // only if the parent is visible.
   1.452 +  nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
   1.453 +  if (parent) {
   1.454 +    nsCOMPtr<nsIWidget> parentWidget;
   1.455 +    parent->GetMainWidget(getter_AddRefs(parentWidget));
   1.456 +    if (!parentWidget || parentWidget->IsVisible()) {
   1.457 +      nsCOMPtr<nsIBaseWindow> baseHiddenWindow;
   1.458 +      if (appShell) {
   1.459 +        nsCOMPtr<nsIXULWindow> hiddenWindow;
   1.460 +        appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
   1.461 +        if (hiddenWindow)
   1.462 +          baseHiddenWindow = do_GetInterface(hiddenWindow);
   1.463 +      }
   1.464 +      // somebody screwed up somewhere. hiddenwindow shouldn't be anybody's
   1.465 +      // parent. still, when it happens, skip activating it.
   1.466 +      if (baseHiddenWindow != parent) {
   1.467 +        nsCOMPtr<nsIWidget> parentWidget;
   1.468 +        parent->GetMainWidget(getter_AddRefs(parentWidget));
   1.469 +        if (parentWidget)
   1.470 +          parentWidget->PlaceBehind(eZPlacementTop, 0, true);
   1.471 +      }
   1.472 +    }
   1.473 +  }
   1.474 +#endif
   1.475 +   
   1.476 +  mDOMWindow = nullptr;
   1.477 +  if (mDocShell) {
   1.478 +    nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
   1.479 +    shellAsWin->Destroy();
   1.480 +    mDocShell = nullptr; // this can cause reentrancy of this function
   1.481 +  }
   1.482 +
   1.483 +  // Remove our ref on the content shells
   1.484 +  uint32_t count = mContentShells.Length();
   1.485 +  for (uint32_t i = 0; i < count; i++) {
   1.486 +    nsContentShellInfo* shellInfo = mContentShells.ElementAt(i);
   1.487 +    delete shellInfo;
   1.488 +  }
   1.489 +  mContentShells.Clear();
   1.490 +  mPrimaryContentShell = nullptr;
   1.491 +
   1.492 +  if (mContentTreeOwner) {
   1.493 +    mContentTreeOwner->XULWindow(nullptr);
   1.494 +    NS_RELEASE(mContentTreeOwner);
   1.495 +  }
   1.496 +  if (mPrimaryContentTreeOwner) {
   1.497 +    mPrimaryContentTreeOwner->XULWindow(nullptr);
   1.498 +    NS_RELEASE(mPrimaryContentTreeOwner);
   1.499 +  }
   1.500 +  if (mChromeTreeOwner) {
   1.501 +    mChromeTreeOwner->XULWindow(nullptr);
   1.502 +    NS_RELEASE(mChromeTreeOwner);
   1.503 +  }
   1.504 +  if (mWindow) {
   1.505 +    mWindow->SetWidgetListener(nullptr); // nsWebShellWindow hackery
   1.506 +    mWindow->Destroy();
   1.507 +    mWindow = nullptr;
   1.508 +  }
   1.509 +
   1.510 +  if (!mIsHiddenWindow) {
   1.511 +    /* Inform appstartup we've destroyed this window and it could
   1.512 +       quit now if it wanted. This must happen at least after mDocShell
   1.513 +       is destroyed, because onunload handlers fire then, and those being
   1.514 +       script, anything could happen. A new window could open, even.
   1.515 +       See bug 130719. */
   1.516 +    nsCOMPtr<nsIObserverService> obssvc =
   1.517 +        do_GetService("@mozilla.org/observer-service;1");
   1.518 +    NS_ASSERTION(obssvc, "Couldn't get observer service?");
   1.519 +
   1.520 +    if (obssvc)
   1.521 +      obssvc->NotifyObservers(nullptr, "xul-window-destroyed", nullptr);
   1.522 +  }
   1.523 +
   1.524 +  return NS_OK;
   1.525 +}
   1.526 +
   1.527 +NS_IMETHODIMP nsXULWindow::GetUnscaledDevicePixelsPerCSSPixel(double *aScale)
   1.528 +{
   1.529 +  *aScale = mWindow ? mWindow->GetDefaultScale().scale : 1.0;
   1.530 +  return NS_OK;
   1.531 +}
   1.532 +
   1.533 +NS_IMETHODIMP nsXULWindow::SetPosition(int32_t aX, int32_t aY)
   1.534 +{
   1.535 +  // Don't reset the window's size mode here - platforms that don't want to move
   1.536 +  // maximized windows should reset it in their respective Move implementation.
   1.537 +  CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
   1.538 +  double invScale = 1.0 / scale.scale;
   1.539 +  nsresult rv = mWindow->Move(aX * invScale, aY * invScale);
   1.540 +  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   1.541 +  if (!mChromeLoaded) {
   1.542 +    // If we're called before the chrome is loaded someone obviously wants this
   1.543 +    // window at this position. We don't persist this one-time position.
   1.544 +    mIgnoreXULPosition = true;
   1.545 +    return NS_OK;
   1.546 +  }
   1.547 +  PersistentAttributesDirty(PAD_POSITION);
   1.548 +  SavePersistentAttributes();
   1.549 +  return NS_OK;
   1.550 +}
   1.551 +
   1.552 +NS_IMETHODIMP nsXULWindow::GetPosition(int32_t* aX, int32_t* aY)
   1.553 +{
   1.554 +  return GetPositionAndSize(aX, aY, nullptr, nullptr);
   1.555 +}
   1.556 +
   1.557 +NS_IMETHODIMP nsXULWindow::SetSize(int32_t aCX, int32_t aCY, bool aRepaint)
   1.558 +{
   1.559 +  /* any attempt to set the window's size or position overrides the window's
   1.560 +     zoom state. this is important when these two states are competing while
   1.561 +     the window is being opened. but it should probably just always be so. */
   1.562 +  mWindow->SetSizeMode(nsSizeMode_Normal);
   1.563 +
   1.564 +  mIntrinsicallySized = false;
   1.565 +
   1.566 +  CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
   1.567 +  double invScale = 1.0 / scale.scale;
   1.568 +  nsresult rv = mWindow->Resize(aCX * invScale, aCY * invScale, aRepaint);
   1.569 +  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   1.570 +  if (!mChromeLoaded) {
   1.571 +    // If we're called before the chrome is loaded someone obviously wants this
   1.572 +    // window at this size & in the normal size mode (since it is the only mode
   1.573 +    // in which setting dimensions makes sense). We don't persist this one-time
   1.574 +    // size.
   1.575 +    mIgnoreXULSize = true;
   1.576 +    mIgnoreXULSizeMode = true;
   1.577 +    return NS_OK;
   1.578 +  }
   1.579 +  PersistentAttributesDirty(PAD_SIZE);
   1.580 +  SavePersistentAttributes();
   1.581 +  return NS_OK;
   1.582 +}
   1.583 +
   1.584 +NS_IMETHODIMP nsXULWindow::GetSize(int32_t* aCX, int32_t* aCY)
   1.585 +{
   1.586 +  return GetPositionAndSize(nullptr, nullptr, aCX, aCY);
   1.587 +}
   1.588 +
   1.589 +NS_IMETHODIMP nsXULWindow::SetPositionAndSize(int32_t aX, int32_t aY, 
   1.590 +   int32_t aCX, int32_t aCY, bool aRepaint)
   1.591 +{
   1.592 +  /* any attempt to set the window's size or position overrides the window's
   1.593 +     zoom state. this is important when these two states are competing while
   1.594 +     the window is being opened. but it should probably just always be so. */
   1.595 +  mWindow->SetSizeMode(nsSizeMode_Normal);
   1.596 +
   1.597 +  mIntrinsicallySized = false;
   1.598 +
   1.599 +  CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
   1.600 +  double invScale = 1.0 / scale.scale;
   1.601 +  nsresult rv = mWindow->Resize(aX * invScale, aY * invScale,
   1.602 +                                aCX * invScale, aCY * invScale,
   1.603 +                                aRepaint);
   1.604 +  NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   1.605 +  if (!mChromeLoaded) {
   1.606 +    // If we're called before the chrome is loaded someone obviously wants this
   1.607 +    // window at this size and position. We don't persist this one-time setting.
   1.608 +    mIgnoreXULPosition = true;
   1.609 +    mIgnoreXULSize = true;
   1.610 +    mIgnoreXULSizeMode = true;
   1.611 +    return NS_OK;
   1.612 +  }
   1.613 +  PersistentAttributesDirty(PAD_POSITION | PAD_SIZE);
   1.614 +  SavePersistentAttributes();
   1.615 +  return NS_OK;
   1.616 +}
   1.617 +
   1.618 +NS_IMETHODIMP nsXULWindow::GetPositionAndSize(int32_t* x, int32_t* y, int32_t* cx,
   1.619 +   int32_t* cy)
   1.620 +{
   1.621 +  nsIntRect rect;
   1.622 +
   1.623 +  if (!mWindow)
   1.624 +    return NS_ERROR_FAILURE;
   1.625 +
   1.626 +  mWindow->GetScreenBounds(rect);
   1.627 +
   1.628 +  if (x)
   1.629 +    *x = rect.x;
   1.630 +  if (y)
   1.631 +    *y = rect.y;
   1.632 +  if (cx)
   1.633 +    *cx = rect.width;
   1.634 +  if (cy)
   1.635 +    *cy = rect.height;
   1.636 +
   1.637 +  return NS_OK;
   1.638 +}
   1.639 +
   1.640 +NS_IMETHODIMP nsXULWindow::Center(nsIXULWindow *aRelative, bool aScreen, bool aAlert)
   1.641 +{
   1.642 +  int32_t  left, top, width, height,
   1.643 +           ourWidth, ourHeight;
   1.644 +  bool     screenCoordinates =  false,
   1.645 +           windowCoordinates =  false;
   1.646 +  nsresult result;
   1.647 +
   1.648 +  if (!mChromeLoaded) {
   1.649 +    // note we lose the parameters. at time of writing, this isn't a problem.
   1.650 +    mCenterAfterLoad = true;
   1.651 +    return NS_OK;
   1.652 +  }
   1.653 +
   1.654 +  if (!aScreen && !aRelative)
   1.655 +    return NS_ERROR_INVALID_ARG;
   1.656 +
   1.657 +  nsCOMPtr<nsIScreenManager> screenmgr = do_GetService("@mozilla.org/gfx/screenmanager;1", &result);
   1.658 +  if (NS_FAILED(result))
   1.659 +    return result;
   1.660 +
   1.661 +  nsCOMPtr<nsIScreen> screen;
   1.662 +
   1.663 +  if (aRelative) {
   1.664 +    nsCOMPtr<nsIBaseWindow> base(do_QueryInterface(aRelative, &result));
   1.665 +    if (base) {
   1.666 +      // get window rect
   1.667 +      result = base->GetPositionAndSize(&left, &top, &width, &height);
   1.668 +      if (NS_SUCCEEDED(result)) {
   1.669 +        double scale;
   1.670 +        if (NS_SUCCEEDED(base->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
   1.671 +          // convert device-pixel coordinates to global display pixels
   1.672 +          left = NSToIntRound(left / scale);
   1.673 +          top = NSToIntRound(top / scale);
   1.674 +          width = NSToIntRound(width / scale);
   1.675 +          height = NSToIntRound(height / scale);
   1.676 +        }
   1.677 +        // if centering on screen, convert that to the corresponding screen
   1.678 +        if (aScreen)
   1.679 +          screenmgr->ScreenForRect(left, top, width, height, getter_AddRefs(screen));
   1.680 +        else
   1.681 +          windowCoordinates = true;
   1.682 +      } else {
   1.683 +        // something's wrong with the reference window.
   1.684 +        // fall back to the primary screen
   1.685 +        aRelative = 0;
   1.686 +        aScreen = true;
   1.687 +      }
   1.688 +    }
   1.689 +  }
   1.690 +  if (!aRelative) {
   1.691 +    if (!mOpenerScreenRect.IsEmpty()) {
   1.692 +      // FIXME - check if these are device or display pixels
   1.693 +      screenmgr->ScreenForRect(mOpenerScreenRect.x, mOpenerScreenRect.y,
   1.694 +                               mOpenerScreenRect.width, mOpenerScreenRect.height,
   1.695 +                               getter_AddRefs(screen));
   1.696 +    } else {
   1.697 +      screenmgr->GetPrimaryScreen(getter_AddRefs(screen));
   1.698 +    }
   1.699 +  }
   1.700 +
   1.701 +  if (aScreen && screen) {
   1.702 +    screen->GetAvailRectDisplayPix(&left, &top, &width, &height);
   1.703 +    screenCoordinates = true;
   1.704 +  }
   1.705 +
   1.706 +  if (screenCoordinates || windowCoordinates) {
   1.707 +    NS_ASSERTION(mWindow, "what, no window?");
   1.708 +    CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
   1.709 +    GetSize(&ourWidth, &ourHeight);
   1.710 +    ourWidth = NSToIntRound(ourWidth / scale.scale);
   1.711 +    ourHeight = NSToIntRound(ourHeight / scale.scale);
   1.712 +    left += (width - ourWidth) / 2;
   1.713 +    top += (height - ourHeight) / (aAlert ? 3 : 2);
   1.714 +    if (windowCoordinates) {
   1.715 +      mWindow->ConstrainPosition(false, &left, &top);
   1.716 +    }
   1.717 +    SetPosition(left * scale.scale, top * scale.scale);
   1.718 +    return NS_OK;
   1.719 +  }
   1.720 +  return NS_ERROR_FAILURE;
   1.721 +}
   1.722 +
   1.723 +NS_IMETHODIMP nsXULWindow::Repaint(bool aForce)
   1.724 +{
   1.725 +  //XXX First Check In
   1.726 +  NS_ASSERTION(false, "Not Yet Implemented");
   1.727 +  return NS_OK;
   1.728 +}
   1.729 +
   1.730 +NS_IMETHODIMP nsXULWindow::GetParentWidget(nsIWidget** aParentWidget)
   1.731 +{
   1.732 +  NS_ENSURE_ARG_POINTER(aParentWidget);
   1.733 +  NS_ENSURE_STATE(mWindow);
   1.734 +
   1.735 +  NS_IF_ADDREF(*aParentWidget = mWindow->GetParent());
   1.736 +  return NS_OK;
   1.737 +}
   1.738 +
   1.739 +NS_IMETHODIMP nsXULWindow::SetParentWidget(nsIWidget* aParentWidget)
   1.740 +{
   1.741 +  //XXX First Check In
   1.742 +  NS_ASSERTION(false, "Not Yet Implemented");
   1.743 +  return NS_OK;
   1.744 +}
   1.745 +
   1.746 +NS_IMETHODIMP nsXULWindow::GetParentNativeWindow(nativeWindow* aParentNativeWindow)
   1.747 +{
   1.748 +  NS_ENSURE_ARG_POINTER(aParentNativeWindow);
   1.749 +
   1.750 +  nsCOMPtr<nsIWidget> parentWidget;
   1.751 +  NS_ENSURE_SUCCESS(GetParentWidget(getter_AddRefs(parentWidget)), NS_ERROR_FAILURE);
   1.752 +
   1.753 +  if (parentWidget) {
   1.754 +    *aParentNativeWindow = parentWidget->GetNativeData(NS_NATIVE_WIDGET);
   1.755 +  }
   1.756 +
   1.757 +  return NS_OK;
   1.758 +}
   1.759 +
   1.760 +NS_IMETHODIMP nsXULWindow::SetParentNativeWindow(nativeWindow aParentNativeWindow)
   1.761 +{
   1.762 +  //XXX First Check In
   1.763 +  NS_ASSERTION(false, "Not Yet Implemented");
   1.764 +  return NS_OK;
   1.765 +}
   1.766 +
   1.767 +NS_IMETHODIMP nsXULWindow::GetNativeHandle(nsAString& aNativeHandle)
   1.768 +{
   1.769 +  nsCOMPtr<nsIWidget> mainWidget;
   1.770 +  NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(mainWidget)), NS_ERROR_FAILURE);
   1.771 +
   1.772 +  if (mainWidget) {
   1.773 +    nativeWindow nativeWindowPtr = mainWidget->GetNativeData(NS_NATIVE_WINDOW);
   1.774 +    /* the nativeWindow pointer is converted to and exposed as a string. This
   1.775 +       is a more reliable way not to lose information (as opposed to JS
   1.776 +       |Number| for instance) */
   1.777 +    aNativeHandle = NS_ConvertASCIItoUTF16(nsPrintfCString("0x%p", nativeWindowPtr));
   1.778 +  }
   1.779 +
   1.780 +  return NS_OK;
   1.781 +}
   1.782 +
   1.783 +NS_IMETHODIMP nsXULWindow::GetVisibility(bool* aVisibility)
   1.784 +{
   1.785 +  NS_ENSURE_ARG_POINTER(aVisibility);
   1.786 +
   1.787 +  // Always claim to be visible for now. See bug
   1.788 +  // https://bugzilla.mozilla.org/show_bug.cgi?id=306245.
   1.789 +
   1.790 +  *aVisibility = true;
   1.791 +
   1.792 +  return NS_OK;
   1.793 +}
   1.794 +
   1.795 +NS_IMETHODIMP nsXULWindow::SetVisibility(bool aVisibility)
   1.796 +{
   1.797 +  if (!mChromeLoaded) {
   1.798 +    mShowAfterLoad = aVisibility;
   1.799 +    return NS_OK;
   1.800 +  }
   1.801 +
   1.802 +  if (mDebuting) {
   1.803 +    return NS_OK;
   1.804 +  }
   1.805 +  mDebuting = true;  // (Show / Focus is recursive)
   1.806 +
   1.807 +  //XXXTAB Do we really need to show docshell and the window?  Isn't 
   1.808 +  // the window good enough?
   1.809 +  nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(mDocShell));
   1.810 +  shellAsWin->SetVisibility(aVisibility);
   1.811 +  // Store locally so it doesn't die on us. 'Show' can result in the window
   1.812 +  // being closed with nsXULWindow::Destroy being called. That would set
   1.813 +  // mWindow to null and posibly destroy the nsIWidget while its Show method
   1.814 +  // is on the stack. We need to keep it alive until Show finishes.
   1.815 +  nsCOMPtr<nsIWidget> window = mWindow;
   1.816 +  window->Show(aVisibility);
   1.817 +
   1.818 +  nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   1.819 +  if (windowMediator)
   1.820 +     windowMediator->UpdateWindowTimeStamp(static_cast<nsIXULWindow*>(this));
   1.821 +
   1.822 +  // notify observers so that we can hide the splash screen if possible
   1.823 +  nsCOMPtr<nsIObserverService> obssvc
   1.824 +    (do_GetService("@mozilla.org/observer-service;1"));
   1.825 +  NS_ASSERTION(obssvc, "Couldn't get observer service.");
   1.826 +  if (obssvc) {
   1.827 +    obssvc->NotifyObservers(nullptr, "xul-window-visible", nullptr); 
   1.828 +  }
   1.829 +
   1.830 +  mDebuting = false;
   1.831 +  return NS_OK;
   1.832 +}
   1.833 +
   1.834 +NS_IMETHODIMP nsXULWindow::GetEnabled(bool *aEnabled)
   1.835 +{
   1.836 +  NS_ENSURE_ARG_POINTER(aEnabled);
   1.837 +
   1.838 +  if (mWindow) {
   1.839 +    *aEnabled = mWindow->IsEnabled();
   1.840 +    return NS_OK;
   1.841 +  }
   1.842 +
   1.843 +  *aEnabled = true; // better guess than most
   1.844 +  return NS_ERROR_FAILURE;
   1.845 +}
   1.846 +
   1.847 +NS_IMETHODIMP nsXULWindow::SetEnabled(bool aEnable)
   1.848 +{
   1.849 +  if (mWindow) {
   1.850 +    mWindow->Enable(aEnable);
   1.851 +    return NS_OK;
   1.852 +  }
   1.853 +  return NS_ERROR_FAILURE;
   1.854 +}
   1.855 +
   1.856 +NS_IMETHODIMP nsXULWindow::GetMainWidget(nsIWidget** aMainWidget)
   1.857 +{
   1.858 +  NS_ENSURE_ARG_POINTER(aMainWidget);
   1.859 +   
   1.860 +  *aMainWidget = mWindow;
   1.861 +  NS_IF_ADDREF(*aMainWidget);
   1.862 +  return NS_OK;
   1.863 +}
   1.864 +
   1.865 +NS_IMETHODIMP nsXULWindow::SetFocus()
   1.866 +{
   1.867 +  //XXX First Check In
   1.868 +  NS_ASSERTION(false, "Not Yet Implemented");
   1.869 +  return NS_OK;
   1.870 +}
   1.871 +
   1.872 +NS_IMETHODIMP nsXULWindow::GetTitle(char16_t** aTitle)
   1.873 +{
   1.874 +  NS_ENSURE_ARG_POINTER(aTitle);
   1.875 +
   1.876 +  *aTitle = ToNewUnicode(mTitle);
   1.877 +  if (!*aTitle)
   1.878 +    return NS_ERROR_OUT_OF_MEMORY;
   1.879 +  return NS_OK;
   1.880 +}
   1.881 +
   1.882 +NS_IMETHODIMP nsXULWindow::SetTitle(const char16_t* aTitle)
   1.883 +{
   1.884 +  NS_ENSURE_STATE(mWindow);
   1.885 +  mTitle.Assign(aTitle);
   1.886 +  mTitle.StripChars("\n\r");
   1.887 +  NS_ENSURE_SUCCESS(mWindow->SetTitle(mTitle), NS_ERROR_FAILURE);
   1.888 +
   1.889 +  // Tell the window mediator that a title has changed
   1.890 +  nsCOMPtr<nsIWindowMediator> windowMediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   1.891 +  if (!windowMediator)
   1.892 +    return NS_OK;
   1.893 +
   1.894 +  windowMediator->UpdateWindowTitle(static_cast<nsIXULWindow*>(this), aTitle);
   1.895 +
   1.896 +  return NS_OK;
   1.897 +}
   1.898 +
   1.899 +
   1.900 +//*****************************************************************************
   1.901 +// nsXULWindow: Helpers
   1.902 +//*****************************************************************************   
   1.903 +
   1.904 +NS_IMETHODIMP nsXULWindow::EnsureChromeTreeOwner()
   1.905 +{
   1.906 +  if (mChromeTreeOwner)
   1.907 +    return NS_OK;
   1.908 +
   1.909 +  mChromeTreeOwner = new nsChromeTreeOwner();
   1.910 +  NS_ENSURE_TRUE(mChromeTreeOwner, NS_ERROR_OUT_OF_MEMORY);
   1.911 +
   1.912 +  NS_ADDREF(mChromeTreeOwner);
   1.913 +  mChromeTreeOwner->XULWindow(this);
   1.914 +
   1.915 +  return NS_OK;
   1.916 +}
   1.917 +
   1.918 +NS_IMETHODIMP nsXULWindow::EnsureContentTreeOwner()
   1.919 +{
   1.920 +  if (mContentTreeOwner)
   1.921 +    return NS_OK;
   1.922 +
   1.923 +  mContentTreeOwner = new nsContentTreeOwner(false);
   1.924 +  NS_ENSURE_TRUE(mContentTreeOwner, NS_ERROR_FAILURE);
   1.925 +
   1.926 +  NS_ADDREF(mContentTreeOwner);
   1.927 +  mContentTreeOwner->XULWindow(this);
   1.928 +   
   1.929 +  return NS_OK;
   1.930 +}
   1.931 +
   1.932 +NS_IMETHODIMP nsXULWindow::EnsurePrimaryContentTreeOwner()
   1.933 +{
   1.934 +  if (mPrimaryContentTreeOwner)
   1.935 +    return NS_OK;
   1.936 +
   1.937 +  mPrimaryContentTreeOwner = new nsContentTreeOwner(true);
   1.938 +  NS_ENSURE_TRUE(mPrimaryContentTreeOwner, NS_ERROR_FAILURE);
   1.939 +
   1.940 +  NS_ADDREF(mPrimaryContentTreeOwner);
   1.941 +  mPrimaryContentTreeOwner->XULWindow(this);
   1.942 +
   1.943 +  return NS_OK;
   1.944 +}
   1.945 +
   1.946 +NS_IMETHODIMP nsXULWindow::EnsurePrompter()
   1.947 +{
   1.948 +  if (mPrompter)
   1.949 +    return NS_OK;
   1.950 +   
   1.951 +  nsCOMPtr<nsIDOMWindow> ourWindow;
   1.952 +  nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow));
   1.953 +  if (NS_SUCCEEDED(rv)) {
   1.954 +    nsCOMPtr<nsIWindowWatcher> wwatch = 
   1.955 +        do_GetService(NS_WINDOWWATCHER_CONTRACTID);
   1.956 +    if (wwatch)
   1.957 +      wwatch->GetNewPrompter(ourWindow, getter_AddRefs(mPrompter));
   1.958 +  }
   1.959 +  return mPrompter ? NS_OK : NS_ERROR_FAILURE;
   1.960 +}
   1.961 +
   1.962 +NS_IMETHODIMP nsXULWindow::EnsureAuthPrompter()
   1.963 +{
   1.964 +  if (mAuthPrompter)
   1.965 +    return NS_OK;
   1.966 +      
   1.967 +  nsCOMPtr<nsIDOMWindow> ourWindow;
   1.968 +  nsresult rv = GetWindowDOMWindow(getter_AddRefs(ourWindow));
   1.969 +  if (NS_SUCCEEDED(rv)) {
   1.970 +    nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
   1.971 +    if (wwatch)
   1.972 +      wwatch->GetNewAuthPrompter(ourWindow, getter_AddRefs(mAuthPrompter));
   1.973 +  }
   1.974 +  return mAuthPrompter ? NS_OK : NS_ERROR_FAILURE;
   1.975 +}
   1.976 + 
   1.977 +void nsXULWindow::OnChromeLoaded()
   1.978 +{
   1.979 +  nsresult rv = EnsureContentTreeOwner();
   1.980 +
   1.981 +  if (NS_SUCCEEDED(rv)) {
   1.982 +    mChromeLoaded = true;
   1.983 +    ApplyChromeFlags();
   1.984 +    SyncAttributesToWidget();
   1.985 +    if (!mIgnoreXULSize)
   1.986 +      LoadSizeFromXUL();
   1.987 +    if (mIntrinsicallySized) {
   1.988 +      // (if LoadSizeFromXUL set the size, mIntrinsicallySized will be false)
   1.989 +      nsCOMPtr<nsIContentViewer> cv;
   1.990 +      mDocShell->GetContentViewer(getter_AddRefs(cv));
   1.991 +      nsCOMPtr<nsIMarkupDocumentViewer> markupViewer = do_QueryInterface(cv);
   1.992 +      if (markupViewer) {
   1.993 +        nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = do_QueryInterface(mDocShell);
   1.994 +        nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
   1.995 +        docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
   1.996 +        if (treeOwner) {
   1.997 +          int32_t width, height;
   1.998 +          markupViewer->GetContentSize(&width, &height);
   1.999 +          treeOwner->SizeShellTo(docShellAsItem, width, height);
  1.1000 +        }
  1.1001 +      }
  1.1002 +    }
  1.1003 +
  1.1004 +    bool positionSet = !mIgnoreXULPosition;
  1.1005 +    nsCOMPtr<nsIXULWindow> parentWindow(do_QueryReferent(mParentWindow));
  1.1006 +#if defined(XP_UNIX) && !defined(XP_MACOSX)
  1.1007 +    // don't override WM placement on unix for independent, top-level windows
  1.1008 +    // (however, we think the benefits of intelligent dependent window placement
  1.1009 +    // trump that override.)
  1.1010 +    if (!parentWindow)
  1.1011 +      positionSet = false;
  1.1012 +#endif
  1.1013 +    if (positionSet)
  1.1014 +      positionSet = LoadPositionFromXUL();
  1.1015 +    LoadMiscPersistentAttributesFromXUL();
  1.1016 +
  1.1017 +    if (mCenterAfterLoad && !positionSet)
  1.1018 +      Center(parentWindow, parentWindow ? false : true, false);
  1.1019 +
  1.1020 +    if (mShowAfterLoad) {
  1.1021 +      SetVisibility(true);
  1.1022 +      // At this point the window may have been closed during Show(), so
  1.1023 +      // nsXULWindow::Destroy may already have been called. Take care!
  1.1024 +    }
  1.1025 +  }
  1.1026 +  mPersistentAttributesMask |= PAD_POSITION | PAD_SIZE | PAD_MISC;
  1.1027 +}
  1.1028 +
  1.1029 +bool nsXULWindow::LoadPositionFromXUL()
  1.1030 +{
  1.1031 +  bool     gotPosition = false;
  1.1032 +
  1.1033 +  // if we're the hidden window, don't try to validate our size/position. We're
  1.1034 +  // special.
  1.1035 +  if (mIsHiddenWindow)
  1.1036 +    return false;
  1.1037 +
  1.1038 +  nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1.1039 +  NS_ENSURE_TRUE(windowElement, false);
  1.1040 +
  1.1041 +  int32_t currX = 0;
  1.1042 +  int32_t currY = 0;
  1.1043 +  int32_t currWidth = 0;
  1.1044 +  int32_t currHeight = 0;
  1.1045 +  nsresult errorCode;
  1.1046 +  int32_t temp;
  1.1047 +
  1.1048 +  GetPositionAndSize(&currX, &currY, &currWidth, &currHeight);
  1.1049 +
  1.1050 +  // Convert to global display pixels for consistent window management across
  1.1051 +  // screens with diverse resolutions
  1.1052 +  CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
  1.1053 +  currX = NSToIntRound(currX / scale.scale);
  1.1054 +  currY = NSToIntRound(currY / scale.scale);
  1.1055 +  currWidth = NSToIntRound(currWidth / scale.scale);
  1.1056 +  currHeight = NSToIntRound(currHeight / scale.scale);
  1.1057 +
  1.1058 +  // Obtain the position information from the <xul:window> element.
  1.1059 +  int32_t specX = currX;
  1.1060 +  int32_t specY = currY;
  1.1061 +  nsAutoString posString;
  1.1062 +
  1.1063 +  windowElement->GetAttribute(SCREENX_ATTRIBUTE, posString);
  1.1064 +  temp = posString.ToInteger(&errorCode);
  1.1065 +  if (NS_SUCCEEDED(errorCode)) {
  1.1066 +    specX = temp;
  1.1067 +    gotPosition = true;
  1.1068 +  }
  1.1069 +  windowElement->GetAttribute(SCREENY_ATTRIBUTE, posString);
  1.1070 +  temp = posString.ToInteger(&errorCode);
  1.1071 +  if (NS_SUCCEEDED(errorCode)) {
  1.1072 +    specY = temp;
  1.1073 +    gotPosition = true;
  1.1074 +  }
  1.1075 +
  1.1076 +  if (gotPosition) {
  1.1077 +    // our position will be relative to our parent, if any
  1.1078 +    nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
  1.1079 +    if (parent) {
  1.1080 +      int32_t parentX, parentY;
  1.1081 +      if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
  1.1082 +        double scale;
  1.1083 +        if (NS_SUCCEEDED(parent->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
  1.1084 +          parentX = NSToIntRound(parentX / scale);
  1.1085 +          parentY = NSToIntRound(parentY / scale);
  1.1086 +        }
  1.1087 +        specX += parentX;
  1.1088 +        specY += parentY;
  1.1089 +      }
  1.1090 +    }
  1.1091 +    else {
  1.1092 +      StaggerPosition(specX, specY, currWidth, currHeight);
  1.1093 +    }
  1.1094 +  }
  1.1095 +  mWindow->ConstrainPosition(false, &specX, &specY);
  1.1096 +  if (specX != currX || specY != currY) {
  1.1097 +    CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
  1.1098 +    SetPosition(specX * scale.scale, specY * scale.scale);
  1.1099 +  }
  1.1100 +
  1.1101 +  return gotPosition;
  1.1102 +}
  1.1103 +
  1.1104 +bool nsXULWindow::LoadSizeFromXUL()
  1.1105 +{
  1.1106 +  bool     gotSize = false;
  1.1107 +
  1.1108 +  // if we're the hidden window, don't try to validate our size/position. We're
  1.1109 +  // special.
  1.1110 +  if (mIsHiddenWindow)
  1.1111 +    return false;
  1.1112 +
  1.1113 +  nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1.1114 +  NS_ENSURE_TRUE(windowElement, false);
  1.1115 +
  1.1116 +  int32_t currWidth = 0;
  1.1117 +  int32_t currHeight = 0;
  1.1118 +  nsresult errorCode;
  1.1119 +  int32_t temp;
  1.1120 +
  1.1121 +  NS_ASSERTION(mWindow, "we expected to have a window already");
  1.1122 +
  1.1123 +  CSSToLayoutDeviceScale scale = mWindow ? mWindow->GetDefaultScale()
  1.1124 +                                         : CSSToLayoutDeviceScale(1.0);
  1.1125 +  GetSize(&currWidth, &currHeight);
  1.1126 +  currWidth = NSToIntRound(currWidth / scale.scale);
  1.1127 +  currHeight = NSToIntRound(currHeight / scale.scale);
  1.1128 +
  1.1129 +  // Obtain the position and sizing information from the <xul:window> element.
  1.1130 +  int32_t specWidth = currWidth;
  1.1131 +  int32_t specHeight = currHeight;
  1.1132 +  nsAutoString sizeString;
  1.1133 +
  1.1134 +  windowElement->GetAttribute(WIDTH_ATTRIBUTE, sizeString);
  1.1135 +  temp = sizeString.ToInteger(&errorCode);
  1.1136 +  if (NS_SUCCEEDED(errorCode) && temp > 0) {
  1.1137 +    specWidth = std::max(temp, 100);
  1.1138 +    gotSize = true;
  1.1139 +  }
  1.1140 +  windowElement->GetAttribute(HEIGHT_ATTRIBUTE, sizeString);
  1.1141 +  temp = sizeString.ToInteger(&errorCode);
  1.1142 +  if (NS_SUCCEEDED(errorCode) && temp > 0) {
  1.1143 +    specHeight = std::max(temp, 100);
  1.1144 +    gotSize = true;
  1.1145 +  }
  1.1146 +
  1.1147 +  if (gotSize) {
  1.1148 +    // constrain to screen size
  1.1149 +    nsCOMPtr<nsIDOMWindow> domWindow;
  1.1150 +    GetWindowDOMWindow(getter_AddRefs(domWindow));
  1.1151 +    if (domWindow) {
  1.1152 +      nsCOMPtr<nsIDOMScreen> screen;
  1.1153 +      domWindow->GetScreen(getter_AddRefs(screen));
  1.1154 +      if (screen) {
  1.1155 +        int32_t screenWidth;
  1.1156 +        int32_t screenHeight;
  1.1157 +        screen->GetAvailWidth(&screenWidth);
  1.1158 +        screen->GetAvailHeight(&screenHeight);
  1.1159 +        if (specWidth > screenWidth)
  1.1160 +          specWidth = screenWidth;
  1.1161 +        if (specHeight > screenHeight)
  1.1162 +          specHeight = screenHeight;
  1.1163 +      }
  1.1164 +    }
  1.1165 +
  1.1166 +    mIntrinsicallySized = false;
  1.1167 +    if (specWidth != currWidth || specHeight != currHeight) {
  1.1168 +      CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
  1.1169 +      SetSize(specWidth * scale.scale, specHeight * scale.scale, false);
  1.1170 +    }
  1.1171 +  }
  1.1172 +
  1.1173 +  return gotSize;
  1.1174 +}
  1.1175 +
  1.1176 +/* Miscellaneous persistent attributes are attributes named in the
  1.1177 +   |persist| attribute, other than size and position. Those are special
  1.1178 +   because it's important to load those before one of the misc
  1.1179 +   attributes (sizemode) and they require extra processing. */
  1.1180 +bool nsXULWindow::LoadMiscPersistentAttributesFromXUL()
  1.1181 +{
  1.1182 +  bool     gotState = false;
  1.1183 +
  1.1184 +  /* There are no misc attributes of interest to the hidden window.
  1.1185 +     It's especially important not to try to validate that window's
  1.1186 +     size or position, because some platforms (Mac OS X) need to
  1.1187 +     make it visible and offscreen. */
  1.1188 +  if (mIsHiddenWindow)
  1.1189 +    return false;
  1.1190 +
  1.1191 +  nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1.1192 +  NS_ENSURE_TRUE(windowElement, false);
  1.1193 +
  1.1194 +  nsAutoString stateString;
  1.1195 +
  1.1196 +  // sizemode
  1.1197 +  windowElement->GetAttribute(MODE_ATTRIBUTE, stateString);
  1.1198 +  int32_t sizeMode = nsSizeMode_Normal;
  1.1199 +  /* ignore request to minimize, to not confuse novices
  1.1200 +  if (stateString.Equals(SIZEMODE_MINIMIZED))
  1.1201 +    sizeMode = nsSizeMode_Minimized;
  1.1202 +  */
  1.1203 +  if (!mIgnoreXULSizeMode &&
  1.1204 +      (stateString.Equals(SIZEMODE_MAXIMIZED) || stateString.Equals(SIZEMODE_FULLSCREEN))) {
  1.1205 +    /* Honor request to maximize only if the window is sizable.
  1.1206 +       An unsizable, unmaximizable, yet maximized window confuses
  1.1207 +       Windows OS and is something of a travesty, anyway. */
  1.1208 +    if (mChromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) {
  1.1209 +      mIntrinsicallySized = false;
  1.1210 +
  1.1211 +      if (stateString.Equals(SIZEMODE_MAXIMIZED))
  1.1212 +        sizeMode = nsSizeMode_Maximized;
  1.1213 +      else
  1.1214 +        sizeMode = nsSizeMode_Fullscreen;
  1.1215 +    }
  1.1216 +  }
  1.1217 +
  1.1218 +  // If we are told to ignore the size mode attribute update the
  1.1219 +  // document so the attribute and window are in sync.
  1.1220 +  if (mIgnoreXULSizeMode) {
  1.1221 +    nsAutoString sizeString;
  1.1222 +    if (sizeMode == nsSizeMode_Maximized)
  1.1223 +      sizeString.Assign(SIZEMODE_MAXIMIZED);
  1.1224 +    else if (sizeMode == nsSizeMode_Fullscreen)
  1.1225 +      sizeString.Assign(SIZEMODE_FULLSCREEN);
  1.1226 +    else if (sizeMode == nsSizeMode_Normal)
  1.1227 +      sizeString.Assign(SIZEMODE_NORMAL);
  1.1228 +    if (!sizeString.IsEmpty()) {
  1.1229 +      ErrorResult rv;
  1.1230 +      windowElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv);
  1.1231 +    }
  1.1232 +  }
  1.1233 +
  1.1234 +  if (sizeMode == nsSizeMode_Fullscreen) {
  1.1235 +    nsCOMPtr<nsIDOMWindow> ourWindow;
  1.1236 +    GetWindowDOMWindow(getter_AddRefs(ourWindow));
  1.1237 +    ourWindow->SetFullScreen(true);
  1.1238 +  } else {
  1.1239 +    mWindow->SetSizeMode(sizeMode);
  1.1240 +  }
  1.1241 +  gotState = true;
  1.1242 +
  1.1243 +  // zlevel
  1.1244 +  windowElement->GetAttribute(ZLEVEL_ATTRIBUTE, stateString);
  1.1245 +  if (!stateString.IsEmpty()) {
  1.1246 +    nsresult errorCode;
  1.1247 +    int32_t zLevel = stateString.ToInteger(&errorCode);
  1.1248 +    if (NS_SUCCEEDED(errorCode) && zLevel >= lowestZ && zLevel <= highestZ)
  1.1249 +      SetZLevel(zLevel);
  1.1250 +  }
  1.1251 +
  1.1252 +  return gotState;
  1.1253 +}
  1.1254 +
  1.1255 +/* Stagger windows of the same type so they don't appear on top of each other.
  1.1256 +   This code does have a scary double loop -- it'll keep passing through
  1.1257 +   the entire list of open windows until it finds a non-collision. Doesn't
  1.1258 +   seem to be a problem, but it deserves watching.
  1.1259 +*/
  1.1260 +void nsXULWindow::StaggerPosition(int32_t &aRequestedX, int32_t &aRequestedY,
  1.1261 +                                  int32_t aSpecWidth, int32_t aSpecHeight)
  1.1262 +{
  1.1263 +  const int32_t kOffset = 22;
  1.1264 +  const uint32_t kSlop  = 4;
  1.1265 +
  1.1266 +  bool     keepTrying;
  1.1267 +  int      bouncedX = 0, // bounced off vertical edge of screen
  1.1268 +           bouncedY = 0; // bounced off horizontal edge
  1.1269 +
  1.1270 +  // look for any other windows of this type
  1.1271 +  nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  1.1272 +  if (!wm)
  1.1273 +    return;
  1.1274 +
  1.1275 +  nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1.1276 +  if (!windowElement)
  1.1277 +    return;
  1.1278 +
  1.1279 +  nsCOMPtr<nsIXULWindow> ourXULWindow(this);
  1.1280 +
  1.1281 +  nsAutoString windowType;
  1.1282 +  windowElement->GetAttribute(WINDOWTYPE_ATTRIBUTE, windowType);
  1.1283 +
  1.1284 +  int32_t screenTop = 0,    // it's pointless to initialize these ...
  1.1285 +          screenRight = 0,  // ... but to prevent oversalubrious and ...
  1.1286 +          screenBottom = 0, // ... underbright compilers from ...
  1.1287 +          screenLeft = 0;   // ... issuing warnings.
  1.1288 +  bool    gotScreen = false;
  1.1289 +
  1.1290 +  { // fetch screen coordinates
  1.1291 +    nsCOMPtr<nsIScreenManager> screenMgr(do_GetService(
  1.1292 +                                         "@mozilla.org/gfx/screenmanager;1"));
  1.1293 +    if (screenMgr) {
  1.1294 +      nsCOMPtr<nsIScreen> ourScreen;
  1.1295 +      // the coordinates here are already display pixels
  1.1296 +      screenMgr->ScreenForRect(aRequestedX, aRequestedY,
  1.1297 +                               aSpecWidth, aSpecHeight,
  1.1298 +                               getter_AddRefs(ourScreen));
  1.1299 +      if (ourScreen) {
  1.1300 +        int32_t screenWidth, screenHeight;
  1.1301 +        ourScreen->GetAvailRectDisplayPix(&screenLeft, &screenTop,
  1.1302 +                                          &screenWidth, &screenHeight);
  1.1303 +        screenBottom = screenTop + screenHeight;
  1.1304 +        screenRight = screenLeft + screenWidth;
  1.1305 +        gotScreen = true;
  1.1306 +      }
  1.1307 +    }
  1.1308 +  }
  1.1309 +
  1.1310 +  // One full pass through all windows of this type, repeat until no collisions.
  1.1311 +  do {
  1.1312 +    keepTrying = false;
  1.1313 +    nsCOMPtr<nsISimpleEnumerator> windowList;
  1.1314 +    wm->GetXULWindowEnumerator(windowType.get(), getter_AddRefs(windowList));
  1.1315 +
  1.1316 +    if (!windowList)
  1.1317 +      break;
  1.1318 +
  1.1319 +    // One full pass through all windows of this type, offset and stop on collision.
  1.1320 +    do {
  1.1321 +      bool more;
  1.1322 +      windowList->HasMoreElements(&more);
  1.1323 +      if (!more)
  1.1324 +        break;
  1.1325 +
  1.1326 +      nsCOMPtr<nsISupports> supportsWindow;
  1.1327 +      windowList->GetNext(getter_AddRefs(supportsWindow));
  1.1328 +
  1.1329 +      nsCOMPtr<nsIXULWindow> listXULWindow(do_QueryInterface(supportsWindow));
  1.1330 +      if (listXULWindow != ourXULWindow) {
  1.1331 +        int32_t listX, listY;
  1.1332 +        nsCOMPtr<nsIBaseWindow> listBaseWindow(do_QueryInterface(supportsWindow));
  1.1333 +        listBaseWindow->GetPosition(&listX, &listY);
  1.1334 +        double scale;
  1.1335 +        if (NS_SUCCEEDED(listBaseWindow->GetUnscaledDevicePixelsPerCSSPixel(&scale))) {
  1.1336 +          listX = NSToIntRound(listX / scale);
  1.1337 +          listY = NSToIntRound(listY / scale);
  1.1338 +        }
  1.1339 +
  1.1340 +        if (Abs(listX - aRequestedX) <= kSlop && Abs(listY - aRequestedY) <= kSlop) {
  1.1341 +          // collision! offset and start over
  1.1342 +          if (bouncedX & 0x1)
  1.1343 +            aRequestedX -= kOffset;
  1.1344 +          else
  1.1345 +            aRequestedX += kOffset;
  1.1346 +          aRequestedY += kOffset;
  1.1347 +
  1.1348 +          if (gotScreen) {
  1.1349 +            // if we're moving to the right and we need to bounce...
  1.1350 +            if (!(bouncedX & 0x1) && ((aRequestedX + aSpecWidth) > screenRight)) {
  1.1351 +              aRequestedX = screenRight - aSpecWidth;
  1.1352 +              ++bouncedX;
  1.1353 +            }
  1.1354 +
  1.1355 +            // if we're moving to the left and we need to bounce...
  1.1356 +            if ((bouncedX & 0x1) && aRequestedX < screenLeft) {
  1.1357 +              aRequestedX = screenLeft;
  1.1358 +              ++bouncedX;
  1.1359 +            }
  1.1360 +
  1.1361 +            // if we hit the bottom then bounce to the top
  1.1362 +            if (aRequestedY + aSpecHeight > screenBottom) {
  1.1363 +              aRequestedY = screenTop;
  1.1364 +              ++bouncedY;
  1.1365 +            }
  1.1366 +          }
  1.1367 +
  1.1368 +          /* loop around again,
  1.1369 +             but it's time to give up once we've covered the screen.
  1.1370 +             there's a potential infinite loop with lots of windows. */
  1.1371 +          keepTrying = bouncedX < 2 || bouncedY == 0;
  1.1372 +          break;
  1.1373 +        }
  1.1374 +      }
  1.1375 +    } while(1);
  1.1376 +  } while (keepTrying);
  1.1377 +}
  1.1378 +
  1.1379 +void nsXULWindow::SyncAttributesToWidget()
  1.1380 +{
  1.1381 +  nsCOMPtr<dom::Element> windowElement = GetWindowDOMElement();
  1.1382 +  if (!windowElement)
  1.1383 +    return;
  1.1384 +
  1.1385 +  nsAutoString attr;
  1.1386 +
  1.1387 +  // "hidechrome" attribute
  1.1388 +  if (windowElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidechrome,
  1.1389 +                                 nsGkAtoms::_true, eCaseMatters)) {
  1.1390 +    mWindow->HideWindowChrome(true);
  1.1391 +  }
  1.1392 +
  1.1393 +  // "chromemargin" attribute
  1.1394 +  nsIntMargin margins;
  1.1395 +  windowElement->GetAttribute(NS_LITERAL_STRING("chromemargin"), attr);
  1.1396 +  if (nsContentUtils::ParseIntMarginValue(attr, margins)) {
  1.1397 +    mWindow->SetNonClientMargins(margins);
  1.1398 +  }
  1.1399 +
  1.1400 +  // "accelerated" attribute
  1.1401 +  bool isAccelerated = windowElement->HasAttribute(NS_LITERAL_STRING("accelerated"));
  1.1402 +  mWindow->SetLayersAcceleration(isAccelerated);
  1.1403 +
  1.1404 +  // "windowtype" attribute
  1.1405 +  windowElement->GetAttribute(WINDOWTYPE_ATTRIBUTE, attr);
  1.1406 +  if (!attr.IsEmpty()) {
  1.1407 +    mWindow->SetWindowClass(attr);
  1.1408 +  }
  1.1409 +
  1.1410 +  // "id" attribute for icon
  1.1411 +  windowElement->GetAttribute(NS_LITERAL_STRING("id"), attr);
  1.1412 +  if (attr.IsEmpty()) {
  1.1413 +    attr.AssignLiteral("default");
  1.1414 +  }
  1.1415 +  mWindow->SetIcon(attr);
  1.1416 +
  1.1417 +  // "drawtitle" attribute
  1.1418 +  windowElement->GetAttribute(NS_LITERAL_STRING("drawtitle"), attr);
  1.1419 +  mWindow->SetDrawsTitle(attr.LowerCaseEqualsLiteral("true"));
  1.1420 +
  1.1421 +  // "toggletoolbar" attribute
  1.1422 +  windowElement->GetAttribute(NS_LITERAL_STRING("toggletoolbar"), attr);
  1.1423 +  mWindow->SetShowsToolbarButton(attr.LowerCaseEqualsLiteral("true"));
  1.1424 +
  1.1425 +  // "fullscreenbutton" attribute
  1.1426 +  windowElement->GetAttribute(NS_LITERAL_STRING("fullscreenbutton"), attr);
  1.1427 +  mWindow->SetShowsFullScreenButton(attr.LowerCaseEqualsLiteral("true"));
  1.1428 +
  1.1429 +  // "macanimationtype" attribute
  1.1430 +  windowElement->GetAttribute(NS_LITERAL_STRING("macanimationtype"), attr);
  1.1431 +  if (attr.EqualsLiteral("document")) {
  1.1432 +    mWindow->SetWindowAnimationType(nsIWidget::eDocumentWindowAnimation);
  1.1433 +  }
  1.1434 +}
  1.1435 +
  1.1436 +NS_IMETHODIMP nsXULWindow::SavePersistentAttributes()
  1.1437 +{
  1.1438 +  // can happen when the persistence timer fires at an inopportune time
  1.1439 +  // during window shutdown
  1.1440 +  if (!mDocShell)
  1.1441 +    return NS_ERROR_FAILURE;
  1.1442 +
  1.1443 +  nsCOMPtr<dom::Element> docShellElement = GetWindowDOMElement();
  1.1444 +  if (!docShellElement)
  1.1445 +    return NS_ERROR_FAILURE;
  1.1446 +
  1.1447 +  nsAutoString   persistString;
  1.1448 +  docShellElement->GetAttribute(PERSIST_ATTRIBUTE, persistString);
  1.1449 +  if (persistString.IsEmpty()) { // quick check which sometimes helps
  1.1450 +    mPersistentAttributesDirty = 0;
  1.1451 +    return NS_OK;
  1.1452 +  }
  1.1453 +
  1.1454 +  // get our size, position and mode to persist
  1.1455 +  int32_t x, y, cx, cy;
  1.1456 +  NS_ENSURE_SUCCESS(GetPositionAndSize(&x, &y, &cx, &cy), NS_ERROR_FAILURE);
  1.1457 +
  1.1458 +  int32_t sizeMode = mWindow->SizeMode();
  1.1459 +  CSSToLayoutDeviceScale scale = mWindow->GetDefaultScale();
  1.1460 +
  1.1461 +  // make our position relative to our parent, if any
  1.1462 +  nsCOMPtr<nsIBaseWindow> parent(do_QueryReferent(mParentWindow));
  1.1463 +  if (parent) {
  1.1464 +    int32_t parentX, parentY;
  1.1465 +    if (NS_SUCCEEDED(parent->GetPosition(&parentX, &parentY))) {
  1.1466 +      x -= parentX;
  1.1467 +      y -= parentY;
  1.1468 +    }
  1.1469 +  }
  1.1470 +
  1.1471 +  char                        sizeBuf[10];
  1.1472 +  nsAutoString                sizeString;
  1.1473 +  nsAutoString                windowElementId;
  1.1474 +  nsCOMPtr<nsIDOMXULDocument> ownerXULDoc;
  1.1475 +
  1.1476 +  // fetch docShellElement's ID and XUL owner document
  1.1477 +  ownerXULDoc = do_QueryInterface(docShellElement->OwnerDoc());
  1.1478 +  if (docShellElement->IsXUL()) {
  1.1479 +    docShellElement->GetId(windowElementId);
  1.1480 +  }
  1.1481 +
  1.1482 +  ErrorResult rv;
  1.1483 +  // (only for size elements which are persisted)
  1.1484 +  if ((mPersistentAttributesDirty & PAD_POSITION) &&
  1.1485 +      sizeMode == nsSizeMode_Normal) {
  1.1486 +    if (persistString.Find("screenX") >= 0) {
  1.1487 +      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(x / scale.scale));
  1.1488 +      sizeString.AssignWithConversion(sizeBuf);
  1.1489 +      docShellElement->SetAttribute(SCREENX_ATTRIBUTE, sizeString, rv);
  1.1490 +      if (ownerXULDoc) // force persistence in case the value didn't change
  1.1491 +        ownerXULDoc->Persist(windowElementId, SCREENX_ATTRIBUTE);
  1.1492 +    }
  1.1493 +    if (persistString.Find("screenY") >= 0) {
  1.1494 +      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(y / scale.scale));
  1.1495 +      sizeString.AssignWithConversion(sizeBuf);
  1.1496 +      docShellElement->SetAttribute(SCREENY_ATTRIBUTE, sizeString, rv);
  1.1497 +      if (ownerXULDoc)
  1.1498 +        ownerXULDoc->Persist(windowElementId, SCREENY_ATTRIBUTE);
  1.1499 +    }
  1.1500 +  }
  1.1501 +
  1.1502 +  if ((mPersistentAttributesDirty & PAD_SIZE) &&
  1.1503 +      sizeMode == nsSizeMode_Normal) {
  1.1504 +    if (persistString.Find("width") >= 0) {
  1.1505 +      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(cx / scale.scale));
  1.1506 +      sizeString.AssignWithConversion(sizeBuf);
  1.1507 +      docShellElement->SetAttribute(WIDTH_ATTRIBUTE, sizeString, rv);
  1.1508 +      if (ownerXULDoc)
  1.1509 +        ownerXULDoc->Persist(windowElementId, WIDTH_ATTRIBUTE);
  1.1510 +    }
  1.1511 +    if (persistString.Find("height") >= 0) {
  1.1512 +      PR_snprintf(sizeBuf, sizeof(sizeBuf), "%d", NSToIntRound(cy / scale.scale));
  1.1513 +      sizeString.AssignWithConversion(sizeBuf);
  1.1514 +      docShellElement->SetAttribute(HEIGHT_ATTRIBUTE, sizeString, rv);
  1.1515 +      if (ownerXULDoc)
  1.1516 +        ownerXULDoc->Persist(windowElementId, HEIGHT_ATTRIBUTE);
  1.1517 +    }
  1.1518 +  }
  1.1519 +
  1.1520 +  if (mPersistentAttributesDirty & PAD_MISC) {
  1.1521 +    if (sizeMode != nsSizeMode_Minimized) {
  1.1522 +      if (sizeMode == nsSizeMode_Maximized)
  1.1523 +        sizeString.Assign(SIZEMODE_MAXIMIZED);
  1.1524 +      else if (sizeMode == nsSizeMode_Fullscreen)
  1.1525 +        sizeString.Assign(SIZEMODE_FULLSCREEN);
  1.1526 +      else
  1.1527 +        sizeString.Assign(SIZEMODE_NORMAL);
  1.1528 +      docShellElement->SetAttribute(MODE_ATTRIBUTE, sizeString, rv);
  1.1529 +      if (ownerXULDoc && persistString.Find("sizemode") >= 0)
  1.1530 +        ownerXULDoc->Persist(windowElementId, MODE_ATTRIBUTE);
  1.1531 +    }
  1.1532 +    if (persistString.Find("zlevel") >= 0) {
  1.1533 +      uint32_t zLevel;
  1.1534 +      nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  1.1535 +      if (mediator) {
  1.1536 +        mediator->GetZLevel(this, &zLevel);
  1.1537 +        PR_snprintf(sizeBuf, sizeof(sizeBuf), "%lu", (unsigned long)zLevel);
  1.1538 +        sizeString.AssignWithConversion(sizeBuf);
  1.1539 +        docShellElement->SetAttribute(ZLEVEL_ATTRIBUTE, sizeString, rv);
  1.1540 +        ownerXULDoc->Persist(windowElementId, ZLEVEL_ATTRIBUTE);
  1.1541 +      }
  1.1542 +    }
  1.1543 +  }
  1.1544 +
  1.1545 +  mPersistentAttributesDirty = 0;
  1.1546 +  return NS_OK;
  1.1547 +}
  1.1548 +
  1.1549 +NS_IMETHODIMP nsXULWindow::GetWindowDOMWindow(nsIDOMWindow** aDOMWindow)
  1.1550 +{
  1.1551 +  NS_ENSURE_STATE(mDocShell);
  1.1552 +
  1.1553 +  if (!mDOMWindow)
  1.1554 +    mDOMWindow = do_GetInterface(mDocShell);
  1.1555 +  NS_ENSURE_TRUE(mDOMWindow, NS_ERROR_FAILURE);
  1.1556 +
  1.1557 +  *aDOMWindow = mDOMWindow;
  1.1558 +  NS_ADDREF(*aDOMWindow);
  1.1559 +  return NS_OK;
  1.1560 +}
  1.1561 +
  1.1562 +dom::Element*
  1.1563 +nsXULWindow::GetWindowDOMElement() const
  1.1564 +{
  1.1565 +  NS_ENSURE_TRUE(mDocShell, nullptr);
  1.1566 +
  1.1567 +  nsCOMPtr<nsIContentViewer> cv;
  1.1568 +  mDocShell->GetContentViewer(getter_AddRefs(cv));
  1.1569 +  NS_ENSURE_TRUE(cv, nullptr);
  1.1570 +
  1.1571 +  const nsIDocument* document = cv->GetDocument();
  1.1572 +  NS_ENSURE_TRUE(document, nullptr);
  1.1573 +
  1.1574 +  return document->GetRootElement();
  1.1575 +}
  1.1576 +
  1.1577 +nsresult nsXULWindow::ContentShellAdded(nsIDocShellTreeItem* aContentShell,
  1.1578 +   bool aPrimary, bool aTargetable, const nsAString& aID)
  1.1579 +{
  1.1580 +  nsContentShellInfo* shellInfo = nullptr;
  1.1581 +
  1.1582 +  uint32_t i, count = mContentShells.Length();
  1.1583 +  nsWeakPtr contentShellWeak = do_GetWeakReference(aContentShell);
  1.1584 +  for (i = 0; i < count; i++) {
  1.1585 +    nsContentShellInfo* info = mContentShells.ElementAt(i);
  1.1586 +    if (info->id.Equals(aID)) {
  1.1587 +      // We already exist. Do a replace.
  1.1588 +      info->child = contentShellWeak;
  1.1589 +      shellInfo = info;
  1.1590 +    }
  1.1591 +    else if (info->child == contentShellWeak)
  1.1592 +      info->child = nullptr;
  1.1593 +  }
  1.1594 +
  1.1595 +  if (!shellInfo) {
  1.1596 +    shellInfo = new nsContentShellInfo(aID, contentShellWeak);
  1.1597 +    mContentShells.AppendElement(shellInfo);
  1.1598 +  }
  1.1599 +    
  1.1600 +  // Set the default content tree owner
  1.1601 +  if (aPrimary) {
  1.1602 +    NS_ENSURE_SUCCESS(EnsurePrimaryContentTreeOwner(), NS_ERROR_FAILURE);
  1.1603 +    aContentShell->SetTreeOwner(mPrimaryContentTreeOwner);
  1.1604 +    mPrimaryContentShell = aContentShell;
  1.1605 +  }
  1.1606 +  else {
  1.1607 +    NS_ENSURE_SUCCESS(EnsureContentTreeOwner(), NS_ERROR_FAILURE);
  1.1608 +    aContentShell->SetTreeOwner(mContentTreeOwner);
  1.1609 +    if (mPrimaryContentShell == aContentShell)
  1.1610 +      mPrimaryContentShell = nullptr;
  1.1611 +  }
  1.1612 +
  1.1613 +  if (aTargetable) {
  1.1614 +#ifdef DEBUG
  1.1615 +    int32_t debugCount = mTargetableShells.Count();
  1.1616 +    int32_t debugCounter;
  1.1617 +    for (debugCounter = debugCount - 1; debugCounter >= 0; --debugCounter) {
  1.1618 +      nsCOMPtr<nsIDocShellTreeItem> curItem =
  1.1619 +        do_QueryReferent(mTargetableShells[debugCounter]);
  1.1620 +      NS_ASSERTION(!SameCOMIdentity(curItem, aContentShell),
  1.1621 +                   "Adding already existing item to mTargetableShells");
  1.1622 +    }
  1.1623 +#endif
  1.1624 +    
  1.1625 +    // put the new shell at the start of the targetable shells list if either
  1.1626 +    // it's the new primary shell or there is no existing primary shell (which
  1.1627 +    // means that chances are this one just stopped being primary).  If we
  1.1628 +    // really cared, we could keep track of the "last no longer primary shell"
  1.1629 +    // explicitly, but it probably doesn't matter enough: the difference would
  1.1630 +    // only be felt in a situation where all shells were non-primary, which
  1.1631 +    // doesn't happen much.  In a situation where there is one and only one
  1.1632 +    // primary shell, and in which shells get unmarked as primary before some
  1.1633 +    // other shell gets marked as primary, this effectively stores the list of
  1.1634 +    // targetable shells in "most recently primary first" order.
  1.1635 +    bool inserted;
  1.1636 +    if (aPrimary || !mPrimaryContentShell) {
  1.1637 +      inserted = mTargetableShells.InsertObjectAt(contentShellWeak, 0);
  1.1638 +    } else {
  1.1639 +      inserted = mTargetableShells.AppendObject(contentShellWeak);
  1.1640 +    }
  1.1641 +    NS_ENSURE_TRUE(inserted, NS_ERROR_OUT_OF_MEMORY);
  1.1642 +  }
  1.1643 +
  1.1644 +  return NS_OK;
  1.1645 +}
  1.1646 +
  1.1647 +nsresult nsXULWindow::ContentShellRemoved(nsIDocShellTreeItem* aContentShell)
  1.1648 +{
  1.1649 +  if (mPrimaryContentShell == aContentShell) {
  1.1650 +    mPrimaryContentShell = nullptr;
  1.1651 +  }
  1.1652 +
  1.1653 +  int32_t i, count = mContentShells.Length();
  1.1654 +  for (i = count - 1; i >= 0; --i) {
  1.1655 +    nsContentShellInfo* info = mContentShells.ElementAt(i);
  1.1656 +    nsCOMPtr<nsIDocShellTreeItem> curItem = do_QueryReferent(info->child);
  1.1657 +    if (!curItem || SameCOMIdentity(curItem, aContentShell)) {
  1.1658 +      mContentShells.RemoveElementAt(i);
  1.1659 +      delete info;
  1.1660 +    }
  1.1661 +  }
  1.1662 +
  1.1663 +  count = mTargetableShells.Count();
  1.1664 +  for (i = count - 1; i >= 0; --i) {
  1.1665 +    nsCOMPtr<nsIDocShellTreeItem> curItem =
  1.1666 +      do_QueryReferent(mTargetableShells[i]);
  1.1667 +    if (!curItem || SameCOMIdentity(curItem, aContentShell)) {
  1.1668 +      mTargetableShells.RemoveObjectAt(i);
  1.1669 +    }
  1.1670 +  }
  1.1671 +  
  1.1672 +  return NS_OK;
  1.1673 +}
  1.1674 +
  1.1675 +NS_IMETHODIMP nsXULWindow::SizeShellTo(nsIDocShellTreeItem* aShellItem,
  1.1676 +   int32_t aCX, int32_t aCY)
  1.1677 +{
  1.1678 +  // XXXTAB This is wrong, we should actually reflow based on the passed in
  1.1679 +  // shell.  For now we are hacking and doing delta sizing.  This is bad
  1.1680 +  // because it assumes all size we add will go to the shell which probably
  1.1681 +  // won't happen.
  1.1682 +
  1.1683 +  nsCOMPtr<nsIBaseWindow> shellAsWin(do_QueryInterface(aShellItem));
  1.1684 +  NS_ENSURE_TRUE(shellAsWin, NS_ERROR_FAILURE);
  1.1685 +
  1.1686 +  int32_t width = 0;
  1.1687 +  int32_t height = 0;
  1.1688 +  shellAsWin->GetSize(&width, &height);
  1.1689 +
  1.1690 +  int32_t widthDelta = aCX - width;
  1.1691 +  int32_t heightDelta = aCY - height;
  1.1692 +
  1.1693 +  if (widthDelta || heightDelta) {
  1.1694 +    int32_t winCX = 0;
  1.1695 +    int32_t winCY = 0;
  1.1696 +
  1.1697 +    GetSize(&winCX, &winCY);
  1.1698 +    // There's no point in trying to make the window smaller than the
  1.1699 +    // desired docshell size --- that's not likely to work. This whole
  1.1700 +    // function assumes that the outer docshell is adding some constant
  1.1701 +    // "border" chrome to aShellItem.
  1.1702 +    winCX = std::max(winCX + widthDelta, aCX);
  1.1703 +    winCY = std::max(winCY + heightDelta, aCY);
  1.1704 +    SetSize(winCX, winCY, true);
  1.1705 +  }
  1.1706 +
  1.1707 +  return NS_OK;
  1.1708 +}
  1.1709 +
  1.1710 +NS_IMETHODIMP nsXULWindow::ExitModalLoop(nsresult aStatus)
  1.1711 +{
  1.1712 +  if (mContinueModalLoop)
  1.1713 +    EnableParent(true);
  1.1714 +  mContinueModalLoop = false;
  1.1715 +  mModalStatus = aStatus;
  1.1716 +  return NS_OK;
  1.1717 +}
  1.1718 +
  1.1719 +// top-level function to create a new window
  1.1720 +NS_IMETHODIMP nsXULWindow::CreateNewWindow(int32_t aChromeFlags,
  1.1721 +                             nsIXULWindow **_retval)
  1.1722 +{
  1.1723 +  NS_ENSURE_ARG_POINTER(_retval);
  1.1724 +
  1.1725 +  if (aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
  1.1726 +    return CreateNewChromeWindow(aChromeFlags, _retval);
  1.1727 +  return CreateNewContentWindow(aChromeFlags, _retval);
  1.1728 +}
  1.1729 +
  1.1730 +NS_IMETHODIMP nsXULWindow::CreateNewChromeWindow(int32_t aChromeFlags,
  1.1731 +                                                 nsIXULWindow **_retval)
  1.1732 +{
  1.1733 +  nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
  1.1734 +  NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
  1.1735 +
  1.1736 +  // Just do a normal create of a window and return.
  1.1737 +
  1.1738 +  nsCOMPtr<nsIXULWindow> newWindow;
  1.1739 +  appShell->CreateTopLevelWindow(this, nullptr, aChromeFlags,
  1.1740 +                                 nsIAppShellService::SIZE_TO_CONTENT,
  1.1741 +                                 nsIAppShellService::SIZE_TO_CONTENT,
  1.1742 +                                 getter_AddRefs(newWindow));
  1.1743 +
  1.1744 +  NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
  1.1745 +
  1.1746 +  *_retval = newWindow;
  1.1747 +  NS_ADDREF(*_retval);
  1.1748 +
  1.1749 +  return NS_OK;
  1.1750 +}
  1.1751 +
  1.1752 +NS_IMETHODIMP nsXULWindow::CreateNewContentWindow(int32_t aChromeFlags,
  1.1753 +                                                  nsIXULWindow **_retval)
  1.1754 +{
  1.1755 +  nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
  1.1756 +  NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
  1.1757 +
  1.1758 +  // We need to create a new top level window and then enter a nested
  1.1759 +  // loop. Eventually the new window will be told that it has loaded,
  1.1760 +  // at which time we know it is safe to spin out of the nested loop
  1.1761 +  // and allow the opening code to proceed.
  1.1762 +
  1.1763 +  nsCOMPtr<nsIURI> uri;
  1.1764 +
  1.1765 +  nsAdoptingCString urlStr = Preferences::GetCString("browser.chromeURL");
  1.1766 +  if (urlStr.IsEmpty()) {
  1.1767 +    urlStr.AssignLiteral("chrome://navigator/content/navigator.xul");
  1.1768 +  }
  1.1769 +
  1.1770 +  nsCOMPtr<nsIIOService> service(do_GetService(NS_IOSERVICE_CONTRACTID));
  1.1771 +  if (service) {
  1.1772 +    service->NewURI(urlStr, nullptr, nullptr, getter_AddRefs(uri));
  1.1773 +  }
  1.1774 +  NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
  1.1775 +
  1.1776 +  // We need to create a chrome window to contain the content window we're about
  1.1777 +  // to pass back. The subject principal needs to be system while we're creating
  1.1778 +  // it to make things work right, so force a system caller. See bug 799348
  1.1779 +  // comment 13 for a description of what happens when we don't.
  1.1780 +  nsCOMPtr<nsIXULWindow> newWindow;
  1.1781 +  {
  1.1782 +    AutoNoJSAPI nojsapi;
  1.1783 +    appShell->CreateTopLevelWindow(this, uri,
  1.1784 +                                   aChromeFlags, 615, 480,
  1.1785 +                                   getter_AddRefs(newWindow));
  1.1786 +    NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
  1.1787 +  }
  1.1788 +
  1.1789 +  // Specify that we want the window to remain locked until the chrome has loaded.
  1.1790 +  nsXULWindow *xulWin = static_cast<nsXULWindow*>
  1.1791 +                                   (static_cast<nsIXULWindow*>
  1.1792 +                                               (newWindow));
  1.1793 +
  1.1794 +  xulWin->LockUntilChromeLoad();
  1.1795 +
  1.1796 +  {
  1.1797 +    AutoNoJSAPI nojsapi;
  1.1798 +    nsIThread *thread = NS_GetCurrentThread();
  1.1799 +    while (xulWin->IsLocked()) {
  1.1800 +      if (!NS_ProcessNextEvent(thread))
  1.1801 +        break;
  1.1802 +    }
  1.1803 + }
  1.1804 +
  1.1805 +  NS_ENSURE_STATE(xulWin->mPrimaryContentShell);
  1.1806 +
  1.1807 +  *_retval = newWindow;
  1.1808 +  NS_ADDREF(*_retval);
  1.1809 +
  1.1810 +  return NS_OK;
  1.1811 +}
  1.1812 +
  1.1813 +void nsXULWindow::EnableParent(bool aEnable)
  1.1814 +{
  1.1815 +  nsCOMPtr<nsIBaseWindow> parentWindow;
  1.1816 +  nsCOMPtr<nsIWidget>     parentWidget;
  1.1817 +
  1.1818 +  parentWindow = do_QueryReferent(mParentWindow);
  1.1819 +  if (parentWindow)
  1.1820 +    parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
  1.1821 +  if (parentWidget)
  1.1822 +    parentWidget->Enable(aEnable);
  1.1823 +}
  1.1824 +
  1.1825 +// Constrain the window to its proper z-level
  1.1826 +bool nsXULWindow::ConstrainToZLevel(bool        aImmediate,
  1.1827 +                                      nsWindowZ  *aPlacement,
  1.1828 +                                      nsIWidget  *aReqBelow,
  1.1829 +                                      nsIWidget **aActualBelow)
  1.1830 +{
  1.1831 +#if 0
  1.1832 +  /* Do we have a parent window? This means our z-order is already constrained,
  1.1833 +     since we're a dependent window. Our window list isn't hierarchical,
  1.1834 +     so we can't properly calculate placement for such a window.
  1.1835 +     Should we just abort? */
  1.1836 +  nsCOMPtr<nsIBaseWindow> parentWindow = do_QueryReferent(mParentWindow);
  1.1837 +  if (parentWindow)
  1.1838 +    return false;
  1.1839 +#endif
  1.1840 +
  1.1841 +  nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  1.1842 +  if (!mediator)
  1.1843 +    return false;
  1.1844 +
  1.1845 +  bool           altered;
  1.1846 +  uint32_t       position,
  1.1847 +                 newPosition,
  1.1848 +                 zLevel;
  1.1849 +  nsIXULWindow  *us = this;
  1.1850 +
  1.1851 +  altered = false;
  1.1852 +  mediator->GetZLevel(this, &zLevel);
  1.1853 +
  1.1854 +  // translate from WidgetGUIEvent to nsIWindowMediator constants
  1.1855 +  position = nsIWindowMediator::zLevelTop;
  1.1856 +  if (*aPlacement == nsWindowZBottom || zLevel == nsIXULWindow::lowestZ)
  1.1857 +    position = nsIWindowMediator::zLevelBottom;
  1.1858 +  else if (*aPlacement == nsWindowZRelative)
  1.1859 +    position = nsIWindowMediator::zLevelBelow;
  1.1860 +
  1.1861 +  if (NS_SUCCEEDED(mediator->CalculateZPosition(us, position, aReqBelow,
  1.1862 +                               &newPosition, aActualBelow, &altered))) {
  1.1863 +    /* If we were asked to move to the top but constrained to remain
  1.1864 +       below one of our other windows, first move all windows in that
  1.1865 +       window's layer and above to the top. This allows the user to
  1.1866 +       click a window which can't be topmost and still bring mozilla
  1.1867 +       to the foreground. */
  1.1868 +    if (altered &&
  1.1869 +        (position == nsIWindowMediator::zLevelTop ||
  1.1870 +         (position == nsIWindowMediator::zLevelBelow && aReqBelow == 0)))
  1.1871 +      PlaceWindowLayersBehind(zLevel + 1, nsIXULWindow::highestZ, 0);
  1.1872 +
  1.1873 +    if (*aPlacement != nsWindowZBottom &&
  1.1874 +        position == nsIWindowMediator::zLevelBottom)
  1.1875 +      altered = true;
  1.1876 +    if (altered || aImmediate) {
  1.1877 +      if (newPosition == nsIWindowMediator::zLevelTop)
  1.1878 +        *aPlacement = nsWindowZTop;
  1.1879 +      else if (newPosition == nsIWindowMediator::zLevelBottom)
  1.1880 +        *aPlacement = nsWindowZBottom;
  1.1881 +      else
  1.1882 +        *aPlacement = nsWindowZRelative;
  1.1883 +
  1.1884 +      if (aImmediate) {
  1.1885 +        nsCOMPtr<nsIBaseWindow> ourBase = do_QueryObject(this);
  1.1886 +        if (ourBase) {
  1.1887 +          nsCOMPtr<nsIWidget> ourWidget;
  1.1888 +          ourBase->GetMainWidget(getter_AddRefs(ourWidget));
  1.1889 +          ourWidget->PlaceBehind(*aPlacement == nsWindowZBottom ?
  1.1890 +                                   eZPlacementBottom : eZPlacementBelow,
  1.1891 +                                 *aActualBelow, false);
  1.1892 +        }
  1.1893 +      }
  1.1894 +    }
  1.1895 +
  1.1896 +    /* CalculateZPosition can tell us to be below nothing, because it tries
  1.1897 +       not to change something it doesn't recognize. A request to verify
  1.1898 +       being below an unrecognized window, then, is treated as a request
  1.1899 +       to come to the top (below null) */
  1.1900 +    nsCOMPtr<nsIXULWindow> windowAbove;
  1.1901 +    if (newPosition == nsIWindowMediator::zLevelBelow && *aActualBelow) {
  1.1902 +      windowAbove = (*aActualBelow)->GetWidgetListener()->GetXULWindow();
  1.1903 +    }
  1.1904 +
  1.1905 +    mediator->SetZPosition(us, newPosition, windowAbove);
  1.1906 +  }
  1.1907 +
  1.1908 +  return altered;
  1.1909 +}
  1.1910 +
  1.1911 +/* Re-z-position all windows in the layers from aLowLevel to aHighLevel,
  1.1912 +   inclusive, to be behind aBehind. aBehind of null means on top.
  1.1913 +   Note this method actually does nothing to our relative window positions.
  1.1914 +   (And therefore there's no need to inform WindowMediator we're moving
  1.1915 +   things, because we aren't.) This method is useful for, say, moving
  1.1916 +   a range of layers of our own windows relative to windows belonging to
  1.1917 +   external applications.
  1.1918 +*/
  1.1919 +void nsXULWindow::PlaceWindowLayersBehind(uint32_t aLowLevel,
  1.1920 +                                          uint32_t aHighLevel,
  1.1921 +                                          nsIXULWindow *aBehind)
  1.1922 +{
  1.1923 +  // step through windows in z-order from top to bottommost window
  1.1924 +
  1.1925 +  nsCOMPtr<nsIWindowMediator> mediator(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
  1.1926 +  if (!mediator)
  1.1927 +    return;
  1.1928 +
  1.1929 +  nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
  1.1930 +  mediator->GetZOrderXULWindowEnumerator(0, true,
  1.1931 +              getter_AddRefs(windowEnumerator));
  1.1932 +  if (!windowEnumerator)
  1.1933 +    return;
  1.1934 +
  1.1935 +  // each window will be moved behind previousHighWidget, itself
  1.1936 +  // a moving target. initialize it.
  1.1937 +  nsCOMPtr<nsIWidget> previousHighWidget;
  1.1938 +  if (aBehind) {
  1.1939 +    nsCOMPtr<nsIBaseWindow> highBase(do_QueryInterface(aBehind));
  1.1940 +    if (highBase)
  1.1941 +      highBase->GetMainWidget(getter_AddRefs(previousHighWidget));
  1.1942 +  }
  1.1943 +
  1.1944 +  // get next lower window
  1.1945 +  bool more;
  1.1946 +  while (windowEnumerator->HasMoreElements(&more), more) {
  1.1947 +    uint32_t nextZ; // z-level of nextWindow
  1.1948 +    nsCOMPtr<nsISupports> nextWindow;
  1.1949 +    windowEnumerator->GetNext(getter_AddRefs(nextWindow));
  1.1950 +    nsCOMPtr<nsIXULWindow> nextXULWindow(do_QueryInterface(nextWindow));
  1.1951 +    nextXULWindow->GetZLevel(&nextZ);
  1.1952 +    if (nextZ < aLowLevel)
  1.1953 +      break; // we've processed all windows through aLowLevel
  1.1954 +    
  1.1955 +    // move it just below its next higher window
  1.1956 +    nsCOMPtr<nsIBaseWindow> nextBase(do_QueryInterface(nextXULWindow));
  1.1957 +    if (nextBase) {
  1.1958 +      nsCOMPtr<nsIWidget> nextWidget;
  1.1959 +      nextBase->GetMainWidget(getter_AddRefs(nextWidget));
  1.1960 +      if (nextZ <= aHighLevel)
  1.1961 +        nextWidget->PlaceBehind(eZPlacementBelow, previousHighWidget, false);
  1.1962 +      previousHighWidget = nextWidget;
  1.1963 +    }
  1.1964 +  }
  1.1965 +}
  1.1966 +
  1.1967 +void nsXULWindow::SetContentScrollbarVisibility(bool aVisible)
  1.1968 +{
  1.1969 +  nsCOMPtr<nsPIDOMWindow> contentWin(do_GetInterface(mPrimaryContentShell));
  1.1970 +  if (contentWin) {
  1.1971 +    mozilla::ErrorResult rv;
  1.1972 +    nsRefPtr<nsGlobalWindow> window = static_cast<nsGlobalWindow*>(contentWin.get());
  1.1973 +    nsRefPtr<mozilla::dom::BarProp> scrollbars = window->GetScrollbars(rv);
  1.1974 +    if (scrollbars) {
  1.1975 +      scrollbars->SetVisible(aVisible, rv);
  1.1976 +    }
  1.1977 +  }
  1.1978 +}
  1.1979 +
  1.1980 +bool nsXULWindow::GetContentScrollbarVisibility()
  1.1981 +{
  1.1982 +  // This code already exists in dom/src/base/nsBarProp.cpp, but we
  1.1983 +  // can't safely get to that from here as this function is called
  1.1984 +  // while the DOM window is being set up, and we need the DOM window
  1.1985 +  // to get to that code.
  1.1986 +  nsCOMPtr<nsIScrollable> scroller(do_QueryInterface(mPrimaryContentShell));
  1.1987 +
  1.1988 +  if (scroller) {
  1.1989 +    int32_t prefValue;
  1.1990 +    scroller->GetDefaultScrollbarPreferences(
  1.1991 +                  nsIScrollable::ScrollOrientation_Y, &prefValue);
  1.1992 +    if (prefValue == nsIScrollable::Scrollbar_Never) // try the other way
  1.1993 +      scroller->GetDefaultScrollbarPreferences(
  1.1994 +                  nsIScrollable::ScrollOrientation_X, &prefValue);
  1.1995 +
  1.1996 +    if (prefValue == nsIScrollable::Scrollbar_Never)
  1.1997 +      return false;
  1.1998 +  }
  1.1999 +
  1.2000 +  return true;
  1.2001 +}
  1.2002 +
  1.2003 +// during spinup, attributes that haven't been loaded yet can't be dirty
  1.2004 +void nsXULWindow::PersistentAttributesDirty(uint32_t aDirtyFlags)
  1.2005 +{
  1.2006 +  mPersistentAttributesDirty |= aDirtyFlags & mPersistentAttributesMask;
  1.2007 +}
  1.2008 +
  1.2009 +NS_IMETHODIMP nsXULWindow::ApplyChromeFlags()
  1.2010 +{
  1.2011 +  nsCOMPtr<dom::Element> window = GetWindowDOMElement();
  1.2012 +  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
  1.2013 +
  1.2014 +  if (mChromeLoaded) {
  1.2015 +    // The two calls in this block don't need to happen early because they
  1.2016 +    // don't cause a global restyle on the document.  Not only that, but the
  1.2017 +    // scrollbar stuff needs a content area to toggle the scrollbars on anyway.
  1.2018 +    // So just don't do these until mChromeLoaded is true.
  1.2019 +
  1.2020 +    // Scrollbars have their own special treatment.
  1.2021 +    SetContentScrollbarVisibility(mChromeFlags &
  1.2022 +                                  nsIWebBrowserChrome::CHROME_SCROLLBARS ?
  1.2023 +                                    true : false);
  1.2024 +  }
  1.2025 +
  1.2026 +  /* the other flags are handled together. we have style rules
  1.2027 +     in navigator.css that trigger visibility based on
  1.2028 +     the 'chromehidden' attribute of the <window> tag. */
  1.2029 +  nsAutoString newvalue;
  1.2030 +
  1.2031 +  if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR))
  1.2032 +    newvalue.AppendLiteral("menubar ");
  1.2033 +
  1.2034 +  if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_TOOLBAR))
  1.2035 +    newvalue.AppendLiteral("toolbar ");
  1.2036 +
  1.2037 +  if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_LOCATIONBAR))
  1.2038 +    newvalue.AppendLiteral("location ");
  1.2039 +
  1.2040 +  if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR))
  1.2041 +    newvalue.AppendLiteral("directories ");
  1.2042 +
  1.2043 +  if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_STATUSBAR))
  1.2044 +    newvalue.AppendLiteral("status ");
  1.2045 +
  1.2046 +  if (! (mChromeFlags & nsIWebBrowserChrome::CHROME_EXTRA))
  1.2047 +    newvalue.AppendLiteral("extrachrome ");
  1.2048 +
  1.2049 +  // Note that if we're not actually changing the value this will be a no-op,
  1.2050 +  // so no need to compare to the old value.
  1.2051 +  ErrorResult rv;
  1.2052 +  window->SetAttribute(NS_LITERAL_STRING("chromehidden"), newvalue, rv);
  1.2053 +
  1.2054 +  return NS_OK;
  1.2055 +}
  1.2056 +
  1.2057 +NS_IMETHODIMP nsXULWindow::GetXULBrowserWindow(nsIXULBrowserWindow * *aXULBrowserWindow)
  1.2058 +{
  1.2059 +  NS_IF_ADDREF(*aXULBrowserWindow = mXULBrowserWindow);
  1.2060 +  return NS_OK;
  1.2061 +}
  1.2062 +
  1.2063 +NS_IMETHODIMP nsXULWindow::SetXULBrowserWindow(nsIXULBrowserWindow * aXULBrowserWindow)
  1.2064 +{
  1.2065 +  mXULBrowserWindow = aXULBrowserWindow;
  1.2066 +  return NS_OK;
  1.2067 +}
  1.2068 +
  1.2069 +//*****************************************************************************
  1.2070 +//*** nsContentShellInfo: Object Management
  1.2071 +//*****************************************************************************   
  1.2072 +
  1.2073 +nsContentShellInfo::nsContentShellInfo(const nsAString& aID,
  1.2074 +                                       nsIWeakReference* aContentShell)
  1.2075 +  : id(aID),
  1.2076 +    child(aContentShell)
  1.2077 +{
  1.2078 +  MOZ_COUNT_CTOR(nsContentShellInfo);
  1.2079 +}
  1.2080 +
  1.2081 +nsContentShellInfo::~nsContentShellInfo()
  1.2082 +{
  1.2083 +  MOZ_COUNT_DTOR(nsContentShellInfo);
  1.2084 +   //XXX Set Tree Owner to null if the tree owner is nsXULWindow->mContentTreeOwner
  1.2085 +} 

mercurial