xpfe/appshell/src/nsAppShellService.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/xpfe/appshell/src/nsAppShellService.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,893 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +
    1.10 +#include "nsIAppShellService.h"
    1.11 +#include "nsIComponentManager.h"
    1.12 +#include "nsIURL.h"
    1.13 +#include "nsNetUtil.h"
    1.14 +#include "nsIServiceManager.h"
    1.15 +#include "nsIObserverService.h"
    1.16 +#include "nsIObserver.h"
    1.17 +#include "nsIXPConnect.h"
    1.18 +
    1.19 +#include "nsIWindowMediator.h"
    1.20 +#include "nsIWindowWatcher.h"
    1.21 +#include "nsPIWindowWatcher.h"
    1.22 +#include "nsIDOMWindow.h"
    1.23 +#include "nsPIDOMWindow.h"
    1.24 +#include "nsWebShellWindow.h"
    1.25 +
    1.26 +#include "nsCRT.h"
    1.27 +#include "prprf.h"
    1.28 +
    1.29 +#include "nsWidgetInitData.h"
    1.30 +#include "nsWidgetsCID.h"
    1.31 +#include "nsIWidget.h"
    1.32 +#include "nsIRequestObserver.h"
    1.33 +
    1.34 +/* For implementing GetHiddenWindowAndJSContext */
    1.35 +#include "nsIScriptGlobalObject.h"
    1.36 +#include "nsIScriptContext.h"
    1.37 +
    1.38 +#include "nsAppShellService.h"
    1.39 +#include "nsISupportsPrimitives.h"
    1.40 +#include "nsIChromeRegistry.h"
    1.41 +#include "nsILoadContext.h"
    1.42 +#include "nsIWebNavigation.h"
    1.43 +
    1.44 +#include "mozilla/Attributes.h"
    1.45 +#include "mozilla/Preferences.h"
    1.46 +#include "mozilla/StartupTimeline.h"
    1.47 +
    1.48 +#include "nsEmbedCID.h"
    1.49 +#include "nsIWebBrowser.h"
    1.50 +#include "nsIDocShell.h"
    1.51 +
    1.52 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP
    1.53 +#include "EventTracer.h"
    1.54 +#endif
    1.55 +
    1.56 +using namespace mozilla;
    1.57 +
    1.58 +// Default URL for the hidden window, can be overridden by a pref on Mac
    1.59 +#define DEFAULT_HIDDENWINDOW_URL "resource://gre-resources/hiddenWindow.html"
    1.60 +
    1.61 +class nsIAppShell;
    1.62 +
    1.63 +nsAppShellService::nsAppShellService() : 
    1.64 +  mXPCOMWillShutDown(false),
    1.65 +  mXPCOMShuttingDown(false),
    1.66 +  mModalWindowCount(0),
    1.67 +  mApplicationProvidedHiddenWindow(false)
    1.68 +{
    1.69 +  nsCOMPtr<nsIObserverService> obs
    1.70 +    (do_GetService("@mozilla.org/observer-service;1"));
    1.71 +
    1.72 +  if (obs) {
    1.73 +    obs->AddObserver(this, "xpcom-will-shutdown", false);
    1.74 +    obs->AddObserver(this, "xpcom-shutdown", false);
    1.75 +  }
    1.76 +}
    1.77 +
    1.78 +nsAppShellService::~nsAppShellService()
    1.79 +{
    1.80 +}
    1.81 +
    1.82 +
    1.83 +/*
    1.84 + * Implement the nsISupports methods...
    1.85 + */
    1.86 +NS_IMPL_ISUPPORTS(nsAppShellService,
    1.87 +                  nsIAppShellService,
    1.88 +                  nsIObserver)
    1.89 +
    1.90 +NS_IMETHODIMP
    1.91 +nsAppShellService::CreateHiddenWindow()
    1.92 +{
    1.93 +  return CreateHiddenWindowHelper(false);
    1.94 +}
    1.95 +
    1.96 +void
    1.97 +nsAppShellService::EnsurePrivateHiddenWindow()
    1.98 +{
    1.99 +  if (!mHiddenPrivateWindow) {
   1.100 +    CreateHiddenWindowHelper(true);
   1.101 +  }
   1.102 +}
   1.103 +
   1.104 +nsresult
   1.105 +nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate)
   1.106 +{
   1.107 +  nsresult rv;
   1.108 +  int32_t initialHeight = 100, initialWidth = 100;
   1.109 +
   1.110 +#ifdef XP_MACOSX
   1.111 +  uint32_t    chromeMask = 0;
   1.112 +  nsAdoptingCString prefVal =
   1.113 +      Preferences::GetCString("browser.hiddenWindowChromeURL");
   1.114 +  const char* hiddenWindowURL = prefVal.get() ? prefVal.get() : DEFAULT_HIDDENWINDOW_URL;
   1.115 +  if (aIsPrivate) {
   1.116 +    hiddenWindowURL = DEFAULT_HIDDENWINDOW_URL;
   1.117 +  } else {
   1.118 +    mApplicationProvidedHiddenWindow = prefVal.get() ? true : false;
   1.119 +  }
   1.120 +#else
   1.121 +  static const char hiddenWindowURL[] = DEFAULT_HIDDENWINDOW_URL;
   1.122 +  uint32_t    chromeMask =  nsIWebBrowserChrome::CHROME_ALL;
   1.123 +#endif
   1.124 +
   1.125 +  nsCOMPtr<nsIURI> url;
   1.126 +  rv = NS_NewURI(getter_AddRefs(url), hiddenWindowURL);
   1.127 +  NS_ENSURE_SUCCESS(rv, rv);
   1.128 +
   1.129 +  nsRefPtr<nsWebShellWindow> newWindow;
   1.130 +  if (!aIsPrivate) {
   1.131 +    rv = JustCreateTopWindow(nullptr, url,
   1.132 +                             chromeMask, initialWidth, initialHeight,
   1.133 +                             true, getter_AddRefs(newWindow));
   1.134 +    NS_ENSURE_SUCCESS(rv, rv);
   1.135 +
   1.136 +    mHiddenWindow.swap(newWindow);
   1.137 +  } else {
   1.138 +    // Create the hidden private window
   1.139 +    chromeMask |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
   1.140 +
   1.141 +    rv = JustCreateTopWindow(nullptr, url,
   1.142 +                             chromeMask, initialWidth, initialHeight,
   1.143 +                             true, getter_AddRefs(newWindow));
   1.144 +    NS_ENSURE_SUCCESS(rv, rv);
   1.145 +
   1.146 +    nsCOMPtr<nsIDocShell> docShell;
   1.147 +    newWindow->GetDocShell(getter_AddRefs(docShell));
   1.148 +    if (docShell) {
   1.149 +      docShell->SetAffectPrivateSessionLifetime(false);
   1.150 +    }
   1.151 +
   1.152 +    mHiddenPrivateWindow.swap(newWindow);
   1.153 +  }
   1.154 +
   1.155 +  // RegisterTopLevelWindow(newWindow); -- Mac only
   1.156 +
   1.157 +  return NS_OK;
   1.158 +}
   1.159 +
   1.160 +NS_IMETHODIMP
   1.161 +nsAppShellService::DestroyHiddenWindow()
   1.162 +{
   1.163 +  if (mHiddenWindow) {
   1.164 +    mHiddenWindow->Destroy();
   1.165 +
   1.166 +    mHiddenWindow = nullptr;
   1.167 +  }
   1.168 +
   1.169 +  if (mHiddenPrivateWindow) {
   1.170 +    mHiddenPrivateWindow->Destroy();
   1.171 +
   1.172 +    mHiddenPrivateWindow = nullptr;
   1.173 +  }
   1.174 +
   1.175 +  return NS_OK;
   1.176 +}
   1.177 +
   1.178 +/*
   1.179 + * Create a new top level window and display the given URL within it...
   1.180 + */
   1.181 +NS_IMETHODIMP
   1.182 +nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
   1.183 +                                        nsIURI *aUrl, 
   1.184 +                                        uint32_t aChromeMask,
   1.185 +                                        int32_t aInitialWidth,
   1.186 +                                        int32_t aInitialHeight,
   1.187 +                                        nsIXULWindow **aResult)
   1.188 +
   1.189 +{
   1.190 +  nsresult rv;
   1.191 +
   1.192 +  StartupTimeline::RecordOnce(StartupTimeline::CREATE_TOP_LEVEL_WINDOW);
   1.193 +
   1.194 +  nsWebShellWindow *newWindow = nullptr;
   1.195 +  rv = JustCreateTopWindow(aParent, aUrl,
   1.196 +                           aChromeMask, aInitialWidth, aInitialHeight,
   1.197 +                           false, &newWindow);  // addrefs
   1.198 +
   1.199 +  *aResult = newWindow; // transfer ref
   1.200 +
   1.201 +  if (NS_SUCCEEDED(rv)) {
   1.202 +    // the addref resulting from this is the owning addref for this window
   1.203 +    RegisterTopLevelWindow(*aResult);
   1.204 +    nsCOMPtr<nsIXULWindow> parent;
   1.205 +    if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
   1.206 +      parent = aParent;
   1.207 +    (*aResult)->SetZLevel(CalculateWindowZLevel(parent, aChromeMask));
   1.208 +  }
   1.209 +
   1.210 +  return rv;
   1.211 +}
   1.212 +
   1.213 +/*
   1.214 + * This class provides a stub implementation of nsIWebBrowserChrome2, as needed
   1.215 + * by nsAppShellService::CreateWindowlessBrowser
   1.216 + */
   1.217 +class WebBrowserChrome2Stub : public nsIWebBrowserChrome2,
   1.218 +                              public nsIInterfaceRequestor,
   1.219 +                              public nsSupportsWeakReference {
   1.220 +public:
   1.221 +    virtual ~WebBrowserChrome2Stub() {}
   1.222 +    NS_DECL_ISUPPORTS
   1.223 +    NS_DECL_NSIWEBBROWSERCHROME
   1.224 +    NS_DECL_NSIWEBBROWSERCHROME2
   1.225 +    NS_DECL_NSIINTERFACEREQUESTOR
   1.226 +};
   1.227 +
   1.228 +NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub)
   1.229 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
   1.230 +  NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
   1.231 +  NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
   1.232 +  NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   1.233 +  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   1.234 +NS_INTERFACE_MAP_END
   1.235 +
   1.236 +NS_IMPL_ADDREF(WebBrowserChrome2Stub)
   1.237 +NS_IMPL_RELEASE(WebBrowserChrome2Stub)
   1.238 +
   1.239 +NS_IMETHODIMP
   1.240 +WebBrowserChrome2Stub::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
   1.241 +{
   1.242 +  return NS_OK;
   1.243 +}
   1.244 +
   1.245 +NS_IMETHODIMP
   1.246 +WebBrowserChrome2Stub::GetWebBrowser(nsIWebBrowser** aWebBrowser)
   1.247 +{
   1.248 +  NS_NOTREACHED("WebBrowserChrome2Stub::GetWebBrowser is not supported");
   1.249 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.250 +}
   1.251 +
   1.252 +NS_IMETHODIMP
   1.253 +WebBrowserChrome2Stub::SetWebBrowser(nsIWebBrowser* aWebBrowser)
   1.254 +{
   1.255 +  NS_NOTREACHED("WebBrowserChrome2Stub::SetWebBrowser is not supported");
   1.256 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.257 +}
   1.258 +
   1.259 +NS_IMETHODIMP
   1.260 +WebBrowserChrome2Stub::GetChromeFlags(uint32_t* aChromeFlags)
   1.261 +{
   1.262 +  *aChromeFlags = 0;
   1.263 +  return NS_OK;
   1.264 +}
   1.265 +
   1.266 +NS_IMETHODIMP
   1.267 +WebBrowserChrome2Stub::SetChromeFlags(uint32_t aChromeFlags)
   1.268 +{
   1.269 +  NS_NOTREACHED("WebBrowserChrome2Stub::SetChromeFlags is not supported");
   1.270 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.271 +}
   1.272 +
   1.273 +NS_IMETHODIMP
   1.274 +WebBrowserChrome2Stub::DestroyBrowserWindow()
   1.275 +{
   1.276 +  NS_NOTREACHED("WebBrowserChrome2Stub::DestroyBrowserWindow is not supported");
   1.277 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.278 +}
   1.279 +
   1.280 +NS_IMETHODIMP
   1.281 +WebBrowserChrome2Stub::SizeBrowserTo(int32_t aCX, int32_t aCY)
   1.282 +{
   1.283 +  NS_NOTREACHED("WebBrowserChrome2Stub::SizeBrowserTo is not supported");
   1.284 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.285 +}
   1.286 +
   1.287 +NS_IMETHODIMP
   1.288 +WebBrowserChrome2Stub::ShowAsModal()
   1.289 +{
   1.290 +  NS_NOTREACHED("WebBrowserChrome2Stub::ShowAsModal is not supported");
   1.291 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.292 +}
   1.293 +
   1.294 +NS_IMETHODIMP
   1.295 +WebBrowserChrome2Stub::IsWindowModal(bool* aResult)
   1.296 +{
   1.297 +  *aResult = false;
   1.298 +  return NS_OK;
   1.299 +}
   1.300 +
   1.301 +NS_IMETHODIMP
   1.302 +WebBrowserChrome2Stub::ExitModalEventLoop(nsresult aStatus)
   1.303 +{
   1.304 +  NS_NOTREACHED("WebBrowserChrome2Stub::ExitModalEventLoop is not supported");
   1.305 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.306 +}
   1.307 +
   1.308 +NS_IMETHODIMP
   1.309 +WebBrowserChrome2Stub::SetStatusWithContext(uint32_t aStatusType,
   1.310 +                                            const nsAString& aStatusText,
   1.311 +                                            nsISupports* aStatusContext)
   1.312 +{
   1.313 +  return NS_OK;
   1.314 +}
   1.315 +
   1.316 +NS_IMETHODIMP
   1.317 +WebBrowserChrome2Stub::GetInterface(const nsIID & aIID, void **aSink)
   1.318 +{
   1.319 +    return QueryInterface(aIID, aSink);
   1.320 +}
   1.321 +
   1.322 +// This is the "stub" we return from CreateWindowlessBrowser - it exists
   1.323 +// purely to keep a strong reference to the browser and the container to
   1.324 +// prevent the container being collected while the stub remains alive.
   1.325 +class WindowlessBrowserStub MOZ_FINAL : public nsIWebNavigation,
   1.326 +                                        public nsIInterfaceRequestor {
   1.327 +public:
   1.328 +  WindowlessBrowserStub(nsIWebBrowser *aBrowser, nsISupports *aContainer) {
   1.329 +    mBrowser = aBrowser;
   1.330 +    mWebNavigation = do_QueryInterface(aBrowser);
   1.331 +    mInterfaceRequestor = do_QueryInterface(aBrowser);
   1.332 +    mContainer = aContainer;
   1.333 +  }
   1.334 +  NS_DECL_ISUPPORTS
   1.335 +  NS_FORWARD_NSIWEBNAVIGATION(mWebNavigation->)
   1.336 +  NS_FORWARD_NSIINTERFACEREQUESTOR(mInterfaceRequestor->)
   1.337 +private:
   1.338 +  nsCOMPtr<nsIWebBrowser> mBrowser;
   1.339 +  nsCOMPtr<nsIWebNavigation> mWebNavigation;
   1.340 +  nsCOMPtr<nsIInterfaceRequestor> mInterfaceRequestor;
   1.341 +  // we don't use the container but just hold a reference to it.
   1.342 +  nsCOMPtr<nsISupports> mContainer;
   1.343 +};
   1.344 +
   1.345 +NS_INTERFACE_MAP_BEGIN(WindowlessBrowserStub)
   1.346 +  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebNavigation)
   1.347 +  NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
   1.348 +  NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   1.349 +NS_INTERFACE_MAP_END
   1.350 +
   1.351 +NS_IMPL_ADDREF(WindowlessBrowserStub)
   1.352 +NS_IMPL_RELEASE(WindowlessBrowserStub)
   1.353 +
   1.354 +
   1.355 +NS_IMETHODIMP
   1.356 +nsAppShellService::CreateWindowlessBrowser(bool aIsChrome, nsIWebNavigation **aResult)
   1.357 +{
   1.358 +  /* First, we create an instance of nsWebBrowser. Instances of this class have
   1.359 +   * an associated doc shell, which is what we're interested in.
   1.360 +   */
   1.361 +  nsCOMPtr<nsIWebBrowser> browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
   1.362 +  if (!browser) {
   1.363 +    NS_ERROR("Couldn't create instance of nsWebBrowser!");
   1.364 +    return NS_ERROR_FAILURE;
   1.365 +  }
   1.366 +
   1.367 +  /* Next, we set the container window for our instance of nsWebBrowser. Since
   1.368 +   * we don't actually have a window, we instead set the container window to be
   1.369 +   * an instance of WebBrowserChrome2Stub, which provides a stub implementation
   1.370 +   * of nsIWebBrowserChrome2.
   1.371 +   */
   1.372 +  nsRefPtr<WebBrowserChrome2Stub> stub = new WebBrowserChrome2Stub();
   1.373 +  if (!stub) {
   1.374 +    NS_ERROR("Couldn't create instance of WebBrowserChrome2Stub!");
   1.375 +    return NS_ERROR_FAILURE;
   1.376 +  }
   1.377 +  browser->SetContainerWindow(stub);
   1.378 +
   1.379 +  nsCOMPtr<nsIWebNavigation> navigation = do_QueryInterface(browser);
   1.380 +
   1.381 +  nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(navigation);
   1.382 +  item->SetItemType(aIsChrome ? nsIDocShellTreeItem::typeChromeWrapper
   1.383 +                              : nsIDocShellTreeItem::typeContentWrapper);
   1.384 +
   1.385 +  /* A windowless web browser doesn't have an associated OS level window. To
   1.386 +   * accomplish this, we initialize the window associated with our instance of
   1.387 +   * nsWebBrowser with an instance of PuppetWidget, which provides a stub
   1.388 +   * implementation of nsIWidget.
   1.389 +   */
   1.390 +  nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(nullptr);
   1.391 +  if (!widget) {
   1.392 +    NS_ERROR("Couldn't create instance of PuppetWidget");
   1.393 +    return NS_ERROR_FAILURE;
   1.394 +  }
   1.395 +  widget->Create(nullptr, 0, nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
   1.396 +                 nullptr, nullptr);
   1.397 +  nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(navigation);
   1.398 +  window->InitWindow(0, widget, 0, 0, 0, 0);
   1.399 +  window->Create();
   1.400 +
   1.401 +  nsISupports *isstub = NS_ISUPPORTS_CAST(nsIWebBrowserChrome2*, stub);
   1.402 +  nsRefPtr<nsIWebNavigation> result = new WindowlessBrowserStub(browser, isstub);
   1.403 +  nsCOMPtr<nsIDocShell> docshell = do_GetInterface(result);
   1.404 +  docshell->SetInvisible(true);
   1.405 +
   1.406 +  result.forget(aResult);
   1.407 +  return NS_OK;
   1.408 +}
   1.409 +
   1.410 +uint32_t
   1.411 +nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
   1.412 +                                         uint32_t      aChromeMask)
   1.413 +{
   1.414 +  uint32_t zLevel;
   1.415 +
   1.416 +  zLevel = nsIXULWindow::normalZ;
   1.417 +  if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RAISED)
   1.418 +    zLevel = nsIXULWindow::raisedZ;
   1.419 +  else if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_LOWERED)
   1.420 +    zLevel = nsIXULWindow::loweredZ;
   1.421 +
   1.422 +#ifdef XP_MACOSX
   1.423 +  /* Platforms on which modal windows are always application-modal, not
   1.424 +     window-modal (that's just the Mac, right?) want modal windows to
   1.425 +     be stacked on top of everyone else.
   1.426 +
   1.427 +     On Mac OS X, bind modality to parent window instead of app (ala Mac OS 9)
   1.428 +  */
   1.429 +  uint32_t modalDepMask = nsIWebBrowserChrome::CHROME_MODAL |
   1.430 +                          nsIWebBrowserChrome::CHROME_DEPENDENT;
   1.431 +  if (aParent && (aChromeMask & modalDepMask)) {
   1.432 +    aParent->GetZLevel(&zLevel);
   1.433 +  }
   1.434 +#else
   1.435 +  /* Platforms with native support for dependent windows (that's everyone
   1.436 +      but pre-Mac OS X, right?) know how to stack dependent windows. On these
   1.437 +      platforms, give the dependent window the same level as its parent,
   1.438 +      so we won't try to override the normal platform behaviour. */
   1.439 +  if ((aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT) && aParent)
   1.440 +    aParent->GetZLevel(&zLevel);
   1.441 +#endif
   1.442 +
   1.443 +  return zLevel;
   1.444 +}
   1.445 +
   1.446 +#ifdef XP_WIN
   1.447 +/*
   1.448 + * Checks to see if any existing window is currently in fullscreen mode.
   1.449 + */
   1.450 +static bool
   1.451 +CheckForFullscreenWindow()
   1.452 +{
   1.453 +  nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
   1.454 +  if (!wm)
   1.455 +    return false;
   1.456 +
   1.457 +  nsCOMPtr<nsISimpleEnumerator> windowList;
   1.458 +  wm->GetXULWindowEnumerator(nullptr, getter_AddRefs(windowList));
   1.459 +  if (!windowList)
   1.460 +    return false;
   1.461 +
   1.462 +  for (;;) {
   1.463 +    bool more = false;
   1.464 +    windowList->HasMoreElements(&more);
   1.465 +    if (!more)
   1.466 +      return false;
   1.467 +
   1.468 +    nsCOMPtr<nsISupports> supportsWindow;
   1.469 +    windowList->GetNext(getter_AddRefs(supportsWindow));
   1.470 +    nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(supportsWindow));
   1.471 +    if (baseWin) {
   1.472 +      nsCOMPtr<nsIWidget> widget;
   1.473 +      baseWin->GetMainWidget(getter_AddRefs(widget));
   1.474 +      if (widget && widget->SizeMode() == nsSizeMode_Fullscreen) {
   1.475 +        return true;
   1.476 +      }
   1.477 +    }
   1.478 +  }
   1.479 +  return false;
   1.480 +}
   1.481 +#endif
   1.482 +
   1.483 +/*
   1.484 + * Just do the window-making part of CreateTopLevelWindow
   1.485 + */
   1.486 +nsresult
   1.487 +nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
   1.488 +                                       nsIURI *aUrl, 
   1.489 +                                       uint32_t aChromeMask,
   1.490 +                                       int32_t aInitialWidth,
   1.491 +                                       int32_t aInitialHeight,
   1.492 +                                       bool aIsHiddenWindow,
   1.493 +                                       nsWebShellWindow **aResult)
   1.494 +{
   1.495 +  *aResult = nullptr;
   1.496 +  NS_ENSURE_STATE(!mXPCOMWillShutDown);
   1.497 +
   1.498 +  nsCOMPtr<nsIXULWindow> parent;
   1.499 +  if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
   1.500 +    parent = aParent;
   1.501 +
   1.502 +  nsRefPtr<nsWebShellWindow> window = new nsWebShellWindow(aChromeMask);
   1.503 +  NS_ENSURE_TRUE(window, NS_ERROR_OUT_OF_MEMORY);
   1.504 +
   1.505 +#ifdef XP_WIN
   1.506 +  // If the parent is currently fullscreen, tell the child to ignore persisted
   1.507 +  // full screen states. This way new browser windows open on top of fullscreen
   1.508 +  // windows normally.
   1.509 +  if (window && CheckForFullscreenWindow())
   1.510 +    window->IgnoreXULSizeMode(true);
   1.511 +#endif
   1.512 +
   1.513 +  nsWidgetInitData widgetInitData;
   1.514 +
   1.515 +  if (aIsHiddenWindow)
   1.516 +    widgetInitData.mWindowType = eWindowType_invisible;
   1.517 +  else
   1.518 +    widgetInitData.mWindowType = aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG ?
   1.519 +      eWindowType_dialog : eWindowType_toplevel;
   1.520 +
   1.521 +  if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_POPUP)
   1.522 +    widgetInitData.mWindowType = eWindowType_popup;
   1.523 +
   1.524 +  if (aChromeMask & nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION)
   1.525 +    widgetInitData.mIsAnimationSuppressed = true;
   1.526 +
   1.527 +  if (aChromeMask & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW)
   1.528 +    widgetInitData.mRequireOffMainThreadCompositing = true;
   1.529 +
   1.530 +#ifdef XP_MACOSX
   1.531 +  // Mac OS X sheet support
   1.532 +  // Adding CHROME_OPENAS_CHROME to sheetMask makes modal windows opened from
   1.533 +  // nsGlobalWindow::ShowModalDialog() be dialogs (not sheets), while modal
   1.534 +  // windows opened from nsPromptService::DoDialog() still are sheets.  This
   1.535 +  // fixes bmo bug 395465 (see nsCocoaWindow::StandardCreate() and
   1.536 +  // nsCocoaWindow::SetModal()).
   1.537 +  uint32_t sheetMask = nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
   1.538 +                       nsIWebBrowserChrome::CHROME_MODAL |
   1.539 +                       nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
   1.540 +  if (parent &&
   1.541 +      (parent != mHiddenWindow && parent != mHiddenPrivateWindow) &&
   1.542 +      ((aChromeMask & sheetMask) == sheetMask)) {
   1.543 +    widgetInitData.mWindowType = eWindowType_sheet;
   1.544 +  }
   1.545 +#endif
   1.546 +
   1.547 +#if defined(XP_WIN)
   1.548 +  if (widgetInitData.mWindowType == eWindowType_toplevel ||
   1.549 +      widgetInitData.mWindowType == eWindowType_dialog)
   1.550 +    widgetInitData.clipChildren = true;
   1.551 +#endif
   1.552 +
   1.553 +  // note default chrome overrides other OS chrome settings, but
   1.554 +  // not internal chrome
   1.555 +  if (aChromeMask & nsIWebBrowserChrome::CHROME_DEFAULT)
   1.556 +    widgetInitData.mBorderStyle = eBorderStyle_default;
   1.557 +  else if ((aChromeMask & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL)
   1.558 +    widgetInitData.mBorderStyle = eBorderStyle_all;
   1.559 +  else {
   1.560 +    widgetInitData.mBorderStyle = eBorderStyle_none; // assumes none == 0x00
   1.561 +    if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_BORDERS)
   1.562 +      widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_border);
   1.563 +    if (aChromeMask & nsIWebBrowserChrome::CHROME_TITLEBAR)
   1.564 +      widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_title);
   1.565 +    if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_CLOSE)
   1.566 +      widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_close);
   1.567 +    if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) {
   1.568 +      widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_resizeh);
   1.569 +      // only resizable windows get the maximize button (but not dialogs)
   1.570 +      if (!(aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG))
   1.571 +        widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_maximize);
   1.572 +    }
   1.573 +    // all windows (except dialogs) get minimize buttons and the system menu
   1.574 +    if (!(aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG))
   1.575 +      widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_minimize | eBorderStyle_menu);
   1.576 +    // but anyone can explicitly ask for a minimize button
   1.577 +    if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_MIN) {
   1.578 +      widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_minimize);
   1.579 +    }  
   1.580 +  }
   1.581 +
   1.582 +  if (aInitialWidth == nsIAppShellService::SIZE_TO_CONTENT ||
   1.583 +      aInitialHeight == nsIAppShellService::SIZE_TO_CONTENT) {
   1.584 +    aInitialWidth = 1;
   1.585 +    aInitialHeight = 1;
   1.586 +    window->SetIntrinsicallySized(true);
   1.587 +  }
   1.588 +
   1.589 +  bool center = aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN;
   1.590 +
   1.591 +  nsCOMPtr<nsIXULChromeRegistry> reg =
   1.592 +    mozilla::services::GetXULChromeRegistryService();
   1.593 +  if (reg) {
   1.594 +    nsAutoCString package;
   1.595 +    package.AssignLiteral("global");
   1.596 +    bool isRTL = false;
   1.597 +    reg->IsLocaleRTL(package, &isRTL);
   1.598 +    widgetInitData.mRTL = isRTL;
   1.599 +  }
   1.600 +
   1.601 +  nsresult rv = window->Initialize(parent, center ? aParent : nullptr,
   1.602 +                                   aUrl, aInitialWidth, aInitialHeight,
   1.603 +                                   aIsHiddenWindow, widgetInitData);
   1.604 +
   1.605 +  NS_ENSURE_SUCCESS(rv, rv);
   1.606 +
   1.607 +  // Enforce the Private Browsing autoStart pref first.
   1.608 +  bool isPrivateBrowsingWindow =
   1.609 +    Preferences::GetBool("browser.privatebrowsing.autostart");
   1.610 +  if (aChromeMask & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW) {
   1.611 +    // Caller requested a private window
   1.612 +    isPrivateBrowsingWindow = true;
   1.613 +  }
   1.614 +  if (!isPrivateBrowsingWindow) {
   1.615 +    // Ensure that we propagate any existing private browsing status
   1.616 +    // from the parent, even if it will not actually be used
   1.617 +    // as a parent value.
   1.618 +    nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(aParent);
   1.619 +    nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(domWin);
   1.620 +    nsCOMPtr<nsILoadContext> parentContext = do_QueryInterface(webNav);
   1.621 +    if (parentContext) {
   1.622 +      isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing();
   1.623 +    }
   1.624 +  }
   1.625 +  nsCOMPtr<nsIDOMWindow> newDomWin =
   1.626 +      do_GetInterface(NS_ISUPPORTS_CAST(nsIBaseWindow*, window));
   1.627 +  nsCOMPtr<nsIWebNavigation> newWebNav = do_GetInterface(newDomWin);
   1.628 +  nsCOMPtr<nsILoadContext> thisContext = do_GetInterface(newWebNav);
   1.629 +  if (thisContext) {
   1.630 +    thisContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
   1.631 +  }
   1.632 +
   1.633 +  window.swap(*aResult); // transfer reference
   1.634 +  if (parent)
   1.635 +    parent->AddChildWindow(*aResult);
   1.636 +
   1.637 +  if (center)
   1.638 +    rv = (*aResult)->Center(parent, parent ? false : true, false);
   1.639 +
   1.640 +  return rv;
   1.641 +}
   1.642 +
   1.643 +NS_IMETHODIMP
   1.644 +nsAppShellService::GetHiddenWindow(nsIXULWindow **aWindow)
   1.645 +{
   1.646 +  NS_ENSURE_ARG_POINTER(aWindow);
   1.647 +
   1.648 +  *aWindow = mHiddenWindow;
   1.649 +  NS_IF_ADDREF(*aWindow);
   1.650 +  return *aWindow ? NS_OK : NS_ERROR_FAILURE;
   1.651 +}
   1.652 +
   1.653 +NS_IMETHODIMP
   1.654 +nsAppShellService::GetHiddenDOMWindow(nsIDOMWindow **aWindow)
   1.655 +{
   1.656 +  nsresult rv;
   1.657 +  nsCOMPtr<nsIDocShell> docShell;
   1.658 +  NS_ENSURE_TRUE(mHiddenWindow, NS_ERROR_FAILURE);
   1.659 +
   1.660 +  rv = mHiddenWindow->GetDocShell(getter_AddRefs(docShell));
   1.661 +  NS_ENSURE_SUCCESS(rv, rv);
   1.662 +
   1.663 +  nsCOMPtr<nsIDOMWindow> hiddenDOMWindow(do_GetInterface(docShell, &rv));
   1.664 +  NS_ENSURE_SUCCESS(rv, rv);
   1.665 +
   1.666 +  *aWindow = hiddenDOMWindow;
   1.667 +  NS_IF_ADDREF(*aWindow);
   1.668 +  return NS_OK;
   1.669 +}
   1.670 +
   1.671 +NS_IMETHODIMP
   1.672 +nsAppShellService::GetHiddenPrivateWindow(nsIXULWindow **aWindow)
   1.673 +{
   1.674 +  NS_ENSURE_ARG_POINTER(aWindow);
   1.675 +
   1.676 +  EnsurePrivateHiddenWindow();
   1.677 +
   1.678 +  *aWindow = mHiddenPrivateWindow;
   1.679 +  NS_IF_ADDREF(*aWindow);
   1.680 +  return *aWindow ? NS_OK : NS_ERROR_FAILURE;
   1.681 +}
   1.682 +
   1.683 +NS_IMETHODIMP
   1.684 +nsAppShellService::GetHiddenPrivateDOMWindow(nsIDOMWindow **aWindow)
   1.685 +{
   1.686 +  EnsurePrivateHiddenWindow();
   1.687 +
   1.688 +  nsresult rv;
   1.689 +  nsCOMPtr<nsIDocShell> docShell;
   1.690 +  NS_ENSURE_TRUE(mHiddenPrivateWindow, NS_ERROR_FAILURE);
   1.691 +
   1.692 +  rv = mHiddenPrivateWindow->GetDocShell(getter_AddRefs(docShell));
   1.693 +  NS_ENSURE_SUCCESS(rv, rv);
   1.694 +
   1.695 +  nsCOMPtr<nsIDOMWindow> hiddenPrivateDOMWindow(do_GetInterface(docShell, &rv));
   1.696 +  NS_ENSURE_SUCCESS(rv, rv);
   1.697 +
   1.698 +  *aWindow = hiddenPrivateDOMWindow;
   1.699 +  NS_IF_ADDREF(*aWindow);
   1.700 +  return NS_OK;
   1.701 +}
   1.702 +
   1.703 +NS_IMETHODIMP
   1.704 +nsAppShellService::GetHasHiddenPrivateWindow(bool* aHasPrivateWindow)
   1.705 +{
   1.706 +  NS_ENSURE_ARG_POINTER(aHasPrivateWindow);
   1.707 +
   1.708 +  *aHasPrivateWindow = !!mHiddenPrivateWindow;
   1.709 +  return NS_OK;
   1.710 +}
   1.711 +
   1.712 +NS_IMETHODIMP
   1.713 +nsAppShellService::GetHiddenWindowAndJSContext(nsIDOMWindow **aWindow,
   1.714 +                                               JSContext    **aJSContext)
   1.715 +{
   1.716 +    nsresult rv = NS_OK;
   1.717 +    if ( aWindow && aJSContext ) {
   1.718 +        *aWindow    = nullptr;
   1.719 +        *aJSContext = nullptr;
   1.720 +
   1.721 +        if ( mHiddenWindow ) {
   1.722 +            // Convert hidden window to nsIDOMWindow and extract its JSContext.
   1.723 +            do {
   1.724 +                // 1. Get doc for hidden window.
   1.725 +                nsCOMPtr<nsIDocShell> docShell;
   1.726 +                rv = mHiddenWindow->GetDocShell(getter_AddRefs(docShell));
   1.727 +                if (NS_FAILED(rv)) break;
   1.728 +
   1.729 +                // 2. Convert that to an nsIDOMWindow.
   1.730 +                nsCOMPtr<nsIDOMWindow> hiddenDOMWindow(do_GetInterface(docShell));
   1.731 +                if(!hiddenDOMWindow) break;
   1.732 +
   1.733 +                // 3. Get script global object for the window.
   1.734 +                nsCOMPtr<nsIScriptGlobalObject> sgo;
   1.735 +                sgo = do_QueryInterface( hiddenDOMWindow );
   1.736 +                if (!sgo) { rv = NS_ERROR_FAILURE; break; }
   1.737 +
   1.738 +                // 4. Get script context from that.
   1.739 +                nsIScriptContext *scriptContext = sgo->GetContext();
   1.740 +                if (!scriptContext) { rv = NS_ERROR_FAILURE; break; }
   1.741 +
   1.742 +                // 5. Get JSContext from the script context.
   1.743 +                JSContext *jsContext = scriptContext->GetNativeContext();
   1.744 +                if (!jsContext) { rv = NS_ERROR_FAILURE; break; }
   1.745 +
   1.746 +                // Now, give results to caller.
   1.747 +                *aWindow    = hiddenDOMWindow.get();
   1.748 +                NS_IF_ADDREF( *aWindow );
   1.749 +                *aJSContext = jsContext;
   1.750 +            } while (0);
   1.751 +        } else {
   1.752 +            rv = NS_ERROR_FAILURE;
   1.753 +        }
   1.754 +    } else {
   1.755 +        rv = NS_ERROR_NULL_POINTER;
   1.756 +    }
   1.757 +    return rv;
   1.758 +}
   1.759 +
   1.760 +NS_IMETHODIMP
   1.761 +nsAppShellService::GetApplicationProvidedHiddenWindow(bool* aAPHW)
   1.762 +{
   1.763 +    *aAPHW = mApplicationProvidedHiddenWindow;
   1.764 +    return NS_OK;
   1.765 +}
   1.766 +
   1.767 +/*
   1.768 + * Register a new top level window (created elsewhere)
   1.769 + */
   1.770 +NS_IMETHODIMP
   1.771 +nsAppShellService::RegisterTopLevelWindow(nsIXULWindow* aWindow)
   1.772 +{
   1.773 +  NS_ENSURE_ARG_POINTER(aWindow);
   1.774 +
   1.775 +  nsCOMPtr<nsIDocShell> docShell;
   1.776 +  aWindow->GetDocShell(getter_AddRefs(docShell));
   1.777 +  nsCOMPtr<nsPIDOMWindow> domWindow(do_GetInterface(docShell));
   1.778 +  NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
   1.779 +  domWindow->SetInitialPrincipalToSubject();
   1.780 +
   1.781 +  // tell the window mediator about the new window
   1.782 +  nsCOMPtr<nsIWindowMediator> mediator
   1.783 +    ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID) );
   1.784 +  NS_ASSERTION(mediator, "Couldn't get window mediator.");
   1.785 +
   1.786 +  if (mediator)
   1.787 +    mediator->RegisterWindow(aWindow);
   1.788 +
   1.789 +  // tell the window watcher about the new window
   1.790 +  nsCOMPtr<nsPIWindowWatcher> wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID) );
   1.791 +  NS_ASSERTION(wwatcher, "No windowwatcher?");
   1.792 +  if (wwatcher && domWindow) {
   1.793 +    wwatcher->AddWindow(domWindow, 0);
   1.794 +  }
   1.795 +
   1.796 +  // an ongoing attempt to quit is stopped by a newly opened window
   1.797 +  nsCOMPtr<nsIObserverService> obssvc =
   1.798 +    do_GetService("@mozilla.org/observer-service;1");
   1.799 +  NS_ASSERTION(obssvc, "Couldn't get observer service.");
   1.800 +
   1.801 +  if (obssvc)
   1.802 +    obssvc->NotifyObservers(aWindow, "xul-window-registered", nullptr);
   1.803 +
   1.804 +  return NS_OK;
   1.805 +}
   1.806 +
   1.807 +
   1.808 +NS_IMETHODIMP
   1.809 +nsAppShellService::UnregisterTopLevelWindow(nsIXULWindow* aWindow)
   1.810 +{
   1.811 +  if (mXPCOMShuttingDown) {
   1.812 +    /* return an error code in order to:
   1.813 +       - avoid doing anything with other member variables while we are in
   1.814 +         the destructor
   1.815 +       - notify the caller not to release the AppShellService after
   1.816 +         unregistering the window
   1.817 +         (we don't want to be deleted twice consecutively to
   1.818 +         mHiddenWindow->Destroy() in our destructor)
   1.819 +    */
   1.820 +    return NS_ERROR_FAILURE;
   1.821 +  }
   1.822 +
   1.823 +  NS_ENSURE_ARG_POINTER(aWindow);
   1.824 +
   1.825 +  if (aWindow == mHiddenWindow) {
   1.826 +    // CreateHiddenWindow() does not register the window, so we're done.
   1.827 +    return NS_OK;
   1.828 +  }
   1.829 +  if (aWindow == mHiddenPrivateWindow) {
   1.830 +    // CreateHiddenWindow() does not register the window, so we're done.
   1.831 +    return NS_OK;
   1.832 +  }
   1.833 +
   1.834 +  // tell the window mediator
   1.835 +  nsCOMPtr<nsIWindowMediator> mediator
   1.836 +    ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID) );
   1.837 +  NS_ASSERTION(mediator, "Couldn't get window mediator. Doing xpcom shutdown?");
   1.838 +
   1.839 +  if (mediator)
   1.840 +    mediator->UnregisterWindow(aWindow);
   1.841 +
   1.842 +  // tell the window watcher
   1.843 +  nsCOMPtr<nsPIWindowWatcher> wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID) );
   1.844 +  NS_ASSERTION(wwatcher, "Couldn't get windowwatcher, doing xpcom shutdown?");
   1.845 +  if (wwatcher) {
   1.846 +    nsCOMPtr<nsIDocShell> docShell;
   1.847 +    aWindow->GetDocShell(getter_AddRefs(docShell));
   1.848 +    if (docShell) {
   1.849 +      nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(docShell));
   1.850 +      if (domWindow)
   1.851 +        wwatcher->RemoveWindow(domWindow);
   1.852 +    }
   1.853 +  }
   1.854 +
   1.855 +  return NS_OK;
   1.856 +}
   1.857 +
   1.858 +
   1.859 +NS_IMETHODIMP
   1.860 +nsAppShellService::Observe(nsISupports* aSubject, const char *aTopic,
   1.861 +                           const char16_t *aData)
   1.862 +{
   1.863 +  if (!strcmp(aTopic, "xpcom-will-shutdown")) {
   1.864 +    mXPCOMWillShutDown = true;
   1.865 +  } else if (!strcmp(aTopic, "xpcom-shutdown")) {
   1.866 +    mXPCOMShuttingDown = true;
   1.867 +    if (mHiddenWindow) {
   1.868 +      mHiddenWindow->Destroy();
   1.869 +    }
   1.870 +    if (mHiddenPrivateWindow) {
   1.871 +      mHiddenPrivateWindow->Destroy();
   1.872 +    }
   1.873 +  } else {
   1.874 +    NS_ERROR("Unexpected observer topic!");
   1.875 +  }
   1.876 +
   1.877 +  return NS_OK;
   1.878 +}
   1.879 +
   1.880 +NS_IMETHODIMP
   1.881 +nsAppShellService::StartEventLoopLagTracking(bool* aResult)
   1.882 +{
   1.883 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP
   1.884 +    *aResult = mozilla::InitEventTracing(true);
   1.885 +#endif
   1.886 +    return NS_OK;
   1.887 +}
   1.888 +
   1.889 +NS_IMETHODIMP
   1.890 +nsAppShellService::StopEventLoopLagTracking()
   1.891 +{
   1.892 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP
   1.893 +    mozilla::ShutdownEventTracing();
   1.894 +#endif
   1.895 +    return NS_OK;
   1.896 +}

mercurial