Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 | } |