xpfe/appshell/src/nsAppShellService.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6
michael@0 7 #include "nsIAppShellService.h"
michael@0 8 #include "nsIComponentManager.h"
michael@0 9 #include "nsIURL.h"
michael@0 10 #include "nsNetUtil.h"
michael@0 11 #include "nsIServiceManager.h"
michael@0 12 #include "nsIObserverService.h"
michael@0 13 #include "nsIObserver.h"
michael@0 14 #include "nsIXPConnect.h"
michael@0 15
michael@0 16 #include "nsIWindowMediator.h"
michael@0 17 #include "nsIWindowWatcher.h"
michael@0 18 #include "nsPIWindowWatcher.h"
michael@0 19 #include "nsIDOMWindow.h"
michael@0 20 #include "nsPIDOMWindow.h"
michael@0 21 #include "nsWebShellWindow.h"
michael@0 22
michael@0 23 #include "nsCRT.h"
michael@0 24 #include "prprf.h"
michael@0 25
michael@0 26 #include "nsWidgetInitData.h"
michael@0 27 #include "nsWidgetsCID.h"
michael@0 28 #include "nsIWidget.h"
michael@0 29 #include "nsIRequestObserver.h"
michael@0 30
michael@0 31 /* For implementing GetHiddenWindowAndJSContext */
michael@0 32 #include "nsIScriptGlobalObject.h"
michael@0 33 #include "nsIScriptContext.h"
michael@0 34
michael@0 35 #include "nsAppShellService.h"
michael@0 36 #include "nsISupportsPrimitives.h"
michael@0 37 #include "nsIChromeRegistry.h"
michael@0 38 #include "nsILoadContext.h"
michael@0 39 #include "nsIWebNavigation.h"
michael@0 40
michael@0 41 #include "mozilla/Attributes.h"
michael@0 42 #include "mozilla/Preferences.h"
michael@0 43 #include "mozilla/StartupTimeline.h"
michael@0 44
michael@0 45 #include "nsEmbedCID.h"
michael@0 46 #include "nsIWebBrowser.h"
michael@0 47 #include "nsIDocShell.h"
michael@0 48
michael@0 49 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
michael@0 50 #include "EventTracer.h"
michael@0 51 #endif
michael@0 52
michael@0 53 using namespace mozilla;
michael@0 54
michael@0 55 // Default URL for the hidden window, can be overridden by a pref on Mac
michael@0 56 #define DEFAULT_HIDDENWINDOW_URL "resource://gre-resources/hiddenWindow.html"
michael@0 57
michael@0 58 class nsIAppShell;
michael@0 59
michael@0 60 nsAppShellService::nsAppShellService() :
michael@0 61 mXPCOMWillShutDown(false),
michael@0 62 mXPCOMShuttingDown(false),
michael@0 63 mModalWindowCount(0),
michael@0 64 mApplicationProvidedHiddenWindow(false)
michael@0 65 {
michael@0 66 nsCOMPtr<nsIObserverService> obs
michael@0 67 (do_GetService("@mozilla.org/observer-service;1"));
michael@0 68
michael@0 69 if (obs) {
michael@0 70 obs->AddObserver(this, "xpcom-will-shutdown", false);
michael@0 71 obs->AddObserver(this, "xpcom-shutdown", false);
michael@0 72 }
michael@0 73 }
michael@0 74
michael@0 75 nsAppShellService::~nsAppShellService()
michael@0 76 {
michael@0 77 }
michael@0 78
michael@0 79
michael@0 80 /*
michael@0 81 * Implement the nsISupports methods...
michael@0 82 */
michael@0 83 NS_IMPL_ISUPPORTS(nsAppShellService,
michael@0 84 nsIAppShellService,
michael@0 85 nsIObserver)
michael@0 86
michael@0 87 NS_IMETHODIMP
michael@0 88 nsAppShellService::CreateHiddenWindow()
michael@0 89 {
michael@0 90 return CreateHiddenWindowHelper(false);
michael@0 91 }
michael@0 92
michael@0 93 void
michael@0 94 nsAppShellService::EnsurePrivateHiddenWindow()
michael@0 95 {
michael@0 96 if (!mHiddenPrivateWindow) {
michael@0 97 CreateHiddenWindowHelper(true);
michael@0 98 }
michael@0 99 }
michael@0 100
michael@0 101 nsresult
michael@0 102 nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate)
michael@0 103 {
michael@0 104 nsresult rv;
michael@0 105 int32_t initialHeight = 100, initialWidth = 100;
michael@0 106
michael@0 107 #ifdef XP_MACOSX
michael@0 108 uint32_t chromeMask = 0;
michael@0 109 nsAdoptingCString prefVal =
michael@0 110 Preferences::GetCString("browser.hiddenWindowChromeURL");
michael@0 111 const char* hiddenWindowURL = prefVal.get() ? prefVal.get() : DEFAULT_HIDDENWINDOW_URL;
michael@0 112 if (aIsPrivate) {
michael@0 113 hiddenWindowURL = DEFAULT_HIDDENWINDOW_URL;
michael@0 114 } else {
michael@0 115 mApplicationProvidedHiddenWindow = prefVal.get() ? true : false;
michael@0 116 }
michael@0 117 #else
michael@0 118 static const char hiddenWindowURL[] = DEFAULT_HIDDENWINDOW_URL;
michael@0 119 uint32_t chromeMask = nsIWebBrowserChrome::CHROME_ALL;
michael@0 120 #endif
michael@0 121
michael@0 122 nsCOMPtr<nsIURI> url;
michael@0 123 rv = NS_NewURI(getter_AddRefs(url), hiddenWindowURL);
michael@0 124 NS_ENSURE_SUCCESS(rv, rv);
michael@0 125
michael@0 126 nsRefPtr<nsWebShellWindow> newWindow;
michael@0 127 if (!aIsPrivate) {
michael@0 128 rv = JustCreateTopWindow(nullptr, url,
michael@0 129 chromeMask, initialWidth, initialHeight,
michael@0 130 true, getter_AddRefs(newWindow));
michael@0 131 NS_ENSURE_SUCCESS(rv, rv);
michael@0 132
michael@0 133 mHiddenWindow.swap(newWindow);
michael@0 134 } else {
michael@0 135 // Create the hidden private window
michael@0 136 chromeMask |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
michael@0 137
michael@0 138 rv = JustCreateTopWindow(nullptr, url,
michael@0 139 chromeMask, initialWidth, initialHeight,
michael@0 140 true, getter_AddRefs(newWindow));
michael@0 141 NS_ENSURE_SUCCESS(rv, rv);
michael@0 142
michael@0 143 nsCOMPtr<nsIDocShell> docShell;
michael@0 144 newWindow->GetDocShell(getter_AddRefs(docShell));
michael@0 145 if (docShell) {
michael@0 146 docShell->SetAffectPrivateSessionLifetime(false);
michael@0 147 }
michael@0 148
michael@0 149 mHiddenPrivateWindow.swap(newWindow);
michael@0 150 }
michael@0 151
michael@0 152 // RegisterTopLevelWindow(newWindow); -- Mac only
michael@0 153
michael@0 154 return NS_OK;
michael@0 155 }
michael@0 156
michael@0 157 NS_IMETHODIMP
michael@0 158 nsAppShellService::DestroyHiddenWindow()
michael@0 159 {
michael@0 160 if (mHiddenWindow) {
michael@0 161 mHiddenWindow->Destroy();
michael@0 162
michael@0 163 mHiddenWindow = nullptr;
michael@0 164 }
michael@0 165
michael@0 166 if (mHiddenPrivateWindow) {
michael@0 167 mHiddenPrivateWindow->Destroy();
michael@0 168
michael@0 169 mHiddenPrivateWindow = nullptr;
michael@0 170 }
michael@0 171
michael@0 172 return NS_OK;
michael@0 173 }
michael@0 174
michael@0 175 /*
michael@0 176 * Create a new top level window and display the given URL within it...
michael@0 177 */
michael@0 178 NS_IMETHODIMP
michael@0 179 nsAppShellService::CreateTopLevelWindow(nsIXULWindow *aParent,
michael@0 180 nsIURI *aUrl,
michael@0 181 uint32_t aChromeMask,
michael@0 182 int32_t aInitialWidth,
michael@0 183 int32_t aInitialHeight,
michael@0 184 nsIXULWindow **aResult)
michael@0 185
michael@0 186 {
michael@0 187 nsresult rv;
michael@0 188
michael@0 189 StartupTimeline::RecordOnce(StartupTimeline::CREATE_TOP_LEVEL_WINDOW);
michael@0 190
michael@0 191 nsWebShellWindow *newWindow = nullptr;
michael@0 192 rv = JustCreateTopWindow(aParent, aUrl,
michael@0 193 aChromeMask, aInitialWidth, aInitialHeight,
michael@0 194 false, &newWindow); // addrefs
michael@0 195
michael@0 196 *aResult = newWindow; // transfer ref
michael@0 197
michael@0 198 if (NS_SUCCEEDED(rv)) {
michael@0 199 // the addref resulting from this is the owning addref for this window
michael@0 200 RegisterTopLevelWindow(*aResult);
michael@0 201 nsCOMPtr<nsIXULWindow> parent;
michael@0 202 if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
michael@0 203 parent = aParent;
michael@0 204 (*aResult)->SetZLevel(CalculateWindowZLevel(parent, aChromeMask));
michael@0 205 }
michael@0 206
michael@0 207 return rv;
michael@0 208 }
michael@0 209
michael@0 210 /*
michael@0 211 * This class provides a stub implementation of nsIWebBrowserChrome2, as needed
michael@0 212 * by nsAppShellService::CreateWindowlessBrowser
michael@0 213 */
michael@0 214 class WebBrowserChrome2Stub : public nsIWebBrowserChrome2,
michael@0 215 public nsIInterfaceRequestor,
michael@0 216 public nsSupportsWeakReference {
michael@0 217 public:
michael@0 218 virtual ~WebBrowserChrome2Stub() {}
michael@0 219 NS_DECL_ISUPPORTS
michael@0 220 NS_DECL_NSIWEBBROWSERCHROME
michael@0 221 NS_DECL_NSIWEBBROWSERCHROME2
michael@0 222 NS_DECL_NSIINTERFACEREQUESTOR
michael@0 223 };
michael@0 224
michael@0 225 NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub)
michael@0 226 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome)
michael@0 227 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
michael@0 228 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2)
michael@0 229 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
michael@0 230 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
michael@0 231 NS_INTERFACE_MAP_END
michael@0 232
michael@0 233 NS_IMPL_ADDREF(WebBrowserChrome2Stub)
michael@0 234 NS_IMPL_RELEASE(WebBrowserChrome2Stub)
michael@0 235
michael@0 236 NS_IMETHODIMP
michael@0 237 WebBrowserChrome2Stub::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
michael@0 238 {
michael@0 239 return NS_OK;
michael@0 240 }
michael@0 241
michael@0 242 NS_IMETHODIMP
michael@0 243 WebBrowserChrome2Stub::GetWebBrowser(nsIWebBrowser** aWebBrowser)
michael@0 244 {
michael@0 245 NS_NOTREACHED("WebBrowserChrome2Stub::GetWebBrowser is not supported");
michael@0 246 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 247 }
michael@0 248
michael@0 249 NS_IMETHODIMP
michael@0 250 WebBrowserChrome2Stub::SetWebBrowser(nsIWebBrowser* aWebBrowser)
michael@0 251 {
michael@0 252 NS_NOTREACHED("WebBrowserChrome2Stub::SetWebBrowser is not supported");
michael@0 253 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 254 }
michael@0 255
michael@0 256 NS_IMETHODIMP
michael@0 257 WebBrowserChrome2Stub::GetChromeFlags(uint32_t* aChromeFlags)
michael@0 258 {
michael@0 259 *aChromeFlags = 0;
michael@0 260 return NS_OK;
michael@0 261 }
michael@0 262
michael@0 263 NS_IMETHODIMP
michael@0 264 WebBrowserChrome2Stub::SetChromeFlags(uint32_t aChromeFlags)
michael@0 265 {
michael@0 266 NS_NOTREACHED("WebBrowserChrome2Stub::SetChromeFlags is not supported");
michael@0 267 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 268 }
michael@0 269
michael@0 270 NS_IMETHODIMP
michael@0 271 WebBrowserChrome2Stub::DestroyBrowserWindow()
michael@0 272 {
michael@0 273 NS_NOTREACHED("WebBrowserChrome2Stub::DestroyBrowserWindow is not supported");
michael@0 274 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 275 }
michael@0 276
michael@0 277 NS_IMETHODIMP
michael@0 278 WebBrowserChrome2Stub::SizeBrowserTo(int32_t aCX, int32_t aCY)
michael@0 279 {
michael@0 280 NS_NOTREACHED("WebBrowserChrome2Stub::SizeBrowserTo is not supported");
michael@0 281 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 282 }
michael@0 283
michael@0 284 NS_IMETHODIMP
michael@0 285 WebBrowserChrome2Stub::ShowAsModal()
michael@0 286 {
michael@0 287 NS_NOTREACHED("WebBrowserChrome2Stub::ShowAsModal is not supported");
michael@0 288 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 289 }
michael@0 290
michael@0 291 NS_IMETHODIMP
michael@0 292 WebBrowserChrome2Stub::IsWindowModal(bool* aResult)
michael@0 293 {
michael@0 294 *aResult = false;
michael@0 295 return NS_OK;
michael@0 296 }
michael@0 297
michael@0 298 NS_IMETHODIMP
michael@0 299 WebBrowserChrome2Stub::ExitModalEventLoop(nsresult aStatus)
michael@0 300 {
michael@0 301 NS_NOTREACHED("WebBrowserChrome2Stub::ExitModalEventLoop is not supported");
michael@0 302 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 303 }
michael@0 304
michael@0 305 NS_IMETHODIMP
michael@0 306 WebBrowserChrome2Stub::SetStatusWithContext(uint32_t aStatusType,
michael@0 307 const nsAString& aStatusText,
michael@0 308 nsISupports* aStatusContext)
michael@0 309 {
michael@0 310 return NS_OK;
michael@0 311 }
michael@0 312
michael@0 313 NS_IMETHODIMP
michael@0 314 WebBrowserChrome2Stub::GetInterface(const nsIID & aIID, void **aSink)
michael@0 315 {
michael@0 316 return QueryInterface(aIID, aSink);
michael@0 317 }
michael@0 318
michael@0 319 // This is the "stub" we return from CreateWindowlessBrowser - it exists
michael@0 320 // purely to keep a strong reference to the browser and the container to
michael@0 321 // prevent the container being collected while the stub remains alive.
michael@0 322 class WindowlessBrowserStub MOZ_FINAL : public nsIWebNavigation,
michael@0 323 public nsIInterfaceRequestor {
michael@0 324 public:
michael@0 325 WindowlessBrowserStub(nsIWebBrowser *aBrowser, nsISupports *aContainer) {
michael@0 326 mBrowser = aBrowser;
michael@0 327 mWebNavigation = do_QueryInterface(aBrowser);
michael@0 328 mInterfaceRequestor = do_QueryInterface(aBrowser);
michael@0 329 mContainer = aContainer;
michael@0 330 }
michael@0 331 NS_DECL_ISUPPORTS
michael@0 332 NS_FORWARD_NSIWEBNAVIGATION(mWebNavigation->)
michael@0 333 NS_FORWARD_NSIINTERFACEREQUESTOR(mInterfaceRequestor->)
michael@0 334 private:
michael@0 335 nsCOMPtr<nsIWebBrowser> mBrowser;
michael@0 336 nsCOMPtr<nsIWebNavigation> mWebNavigation;
michael@0 337 nsCOMPtr<nsIInterfaceRequestor> mInterfaceRequestor;
michael@0 338 // we don't use the container but just hold a reference to it.
michael@0 339 nsCOMPtr<nsISupports> mContainer;
michael@0 340 };
michael@0 341
michael@0 342 NS_INTERFACE_MAP_BEGIN(WindowlessBrowserStub)
michael@0 343 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebNavigation)
michael@0 344 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
michael@0 345 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
michael@0 346 NS_INTERFACE_MAP_END
michael@0 347
michael@0 348 NS_IMPL_ADDREF(WindowlessBrowserStub)
michael@0 349 NS_IMPL_RELEASE(WindowlessBrowserStub)
michael@0 350
michael@0 351
michael@0 352 NS_IMETHODIMP
michael@0 353 nsAppShellService::CreateWindowlessBrowser(bool aIsChrome, nsIWebNavigation **aResult)
michael@0 354 {
michael@0 355 /* First, we create an instance of nsWebBrowser. Instances of this class have
michael@0 356 * an associated doc shell, which is what we're interested in.
michael@0 357 */
michael@0 358 nsCOMPtr<nsIWebBrowser> browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
michael@0 359 if (!browser) {
michael@0 360 NS_ERROR("Couldn't create instance of nsWebBrowser!");
michael@0 361 return NS_ERROR_FAILURE;
michael@0 362 }
michael@0 363
michael@0 364 /* Next, we set the container window for our instance of nsWebBrowser. Since
michael@0 365 * we don't actually have a window, we instead set the container window to be
michael@0 366 * an instance of WebBrowserChrome2Stub, which provides a stub implementation
michael@0 367 * of nsIWebBrowserChrome2.
michael@0 368 */
michael@0 369 nsRefPtr<WebBrowserChrome2Stub> stub = new WebBrowserChrome2Stub();
michael@0 370 if (!stub) {
michael@0 371 NS_ERROR("Couldn't create instance of WebBrowserChrome2Stub!");
michael@0 372 return NS_ERROR_FAILURE;
michael@0 373 }
michael@0 374 browser->SetContainerWindow(stub);
michael@0 375
michael@0 376 nsCOMPtr<nsIWebNavigation> navigation = do_QueryInterface(browser);
michael@0 377
michael@0 378 nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(navigation);
michael@0 379 item->SetItemType(aIsChrome ? nsIDocShellTreeItem::typeChromeWrapper
michael@0 380 : nsIDocShellTreeItem::typeContentWrapper);
michael@0 381
michael@0 382 /* A windowless web browser doesn't have an associated OS level window. To
michael@0 383 * accomplish this, we initialize the window associated with our instance of
michael@0 384 * nsWebBrowser with an instance of PuppetWidget, which provides a stub
michael@0 385 * implementation of nsIWidget.
michael@0 386 */
michael@0 387 nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(nullptr);
michael@0 388 if (!widget) {
michael@0 389 NS_ERROR("Couldn't create instance of PuppetWidget");
michael@0 390 return NS_ERROR_FAILURE;
michael@0 391 }
michael@0 392 widget->Create(nullptr, 0, nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
michael@0 393 nullptr, nullptr);
michael@0 394 nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(navigation);
michael@0 395 window->InitWindow(0, widget, 0, 0, 0, 0);
michael@0 396 window->Create();
michael@0 397
michael@0 398 nsISupports *isstub = NS_ISUPPORTS_CAST(nsIWebBrowserChrome2*, stub);
michael@0 399 nsRefPtr<nsIWebNavigation> result = new WindowlessBrowserStub(browser, isstub);
michael@0 400 nsCOMPtr<nsIDocShell> docshell = do_GetInterface(result);
michael@0 401 docshell->SetInvisible(true);
michael@0 402
michael@0 403 result.forget(aResult);
michael@0 404 return NS_OK;
michael@0 405 }
michael@0 406
michael@0 407 uint32_t
michael@0 408 nsAppShellService::CalculateWindowZLevel(nsIXULWindow *aParent,
michael@0 409 uint32_t aChromeMask)
michael@0 410 {
michael@0 411 uint32_t zLevel;
michael@0 412
michael@0 413 zLevel = nsIXULWindow::normalZ;
michael@0 414 if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RAISED)
michael@0 415 zLevel = nsIXULWindow::raisedZ;
michael@0 416 else if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_LOWERED)
michael@0 417 zLevel = nsIXULWindow::loweredZ;
michael@0 418
michael@0 419 #ifdef XP_MACOSX
michael@0 420 /* Platforms on which modal windows are always application-modal, not
michael@0 421 window-modal (that's just the Mac, right?) want modal windows to
michael@0 422 be stacked on top of everyone else.
michael@0 423
michael@0 424 On Mac OS X, bind modality to parent window instead of app (ala Mac OS 9)
michael@0 425 */
michael@0 426 uint32_t modalDepMask = nsIWebBrowserChrome::CHROME_MODAL |
michael@0 427 nsIWebBrowserChrome::CHROME_DEPENDENT;
michael@0 428 if (aParent && (aChromeMask & modalDepMask)) {
michael@0 429 aParent->GetZLevel(&zLevel);
michael@0 430 }
michael@0 431 #else
michael@0 432 /* Platforms with native support for dependent windows (that's everyone
michael@0 433 but pre-Mac OS X, right?) know how to stack dependent windows. On these
michael@0 434 platforms, give the dependent window the same level as its parent,
michael@0 435 so we won't try to override the normal platform behaviour. */
michael@0 436 if ((aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT) && aParent)
michael@0 437 aParent->GetZLevel(&zLevel);
michael@0 438 #endif
michael@0 439
michael@0 440 return zLevel;
michael@0 441 }
michael@0 442
michael@0 443 #ifdef XP_WIN
michael@0 444 /*
michael@0 445 * Checks to see if any existing window is currently in fullscreen mode.
michael@0 446 */
michael@0 447 static bool
michael@0 448 CheckForFullscreenWindow()
michael@0 449 {
michael@0 450 nsCOMPtr<nsIWindowMediator> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID));
michael@0 451 if (!wm)
michael@0 452 return false;
michael@0 453
michael@0 454 nsCOMPtr<nsISimpleEnumerator> windowList;
michael@0 455 wm->GetXULWindowEnumerator(nullptr, getter_AddRefs(windowList));
michael@0 456 if (!windowList)
michael@0 457 return false;
michael@0 458
michael@0 459 for (;;) {
michael@0 460 bool more = false;
michael@0 461 windowList->HasMoreElements(&more);
michael@0 462 if (!more)
michael@0 463 return false;
michael@0 464
michael@0 465 nsCOMPtr<nsISupports> supportsWindow;
michael@0 466 windowList->GetNext(getter_AddRefs(supportsWindow));
michael@0 467 nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(supportsWindow));
michael@0 468 if (baseWin) {
michael@0 469 nsCOMPtr<nsIWidget> widget;
michael@0 470 baseWin->GetMainWidget(getter_AddRefs(widget));
michael@0 471 if (widget && widget->SizeMode() == nsSizeMode_Fullscreen) {
michael@0 472 return true;
michael@0 473 }
michael@0 474 }
michael@0 475 }
michael@0 476 return false;
michael@0 477 }
michael@0 478 #endif
michael@0 479
michael@0 480 /*
michael@0 481 * Just do the window-making part of CreateTopLevelWindow
michael@0 482 */
michael@0 483 nsresult
michael@0 484 nsAppShellService::JustCreateTopWindow(nsIXULWindow *aParent,
michael@0 485 nsIURI *aUrl,
michael@0 486 uint32_t aChromeMask,
michael@0 487 int32_t aInitialWidth,
michael@0 488 int32_t aInitialHeight,
michael@0 489 bool aIsHiddenWindow,
michael@0 490 nsWebShellWindow **aResult)
michael@0 491 {
michael@0 492 *aResult = nullptr;
michael@0 493 NS_ENSURE_STATE(!mXPCOMWillShutDown);
michael@0 494
michael@0 495 nsCOMPtr<nsIXULWindow> parent;
michael@0 496 if (aChromeMask & nsIWebBrowserChrome::CHROME_DEPENDENT)
michael@0 497 parent = aParent;
michael@0 498
michael@0 499 nsRefPtr<nsWebShellWindow> window = new nsWebShellWindow(aChromeMask);
michael@0 500 NS_ENSURE_TRUE(window, NS_ERROR_OUT_OF_MEMORY);
michael@0 501
michael@0 502 #ifdef XP_WIN
michael@0 503 // If the parent is currently fullscreen, tell the child to ignore persisted
michael@0 504 // full screen states. This way new browser windows open on top of fullscreen
michael@0 505 // windows normally.
michael@0 506 if (window && CheckForFullscreenWindow())
michael@0 507 window->IgnoreXULSizeMode(true);
michael@0 508 #endif
michael@0 509
michael@0 510 nsWidgetInitData widgetInitData;
michael@0 511
michael@0 512 if (aIsHiddenWindow)
michael@0 513 widgetInitData.mWindowType = eWindowType_invisible;
michael@0 514 else
michael@0 515 widgetInitData.mWindowType = aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG ?
michael@0 516 eWindowType_dialog : eWindowType_toplevel;
michael@0 517
michael@0 518 if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_POPUP)
michael@0 519 widgetInitData.mWindowType = eWindowType_popup;
michael@0 520
michael@0 521 if (aChromeMask & nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION)
michael@0 522 widgetInitData.mIsAnimationSuppressed = true;
michael@0 523
michael@0 524 if (aChromeMask & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW)
michael@0 525 widgetInitData.mRequireOffMainThreadCompositing = true;
michael@0 526
michael@0 527 #ifdef XP_MACOSX
michael@0 528 // Mac OS X sheet support
michael@0 529 // Adding CHROME_OPENAS_CHROME to sheetMask makes modal windows opened from
michael@0 530 // nsGlobalWindow::ShowModalDialog() be dialogs (not sheets), while modal
michael@0 531 // windows opened from nsPromptService::DoDialog() still are sheets. This
michael@0 532 // fixes bmo bug 395465 (see nsCocoaWindow::StandardCreate() and
michael@0 533 // nsCocoaWindow::SetModal()).
michael@0 534 uint32_t sheetMask = nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
michael@0 535 nsIWebBrowserChrome::CHROME_MODAL |
michael@0 536 nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
michael@0 537 if (parent &&
michael@0 538 (parent != mHiddenWindow && parent != mHiddenPrivateWindow) &&
michael@0 539 ((aChromeMask & sheetMask) == sheetMask)) {
michael@0 540 widgetInitData.mWindowType = eWindowType_sheet;
michael@0 541 }
michael@0 542 #endif
michael@0 543
michael@0 544 #if defined(XP_WIN)
michael@0 545 if (widgetInitData.mWindowType == eWindowType_toplevel ||
michael@0 546 widgetInitData.mWindowType == eWindowType_dialog)
michael@0 547 widgetInitData.clipChildren = true;
michael@0 548 #endif
michael@0 549
michael@0 550 // note default chrome overrides other OS chrome settings, but
michael@0 551 // not internal chrome
michael@0 552 if (aChromeMask & nsIWebBrowserChrome::CHROME_DEFAULT)
michael@0 553 widgetInitData.mBorderStyle = eBorderStyle_default;
michael@0 554 else if ((aChromeMask & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL)
michael@0 555 widgetInitData.mBorderStyle = eBorderStyle_all;
michael@0 556 else {
michael@0 557 widgetInitData.mBorderStyle = eBorderStyle_none; // assumes none == 0x00
michael@0 558 if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_BORDERS)
michael@0 559 widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_border);
michael@0 560 if (aChromeMask & nsIWebBrowserChrome::CHROME_TITLEBAR)
michael@0 561 widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_title);
michael@0 562 if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_CLOSE)
michael@0 563 widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_close);
michael@0 564 if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) {
michael@0 565 widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_resizeh);
michael@0 566 // only resizable windows get the maximize button (but not dialogs)
michael@0 567 if (!(aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG))
michael@0 568 widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_maximize);
michael@0 569 }
michael@0 570 // all windows (except dialogs) get minimize buttons and the system menu
michael@0 571 if (!(aChromeMask & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG))
michael@0 572 widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_minimize | eBorderStyle_menu);
michael@0 573 // but anyone can explicitly ask for a minimize button
michael@0 574 if (aChromeMask & nsIWebBrowserChrome::CHROME_WINDOW_MIN) {
michael@0 575 widgetInitData.mBorderStyle = static_cast<enum nsBorderStyle>(widgetInitData.mBorderStyle | eBorderStyle_minimize);
michael@0 576 }
michael@0 577 }
michael@0 578
michael@0 579 if (aInitialWidth == nsIAppShellService::SIZE_TO_CONTENT ||
michael@0 580 aInitialHeight == nsIAppShellService::SIZE_TO_CONTENT) {
michael@0 581 aInitialWidth = 1;
michael@0 582 aInitialHeight = 1;
michael@0 583 window->SetIntrinsicallySized(true);
michael@0 584 }
michael@0 585
michael@0 586 bool center = aChromeMask & nsIWebBrowserChrome::CHROME_CENTER_SCREEN;
michael@0 587
michael@0 588 nsCOMPtr<nsIXULChromeRegistry> reg =
michael@0 589 mozilla::services::GetXULChromeRegistryService();
michael@0 590 if (reg) {
michael@0 591 nsAutoCString package;
michael@0 592 package.AssignLiteral("global");
michael@0 593 bool isRTL = false;
michael@0 594 reg->IsLocaleRTL(package, &isRTL);
michael@0 595 widgetInitData.mRTL = isRTL;
michael@0 596 }
michael@0 597
michael@0 598 nsresult rv = window->Initialize(parent, center ? aParent : nullptr,
michael@0 599 aUrl, aInitialWidth, aInitialHeight,
michael@0 600 aIsHiddenWindow, widgetInitData);
michael@0 601
michael@0 602 NS_ENSURE_SUCCESS(rv, rv);
michael@0 603
michael@0 604 // Enforce the Private Browsing autoStart pref first.
michael@0 605 bool isPrivateBrowsingWindow =
michael@0 606 Preferences::GetBool("browser.privatebrowsing.autostart");
michael@0 607 if (aChromeMask & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW) {
michael@0 608 // Caller requested a private window
michael@0 609 isPrivateBrowsingWindow = true;
michael@0 610 }
michael@0 611 if (!isPrivateBrowsingWindow) {
michael@0 612 // Ensure that we propagate any existing private browsing status
michael@0 613 // from the parent, even if it will not actually be used
michael@0 614 // as a parent value.
michael@0 615 nsCOMPtr<nsIDOMWindow> domWin = do_GetInterface(aParent);
michael@0 616 nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(domWin);
michael@0 617 nsCOMPtr<nsILoadContext> parentContext = do_QueryInterface(webNav);
michael@0 618 if (parentContext) {
michael@0 619 isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing();
michael@0 620 }
michael@0 621 }
michael@0 622 nsCOMPtr<nsIDOMWindow> newDomWin =
michael@0 623 do_GetInterface(NS_ISUPPORTS_CAST(nsIBaseWindow*, window));
michael@0 624 nsCOMPtr<nsIWebNavigation> newWebNav = do_GetInterface(newDomWin);
michael@0 625 nsCOMPtr<nsILoadContext> thisContext = do_GetInterface(newWebNav);
michael@0 626 if (thisContext) {
michael@0 627 thisContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
michael@0 628 }
michael@0 629
michael@0 630 window.swap(*aResult); // transfer reference
michael@0 631 if (parent)
michael@0 632 parent->AddChildWindow(*aResult);
michael@0 633
michael@0 634 if (center)
michael@0 635 rv = (*aResult)->Center(parent, parent ? false : true, false);
michael@0 636
michael@0 637 return rv;
michael@0 638 }
michael@0 639
michael@0 640 NS_IMETHODIMP
michael@0 641 nsAppShellService::GetHiddenWindow(nsIXULWindow **aWindow)
michael@0 642 {
michael@0 643 NS_ENSURE_ARG_POINTER(aWindow);
michael@0 644
michael@0 645 *aWindow = mHiddenWindow;
michael@0 646 NS_IF_ADDREF(*aWindow);
michael@0 647 return *aWindow ? NS_OK : NS_ERROR_FAILURE;
michael@0 648 }
michael@0 649
michael@0 650 NS_IMETHODIMP
michael@0 651 nsAppShellService::GetHiddenDOMWindow(nsIDOMWindow **aWindow)
michael@0 652 {
michael@0 653 nsresult rv;
michael@0 654 nsCOMPtr<nsIDocShell> docShell;
michael@0 655 NS_ENSURE_TRUE(mHiddenWindow, NS_ERROR_FAILURE);
michael@0 656
michael@0 657 rv = mHiddenWindow->GetDocShell(getter_AddRefs(docShell));
michael@0 658 NS_ENSURE_SUCCESS(rv, rv);
michael@0 659
michael@0 660 nsCOMPtr<nsIDOMWindow> hiddenDOMWindow(do_GetInterface(docShell, &rv));
michael@0 661 NS_ENSURE_SUCCESS(rv, rv);
michael@0 662
michael@0 663 *aWindow = hiddenDOMWindow;
michael@0 664 NS_IF_ADDREF(*aWindow);
michael@0 665 return NS_OK;
michael@0 666 }
michael@0 667
michael@0 668 NS_IMETHODIMP
michael@0 669 nsAppShellService::GetHiddenPrivateWindow(nsIXULWindow **aWindow)
michael@0 670 {
michael@0 671 NS_ENSURE_ARG_POINTER(aWindow);
michael@0 672
michael@0 673 EnsurePrivateHiddenWindow();
michael@0 674
michael@0 675 *aWindow = mHiddenPrivateWindow;
michael@0 676 NS_IF_ADDREF(*aWindow);
michael@0 677 return *aWindow ? NS_OK : NS_ERROR_FAILURE;
michael@0 678 }
michael@0 679
michael@0 680 NS_IMETHODIMP
michael@0 681 nsAppShellService::GetHiddenPrivateDOMWindow(nsIDOMWindow **aWindow)
michael@0 682 {
michael@0 683 EnsurePrivateHiddenWindow();
michael@0 684
michael@0 685 nsresult rv;
michael@0 686 nsCOMPtr<nsIDocShell> docShell;
michael@0 687 NS_ENSURE_TRUE(mHiddenPrivateWindow, NS_ERROR_FAILURE);
michael@0 688
michael@0 689 rv = mHiddenPrivateWindow->GetDocShell(getter_AddRefs(docShell));
michael@0 690 NS_ENSURE_SUCCESS(rv, rv);
michael@0 691
michael@0 692 nsCOMPtr<nsIDOMWindow> hiddenPrivateDOMWindow(do_GetInterface(docShell, &rv));
michael@0 693 NS_ENSURE_SUCCESS(rv, rv);
michael@0 694
michael@0 695 *aWindow = hiddenPrivateDOMWindow;
michael@0 696 NS_IF_ADDREF(*aWindow);
michael@0 697 return NS_OK;
michael@0 698 }
michael@0 699
michael@0 700 NS_IMETHODIMP
michael@0 701 nsAppShellService::GetHasHiddenPrivateWindow(bool* aHasPrivateWindow)
michael@0 702 {
michael@0 703 NS_ENSURE_ARG_POINTER(aHasPrivateWindow);
michael@0 704
michael@0 705 *aHasPrivateWindow = !!mHiddenPrivateWindow;
michael@0 706 return NS_OK;
michael@0 707 }
michael@0 708
michael@0 709 NS_IMETHODIMP
michael@0 710 nsAppShellService::GetHiddenWindowAndJSContext(nsIDOMWindow **aWindow,
michael@0 711 JSContext **aJSContext)
michael@0 712 {
michael@0 713 nsresult rv = NS_OK;
michael@0 714 if ( aWindow && aJSContext ) {
michael@0 715 *aWindow = nullptr;
michael@0 716 *aJSContext = nullptr;
michael@0 717
michael@0 718 if ( mHiddenWindow ) {
michael@0 719 // Convert hidden window to nsIDOMWindow and extract its JSContext.
michael@0 720 do {
michael@0 721 // 1. Get doc for hidden window.
michael@0 722 nsCOMPtr<nsIDocShell> docShell;
michael@0 723 rv = mHiddenWindow->GetDocShell(getter_AddRefs(docShell));
michael@0 724 if (NS_FAILED(rv)) break;
michael@0 725
michael@0 726 // 2. Convert that to an nsIDOMWindow.
michael@0 727 nsCOMPtr<nsIDOMWindow> hiddenDOMWindow(do_GetInterface(docShell));
michael@0 728 if(!hiddenDOMWindow) break;
michael@0 729
michael@0 730 // 3. Get script global object for the window.
michael@0 731 nsCOMPtr<nsIScriptGlobalObject> sgo;
michael@0 732 sgo = do_QueryInterface( hiddenDOMWindow );
michael@0 733 if (!sgo) { rv = NS_ERROR_FAILURE; break; }
michael@0 734
michael@0 735 // 4. Get script context from that.
michael@0 736 nsIScriptContext *scriptContext = sgo->GetContext();
michael@0 737 if (!scriptContext) { rv = NS_ERROR_FAILURE; break; }
michael@0 738
michael@0 739 // 5. Get JSContext from the script context.
michael@0 740 JSContext *jsContext = scriptContext->GetNativeContext();
michael@0 741 if (!jsContext) { rv = NS_ERROR_FAILURE; break; }
michael@0 742
michael@0 743 // Now, give results to caller.
michael@0 744 *aWindow = hiddenDOMWindow.get();
michael@0 745 NS_IF_ADDREF( *aWindow );
michael@0 746 *aJSContext = jsContext;
michael@0 747 } while (0);
michael@0 748 } else {
michael@0 749 rv = NS_ERROR_FAILURE;
michael@0 750 }
michael@0 751 } else {
michael@0 752 rv = NS_ERROR_NULL_POINTER;
michael@0 753 }
michael@0 754 return rv;
michael@0 755 }
michael@0 756
michael@0 757 NS_IMETHODIMP
michael@0 758 nsAppShellService::GetApplicationProvidedHiddenWindow(bool* aAPHW)
michael@0 759 {
michael@0 760 *aAPHW = mApplicationProvidedHiddenWindow;
michael@0 761 return NS_OK;
michael@0 762 }
michael@0 763
michael@0 764 /*
michael@0 765 * Register a new top level window (created elsewhere)
michael@0 766 */
michael@0 767 NS_IMETHODIMP
michael@0 768 nsAppShellService::RegisterTopLevelWindow(nsIXULWindow* aWindow)
michael@0 769 {
michael@0 770 NS_ENSURE_ARG_POINTER(aWindow);
michael@0 771
michael@0 772 nsCOMPtr<nsIDocShell> docShell;
michael@0 773 aWindow->GetDocShell(getter_AddRefs(docShell));
michael@0 774 nsCOMPtr<nsPIDOMWindow> domWindow(do_GetInterface(docShell));
michael@0 775 NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
michael@0 776 domWindow->SetInitialPrincipalToSubject();
michael@0 777
michael@0 778 // tell the window mediator about the new window
michael@0 779 nsCOMPtr<nsIWindowMediator> mediator
michael@0 780 ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID) );
michael@0 781 NS_ASSERTION(mediator, "Couldn't get window mediator.");
michael@0 782
michael@0 783 if (mediator)
michael@0 784 mediator->RegisterWindow(aWindow);
michael@0 785
michael@0 786 // tell the window watcher about the new window
michael@0 787 nsCOMPtr<nsPIWindowWatcher> wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID) );
michael@0 788 NS_ASSERTION(wwatcher, "No windowwatcher?");
michael@0 789 if (wwatcher && domWindow) {
michael@0 790 wwatcher->AddWindow(domWindow, 0);
michael@0 791 }
michael@0 792
michael@0 793 // an ongoing attempt to quit is stopped by a newly opened window
michael@0 794 nsCOMPtr<nsIObserverService> obssvc =
michael@0 795 do_GetService("@mozilla.org/observer-service;1");
michael@0 796 NS_ASSERTION(obssvc, "Couldn't get observer service.");
michael@0 797
michael@0 798 if (obssvc)
michael@0 799 obssvc->NotifyObservers(aWindow, "xul-window-registered", nullptr);
michael@0 800
michael@0 801 return NS_OK;
michael@0 802 }
michael@0 803
michael@0 804
michael@0 805 NS_IMETHODIMP
michael@0 806 nsAppShellService::UnregisterTopLevelWindow(nsIXULWindow* aWindow)
michael@0 807 {
michael@0 808 if (mXPCOMShuttingDown) {
michael@0 809 /* return an error code in order to:
michael@0 810 - avoid doing anything with other member variables while we are in
michael@0 811 the destructor
michael@0 812 - notify the caller not to release the AppShellService after
michael@0 813 unregistering the window
michael@0 814 (we don't want to be deleted twice consecutively to
michael@0 815 mHiddenWindow->Destroy() in our destructor)
michael@0 816 */
michael@0 817 return NS_ERROR_FAILURE;
michael@0 818 }
michael@0 819
michael@0 820 NS_ENSURE_ARG_POINTER(aWindow);
michael@0 821
michael@0 822 if (aWindow == mHiddenWindow) {
michael@0 823 // CreateHiddenWindow() does not register the window, so we're done.
michael@0 824 return NS_OK;
michael@0 825 }
michael@0 826 if (aWindow == mHiddenPrivateWindow) {
michael@0 827 // CreateHiddenWindow() does not register the window, so we're done.
michael@0 828 return NS_OK;
michael@0 829 }
michael@0 830
michael@0 831 // tell the window mediator
michael@0 832 nsCOMPtr<nsIWindowMediator> mediator
michael@0 833 ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID) );
michael@0 834 NS_ASSERTION(mediator, "Couldn't get window mediator. Doing xpcom shutdown?");
michael@0 835
michael@0 836 if (mediator)
michael@0 837 mediator->UnregisterWindow(aWindow);
michael@0 838
michael@0 839 // tell the window watcher
michael@0 840 nsCOMPtr<nsPIWindowWatcher> wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID) );
michael@0 841 NS_ASSERTION(wwatcher, "Couldn't get windowwatcher, doing xpcom shutdown?");
michael@0 842 if (wwatcher) {
michael@0 843 nsCOMPtr<nsIDocShell> docShell;
michael@0 844 aWindow->GetDocShell(getter_AddRefs(docShell));
michael@0 845 if (docShell) {
michael@0 846 nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(docShell));
michael@0 847 if (domWindow)
michael@0 848 wwatcher->RemoveWindow(domWindow);
michael@0 849 }
michael@0 850 }
michael@0 851
michael@0 852 return NS_OK;
michael@0 853 }
michael@0 854
michael@0 855
michael@0 856 NS_IMETHODIMP
michael@0 857 nsAppShellService::Observe(nsISupports* aSubject, const char *aTopic,
michael@0 858 const char16_t *aData)
michael@0 859 {
michael@0 860 if (!strcmp(aTopic, "xpcom-will-shutdown")) {
michael@0 861 mXPCOMWillShutDown = true;
michael@0 862 } else if (!strcmp(aTopic, "xpcom-shutdown")) {
michael@0 863 mXPCOMShuttingDown = true;
michael@0 864 if (mHiddenWindow) {
michael@0 865 mHiddenWindow->Destroy();
michael@0 866 }
michael@0 867 if (mHiddenPrivateWindow) {
michael@0 868 mHiddenPrivateWindow->Destroy();
michael@0 869 }
michael@0 870 } else {
michael@0 871 NS_ERROR("Unexpected observer topic!");
michael@0 872 }
michael@0 873
michael@0 874 return NS_OK;
michael@0 875 }
michael@0 876
michael@0 877 NS_IMETHODIMP
michael@0 878 nsAppShellService::StartEventLoopLagTracking(bool* aResult)
michael@0 879 {
michael@0 880 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
michael@0 881 *aResult = mozilla::InitEventTracing(true);
michael@0 882 #endif
michael@0 883 return NS_OK;
michael@0 884 }
michael@0 885
michael@0 886 NS_IMETHODIMP
michael@0 887 nsAppShellService::StopEventLoopLagTracking()
michael@0 888 {
michael@0 889 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
michael@0 890 mozilla::ShutdownEventTracing();
michael@0 891 #endif
michael@0 892 return NS_OK;
michael@0 893 }

mercurial