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 +}