1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsIAppShellService.h"
8 #include "nsIComponentManager.h"
10 #include "nsNetUtil.h"
11 #include "nsIServiceManager.h"
12 #include "nsIObserverService.h"
13 #include "nsIObserver.h"
14 #include "nsIXPConnect.h"
15 #include "nsIXULRuntime.h"
17 #include "nsIWindowMediator.h"
18 #include "nsIWindowWatcher.h"
19 #include "nsPIWindowWatcher.h"
20 #include "nsIDOMWindow.h"
21 #include "nsPIDOMWindow.h"
22 #include "nsWebShellWindow.h"
26 #include "nsWidgetInitData.h"
27 #include "nsWidgetsCID.h"
28 #include "nsIWidget.h"
29 #include "nsIRequestObserver.h"
31 /* For implementing GetHiddenWindowAndJSContext */
32 #include "nsIScriptGlobalObject.h"
33 #include "nsIScriptContext.h"
35 #include "nsAppShellService.h"
36 #include "nsISupportsPrimitives.h"
37 #include "nsIChromeRegistry.h"
38 #include "nsILoadContext.h"
39 #include "nsIWebNavigation.h"
41 #include "mozilla/Attributes.h"
42 #include "mozilla/Preferences.h"
43 #include "mozilla/StartupTimeline.h"
45 #include "nsEmbedCID.h"
46 #include "nsIWebBrowser.h"
47 #include "nsIDocShell.h"
49 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
50 #include "EventTracer.h"
53 using namespace mozilla
;
55 // Default URL for the hidden window, can be overridden by a pref on Mac
56 #define DEFAULT_HIDDENWINDOW_URL "resource://gre-resources/hiddenWindow.html"
60 nsAppShellService::nsAppShellService() :
61 mXPCOMWillShutDown(false),
62 mXPCOMShuttingDown(false),
64 mApplicationProvidedHiddenWindow(false)
66 nsCOMPtr
<nsIObserverService
> obs
67 (do_GetService("@mozilla.org/observer-service;1"));
70 obs
->AddObserver(this, "xpcom-will-shutdown", false);
71 obs
->AddObserver(this, "xpcom-shutdown", false);
75 nsAppShellService::~nsAppShellService()
81 * Implement the nsISupports methods...
83 NS_IMPL_ISUPPORTS(nsAppShellService
,
88 nsAppShellService::CreateHiddenWindow()
90 return CreateHiddenWindowHelper(false);
94 nsAppShellService::EnsurePrivateHiddenWindow()
96 if (!mHiddenPrivateWindow
) {
97 CreateHiddenWindowHelper(true);
102 nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate
)
105 int32_t initialHeight
= 100, initialWidth
= 100;
108 uint32_t chromeMask
= 0;
109 nsAdoptingCString prefVal
=
110 Preferences::GetCString("browser.hiddenWindowChromeURL");
111 const char* hiddenWindowURL
= prefVal
.get() ? prefVal
.get() : DEFAULT_HIDDENWINDOW_URL
;
113 hiddenWindowURL
= DEFAULT_HIDDENWINDOW_URL
;
115 mApplicationProvidedHiddenWindow
= prefVal
.get() ? true : false;
118 static const char hiddenWindowURL
[] = DEFAULT_HIDDENWINDOW_URL
;
119 uint32_t chromeMask
= nsIWebBrowserChrome::CHROME_ALL
;
122 nsCOMPtr
<nsIURI
> url
;
123 rv
= NS_NewURI(getter_AddRefs(url
), hiddenWindowURL
);
124 NS_ENSURE_SUCCESS(rv
, rv
);
126 nsRefPtr
<nsWebShellWindow
> newWindow
;
128 rv
= JustCreateTopWindow(nullptr, url
,
129 chromeMask
, initialWidth
, initialHeight
,
130 true, nullptr, getter_AddRefs(newWindow
));
131 NS_ENSURE_SUCCESS(rv
, rv
);
133 mHiddenWindow
.swap(newWindow
);
135 // Create the hidden private window
136 chromeMask
|= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
;
138 rv
= JustCreateTopWindow(nullptr, url
,
139 chromeMask
, initialWidth
, initialHeight
,
140 true, nullptr, getter_AddRefs(newWindow
));
141 NS_ENSURE_SUCCESS(rv
, rv
);
143 nsCOMPtr
<nsIDocShell
> docShell
;
144 newWindow
->GetDocShell(getter_AddRefs(docShell
));
146 docShell
->SetAffectPrivateSessionLifetime(false);
149 mHiddenPrivateWindow
.swap(newWindow
);
152 // RegisterTopLevelWindow(newWindow); -- Mac only
158 nsAppShellService::DestroyHiddenWindow()
161 mHiddenWindow
->Destroy();
163 mHiddenWindow
= nullptr;
166 if (mHiddenPrivateWindow
) {
167 mHiddenPrivateWindow
->Destroy();
169 mHiddenPrivateWindow
= nullptr;
176 * Create a new top level window and display the given URL within it...
179 nsAppShellService::CreateTopLevelWindow(nsIXULWindow
*aParent
,
181 uint32_t aChromeMask
,
182 int32_t aInitialWidth
,
183 int32_t aInitialHeight
,
184 nsITabParent
*aOpeningTab
,
185 nsIXULWindow
**aResult
)
190 StartupTimeline::RecordOnce(StartupTimeline::CREATE_TOP_LEVEL_WINDOW
);
192 nsWebShellWindow
*newWindow
= nullptr;
193 rv
= JustCreateTopWindow(aParent
, aUrl
,
194 aChromeMask
, aInitialWidth
, aInitialHeight
,
195 false, aOpeningTab
, &newWindow
); // addrefs
197 *aResult
= newWindow
; // transfer ref
199 if (NS_SUCCEEDED(rv
)) {
200 // the addref resulting from this is the owning addref for this window
201 RegisterTopLevelWindow(*aResult
);
202 nsCOMPtr
<nsIXULWindow
> parent
;
203 if (aChromeMask
& nsIWebBrowserChrome::CHROME_DEPENDENT
)
205 (*aResult
)->SetZLevel(CalculateWindowZLevel(parent
, aChromeMask
));
212 * This class provides a stub implementation of nsIWebBrowserChrome2, as needed
213 * by nsAppShellService::CreateWindowlessBrowser
215 class WebBrowserChrome2Stub
: public nsIWebBrowserChrome2
,
216 public nsIInterfaceRequestor
,
217 public nsSupportsWeakReference
{
219 virtual ~WebBrowserChrome2Stub() {}
222 NS_DECL_NSIWEBBROWSERCHROME
223 NS_DECL_NSIWEBBROWSERCHROME2
224 NS_DECL_NSIINTERFACEREQUESTOR
227 NS_INTERFACE_MAP_BEGIN(WebBrowserChrome2Stub
)
228 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIWebBrowserChrome
)
229 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome
)
230 NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome2
)
231 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
232 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
235 NS_IMPL_ADDREF(WebBrowserChrome2Stub
)
236 NS_IMPL_RELEASE(WebBrowserChrome2Stub
)
239 WebBrowserChrome2Stub::SetStatus(uint32_t aStatusType
, const char16_t
* aStatus
)
245 WebBrowserChrome2Stub::GetWebBrowser(nsIWebBrowser
** aWebBrowser
)
247 NS_NOTREACHED("WebBrowserChrome2Stub::GetWebBrowser is not supported");
248 return NS_ERROR_NOT_IMPLEMENTED
;
252 WebBrowserChrome2Stub::SetWebBrowser(nsIWebBrowser
* aWebBrowser
)
254 NS_NOTREACHED("WebBrowserChrome2Stub::SetWebBrowser is not supported");
255 return NS_ERROR_NOT_IMPLEMENTED
;
259 WebBrowserChrome2Stub::GetChromeFlags(uint32_t* aChromeFlags
)
266 WebBrowserChrome2Stub::SetChromeFlags(uint32_t aChromeFlags
)
268 NS_NOTREACHED("WebBrowserChrome2Stub::SetChromeFlags is not supported");
269 return NS_ERROR_NOT_IMPLEMENTED
;
273 WebBrowserChrome2Stub::DestroyBrowserWindow()
275 NS_NOTREACHED("WebBrowserChrome2Stub::DestroyBrowserWindow is not supported");
276 return NS_ERROR_NOT_IMPLEMENTED
;
280 WebBrowserChrome2Stub::SizeBrowserTo(int32_t aCX
, int32_t aCY
)
282 NS_NOTREACHED("WebBrowserChrome2Stub::SizeBrowserTo is not supported");
283 return NS_ERROR_NOT_IMPLEMENTED
;
287 WebBrowserChrome2Stub::ShowAsModal()
289 NS_NOTREACHED("WebBrowserChrome2Stub::ShowAsModal is not supported");
290 return NS_ERROR_NOT_IMPLEMENTED
;
294 WebBrowserChrome2Stub::IsWindowModal(bool* aResult
)
301 WebBrowserChrome2Stub::ExitModalEventLoop(nsresult aStatus
)
303 NS_NOTREACHED("WebBrowserChrome2Stub::ExitModalEventLoop is not supported");
304 return NS_ERROR_NOT_IMPLEMENTED
;
308 WebBrowserChrome2Stub::SetStatusWithContext(uint32_t aStatusType
,
309 const nsAString
& aStatusText
,
310 nsISupports
* aStatusContext
)
316 WebBrowserChrome2Stub::GetInterface(const nsIID
& aIID
, void **aSink
)
318 return QueryInterface(aIID
, aSink
);
321 // This is the "stub" we return from CreateWindowlessBrowser - it exists
322 // purely to keep a strong reference to the browser and the container to
323 // prevent the container being collected while the stub remains alive.
324 class WindowlessBrowserStub MOZ_FINAL
: public nsIWebNavigation
,
325 public nsIInterfaceRequestor
{
327 WindowlessBrowserStub(nsIWebBrowser
*aBrowser
, nsISupports
*aContainer
) {
329 mWebNavigation
= do_QueryInterface(aBrowser
);
330 mInterfaceRequestor
= do_QueryInterface(aBrowser
);
331 mContainer
= aContainer
;
334 NS_FORWARD_NSIWEBNAVIGATION(mWebNavigation
->)
335 NS_FORWARD_NSIINTERFACEREQUESTOR(mInterfaceRequestor
->)
337 ~WindowlessBrowserStub() {}
338 nsCOMPtr
<nsIWebBrowser
> mBrowser
;
339 nsCOMPtr
<nsIWebNavigation
> mWebNavigation
;
340 nsCOMPtr
<nsIInterfaceRequestor
> mInterfaceRequestor
;
341 // we don't use the container but just hold a reference to it.
342 nsCOMPtr
<nsISupports
> mContainer
;
345 NS_INTERFACE_MAP_BEGIN(WindowlessBrowserStub
)
346 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIWebNavigation
)
347 NS_INTERFACE_MAP_ENTRY(nsIWebNavigation
)
348 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
351 NS_IMPL_ADDREF(WindowlessBrowserStub
)
352 NS_IMPL_RELEASE(WindowlessBrowserStub
)
356 nsAppShellService::CreateWindowlessBrowser(bool aIsChrome
, nsIWebNavigation
**aResult
)
358 /* First, we create an instance of nsWebBrowser. Instances of this class have
359 * an associated doc shell, which is what we're interested in.
361 nsCOMPtr
<nsIWebBrowser
> browser
= do_CreateInstance(NS_WEBBROWSER_CONTRACTID
);
363 NS_ERROR("Couldn't create instance of nsWebBrowser!");
364 return NS_ERROR_FAILURE
;
367 /* Next, we set the container window for our instance of nsWebBrowser. Since
368 * we don't actually have a window, we instead set the container window to be
369 * an instance of WebBrowserChrome2Stub, which provides a stub implementation
370 * of nsIWebBrowserChrome2.
372 nsRefPtr
<WebBrowserChrome2Stub
> stub
= new WebBrowserChrome2Stub();
374 NS_ERROR("Couldn't create instance of WebBrowserChrome2Stub!");
375 return NS_ERROR_FAILURE
;
377 browser
->SetContainerWindow(stub
);
379 nsCOMPtr
<nsIWebNavigation
> navigation
= do_QueryInterface(browser
);
381 nsCOMPtr
<nsIDocShellTreeItem
> item
= do_QueryInterface(navigation
);
382 item
->SetItemType(aIsChrome
? nsIDocShellTreeItem::typeChromeWrapper
383 : nsIDocShellTreeItem::typeContentWrapper
);
385 /* A windowless web browser doesn't have an associated OS level window. To
386 * accomplish this, we initialize the window associated with our instance of
387 * nsWebBrowser with an instance of PuppetWidget, which provides a stub
388 * implementation of nsIWidget.
390 nsCOMPtr
<nsIWidget
> widget
= nsIWidget::CreatePuppetWidget(nullptr);
392 NS_ERROR("Couldn't create instance of PuppetWidget");
393 return NS_ERROR_FAILURE
;
395 widget
->Create(nullptr, 0, nsIntRect(nsIntPoint(0, 0), nsIntSize(0, 0)),
397 nsCOMPtr
<nsIBaseWindow
> window
= do_QueryInterface(navigation
);
398 window
->InitWindow(0, widget
, 0, 0, 0, 0);
401 nsISupports
*isstub
= NS_ISUPPORTS_CAST(nsIWebBrowserChrome2
*, stub
);
402 nsRefPtr
<nsIWebNavigation
> result
= new WindowlessBrowserStub(browser
, isstub
);
403 nsCOMPtr
<nsIDocShell
> docshell
= do_GetInterface(result
);
404 docshell
->SetInvisible(true);
406 result
.forget(aResult
);
411 nsAppShellService::CalculateWindowZLevel(nsIXULWindow
*aParent
,
412 uint32_t aChromeMask
)
416 zLevel
= nsIXULWindow::normalZ
;
417 if (aChromeMask
& nsIWebBrowserChrome::CHROME_WINDOW_RAISED
)
418 zLevel
= nsIXULWindow::raisedZ
;
419 else if (aChromeMask
& nsIWebBrowserChrome::CHROME_WINDOW_LOWERED
)
420 zLevel
= nsIXULWindow::loweredZ
;
423 /* Platforms on which modal windows are always application-modal, not
424 window-modal (that's just the Mac, right?) want modal windows to
425 be stacked on top of everyone else.
427 On Mac OS X, bind modality to parent window instead of app (ala Mac OS 9)
429 uint32_t modalDepMask
= nsIWebBrowserChrome::CHROME_MODAL
|
430 nsIWebBrowserChrome::CHROME_DEPENDENT
;
431 if (aParent
&& (aChromeMask
& modalDepMask
)) {
432 aParent
->GetZLevel(&zLevel
);
435 /* Platforms with native support for dependent windows (that's everyone
436 but pre-Mac OS X, right?) know how to stack dependent windows. On these
437 platforms, give the dependent window the same level as its parent,
438 so we won't try to override the normal platform behaviour. */
439 if ((aChromeMask
& nsIWebBrowserChrome::CHROME_DEPENDENT
) && aParent
)
440 aParent
->GetZLevel(&zLevel
);
448 * Checks to see if any existing window is currently in fullscreen mode.
451 CheckForFullscreenWindow()
453 nsCOMPtr
<nsIWindowMediator
> wm(do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
));
457 nsCOMPtr
<nsISimpleEnumerator
> windowList
;
458 wm
->GetXULWindowEnumerator(nullptr, getter_AddRefs(windowList
));
464 windowList
->HasMoreElements(&more
);
468 nsCOMPtr
<nsISupports
> supportsWindow
;
469 windowList
->GetNext(getter_AddRefs(supportsWindow
));
470 nsCOMPtr
<nsIBaseWindow
> baseWin(do_QueryInterface(supportsWindow
));
472 nsCOMPtr
<nsIWidget
> widget
;
473 baseWin
->GetMainWidget(getter_AddRefs(widget
));
474 if (widget
&& widget
->SizeMode() == nsSizeMode_Fullscreen
) {
484 * Just do the window-making part of CreateTopLevelWindow
487 nsAppShellService::JustCreateTopWindow(nsIXULWindow
*aParent
,
489 uint32_t aChromeMask
,
490 int32_t aInitialWidth
,
491 int32_t aInitialHeight
,
492 bool aIsHiddenWindow
,
493 nsITabParent
*aOpeningTab
,
494 nsWebShellWindow
**aResult
)
497 NS_ENSURE_STATE(!mXPCOMWillShutDown
);
499 nsCOMPtr
<nsIXULWindow
> parent
;
500 if (aChromeMask
& nsIWebBrowserChrome::CHROME_DEPENDENT
)
503 nsRefPtr
<nsWebShellWindow
> window
= new nsWebShellWindow(aChromeMask
);
504 NS_ENSURE_TRUE(window
, NS_ERROR_OUT_OF_MEMORY
);
507 // If the parent is currently fullscreen, tell the child to ignore persisted
508 // full screen states. This way new browser windows open on top of fullscreen
510 if (window
&& CheckForFullscreenWindow())
511 window
->IgnoreXULSizeMode(true);
514 nsWidgetInitData widgetInitData
;
517 widgetInitData
.mWindowType
= eWindowType_invisible
;
519 widgetInitData
.mWindowType
= aChromeMask
& nsIWebBrowserChrome::CHROME_OPENAS_DIALOG
?
520 eWindowType_dialog
: eWindowType_toplevel
;
522 if (aChromeMask
& nsIWebBrowserChrome::CHROME_WINDOW_POPUP
)
523 widgetInitData
.mWindowType
= eWindowType_popup
;
525 if (aChromeMask
& nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION
)
526 widgetInitData
.mIsAnimationSuppressed
= true;
528 if (aChromeMask
& nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
)
529 widgetInitData
.mRequireOffMainThreadCompositing
= true;
532 // Mac OS X sheet support
533 // Adding CHROME_OPENAS_CHROME to sheetMask makes modal windows opened from
534 // nsGlobalWindow::ShowModalDialog() be dialogs (not sheets), while modal
535 // windows opened from nsPromptService::DoDialog() still are sheets. This
536 // fixes bmo bug 395465 (see nsCocoaWindow::StandardCreate() and
537 // nsCocoaWindow::SetModal()).
538 uint32_t sheetMask
= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG
|
539 nsIWebBrowserChrome::CHROME_MODAL
|
540 nsIWebBrowserChrome::CHROME_OPENAS_CHROME
;
542 (parent
!= mHiddenWindow
&& parent
!= mHiddenPrivateWindow
) &&
543 ((aChromeMask
& sheetMask
) == sheetMask
)) {
544 widgetInitData
.mWindowType
= eWindowType_sheet
;
549 if (widgetInitData
.mWindowType
== eWindowType_toplevel
||
550 widgetInitData
.mWindowType
== eWindowType_dialog
)
551 widgetInitData
.clipChildren
= true;
554 // note default chrome overrides other OS chrome settings, but
555 // not internal chrome
556 if (aChromeMask
& nsIWebBrowserChrome::CHROME_DEFAULT
)
557 widgetInitData
.mBorderStyle
= eBorderStyle_default
;
558 else if ((aChromeMask
& nsIWebBrowserChrome::CHROME_ALL
) == nsIWebBrowserChrome::CHROME_ALL
)
559 widgetInitData
.mBorderStyle
= eBorderStyle_all
;
561 widgetInitData
.mBorderStyle
= eBorderStyle_none
; // assumes none == 0x00
562 if (aChromeMask
& nsIWebBrowserChrome::CHROME_WINDOW_BORDERS
)
563 widgetInitData
.mBorderStyle
= static_cast<enum nsBorderStyle
>(widgetInitData
.mBorderStyle
| eBorderStyle_border
);
564 if (aChromeMask
& nsIWebBrowserChrome::CHROME_TITLEBAR
)
565 widgetInitData
.mBorderStyle
= static_cast<enum nsBorderStyle
>(widgetInitData
.mBorderStyle
| eBorderStyle_title
);
566 if (aChromeMask
& nsIWebBrowserChrome::CHROME_WINDOW_CLOSE
)
567 widgetInitData
.mBorderStyle
= static_cast<enum nsBorderStyle
>(widgetInitData
.mBorderStyle
| eBorderStyle_close
);
568 if (aChromeMask
& nsIWebBrowserChrome::CHROME_WINDOW_RESIZE
) {
569 widgetInitData
.mBorderStyle
= static_cast<enum nsBorderStyle
>(widgetInitData
.mBorderStyle
| eBorderStyle_resizeh
);
570 // only resizable windows get the maximize button (but not dialogs)
571 if (!(aChromeMask
& nsIWebBrowserChrome::CHROME_OPENAS_DIALOG
))
572 widgetInitData
.mBorderStyle
= static_cast<enum nsBorderStyle
>(widgetInitData
.mBorderStyle
| eBorderStyle_maximize
);
574 // all windows (except dialogs) get minimize buttons and the system menu
575 if (!(aChromeMask
& nsIWebBrowserChrome::CHROME_OPENAS_DIALOG
))
576 widgetInitData
.mBorderStyle
= static_cast<enum nsBorderStyle
>(widgetInitData
.mBorderStyle
| eBorderStyle_minimize
| eBorderStyle_menu
);
577 // but anyone can explicitly ask for a minimize button
578 if (aChromeMask
& nsIWebBrowserChrome::CHROME_WINDOW_MIN
) {
579 widgetInitData
.mBorderStyle
= static_cast<enum nsBorderStyle
>(widgetInitData
.mBorderStyle
| eBorderStyle_minimize
);
583 if (aInitialWidth
== nsIAppShellService::SIZE_TO_CONTENT
||
584 aInitialHeight
== nsIAppShellService::SIZE_TO_CONTENT
) {
587 window
->SetIntrinsicallySized(true);
590 bool center
= aChromeMask
& nsIWebBrowserChrome::CHROME_CENTER_SCREEN
;
592 nsCOMPtr
<nsIXULChromeRegistry
> reg
=
593 mozilla::services::GetXULChromeRegistryService();
595 nsAutoCString package
;
596 package
.AssignLiteral("global");
598 reg
->IsLocaleRTL(package
, &isRTL
);
599 widgetInitData
.mRTL
= isRTL
;
602 nsresult rv
= window
->Initialize(parent
, center
? aParent
: nullptr,
603 aUrl
, aInitialWidth
, aInitialHeight
,
604 aIsHiddenWindow
, aOpeningTab
, widgetInitData
);
606 NS_ENSURE_SUCCESS(rv
, rv
);
608 // Enforce the Private Browsing autoStart pref first.
609 bool isPrivateBrowsingWindow
=
610 Preferences::GetBool("browser.privatebrowsing.autostart");
611 bool isUsingRemoteTabs
= mozilla::BrowserTabsRemoteAutostart();
613 if (aChromeMask
& nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW
) {
614 // Caller requested a private window
615 isPrivateBrowsingWindow
= true;
617 if (aChromeMask
& nsIWebBrowserChrome::CHROME_REMOTE_WINDOW
) {
618 isUsingRemoteTabs
= true;
621 nsCOMPtr
<nsIDOMWindow
> domWin
= do_GetInterface(aParent
);
622 nsCOMPtr
<nsIWebNavigation
> webNav
= do_GetInterface(domWin
);
623 nsCOMPtr
<nsILoadContext
> parentContext
= do_QueryInterface(webNav
);
625 if (!isPrivateBrowsingWindow
&& parentContext
) {
626 // Ensure that we propagate any existing private browsing status
627 // from the parent, even if it will not actually be used
628 // as a parent value.
629 isPrivateBrowsingWindow
= parentContext
->UsePrivateBrowsing();
633 isUsingRemoteTabs
= parentContext
->UseRemoteTabs();
636 nsCOMPtr
<nsIDOMWindow
> newDomWin
=
637 do_GetInterface(NS_ISUPPORTS_CAST(nsIBaseWindow
*, window
));
638 nsCOMPtr
<nsIWebNavigation
> newWebNav
= do_GetInterface(newDomWin
);
639 nsCOMPtr
<nsILoadContext
> thisContext
= do_GetInterface(newWebNav
);
641 thisContext
->SetPrivateBrowsing(isPrivateBrowsingWindow
);
642 thisContext
->SetRemoteTabs(isUsingRemoteTabs
);
645 window
.swap(*aResult
); // transfer reference
647 parent
->AddChildWindow(*aResult
);
650 rv
= (*aResult
)->Center(parent
, parent
? false : true, false);
656 nsAppShellService::GetHiddenWindow(nsIXULWindow
**aWindow
)
658 NS_ENSURE_ARG_POINTER(aWindow
);
660 *aWindow
= mHiddenWindow
;
661 NS_IF_ADDREF(*aWindow
);
662 return *aWindow
? NS_OK
: NS_ERROR_FAILURE
;
666 nsAppShellService::GetHiddenDOMWindow(nsIDOMWindow
**aWindow
)
669 nsCOMPtr
<nsIDocShell
> docShell
;
670 NS_ENSURE_TRUE(mHiddenWindow
, NS_ERROR_FAILURE
);
672 rv
= mHiddenWindow
->GetDocShell(getter_AddRefs(docShell
));
673 NS_ENSURE_SUCCESS(rv
, rv
);
674 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
676 nsCOMPtr
<nsIDOMWindow
> hiddenDOMWindow(docShell
->GetWindow());
677 hiddenDOMWindow
.forget(aWindow
);
678 return *aWindow
? NS_OK
: NS_ERROR_FAILURE
;
682 nsAppShellService::GetHiddenPrivateWindow(nsIXULWindow
**aWindow
)
684 NS_ENSURE_ARG_POINTER(aWindow
);
686 EnsurePrivateHiddenWindow();
688 *aWindow
= mHiddenPrivateWindow
;
689 NS_IF_ADDREF(*aWindow
);
690 return *aWindow
? NS_OK
: NS_ERROR_FAILURE
;
694 nsAppShellService::GetHiddenPrivateDOMWindow(nsIDOMWindow
**aWindow
)
696 EnsurePrivateHiddenWindow();
699 nsCOMPtr
<nsIDocShell
> docShell
;
700 NS_ENSURE_TRUE(mHiddenPrivateWindow
, NS_ERROR_FAILURE
);
702 rv
= mHiddenPrivateWindow
->GetDocShell(getter_AddRefs(docShell
));
703 NS_ENSURE_SUCCESS(rv
, rv
);
704 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
706 nsCOMPtr
<nsIDOMWindow
> hiddenPrivateDOMWindow(docShell
->GetWindow());
707 hiddenPrivateDOMWindow
.forget(aWindow
);
708 return *aWindow
? NS_OK
: NS_ERROR_FAILURE
;
712 nsAppShellService::GetHasHiddenPrivateWindow(bool* aHasPrivateWindow
)
714 NS_ENSURE_ARG_POINTER(aHasPrivateWindow
);
716 *aHasPrivateWindow
= !!mHiddenPrivateWindow
;
721 nsAppShellService::GetHiddenWindowAndJSContext(nsIDOMWindow
**aWindow
,
722 JSContext
**aJSContext
)
725 if ( aWindow
&& aJSContext
) {
727 *aJSContext
= nullptr;
729 if ( mHiddenWindow
) {
730 // Convert hidden window to nsIDOMWindow and extract its JSContext.
732 // 1. Get doc for hidden window.
733 nsCOMPtr
<nsIDocShell
> docShell
;
734 rv
= mHiddenWindow
->GetDocShell(getter_AddRefs(docShell
));
735 if (NS_FAILED(rv
)) break;
740 // 2. Convert that to an nsIDOMWindow.
741 nsCOMPtr
<nsIDOMWindow
> hiddenDOMWindow(docShell
->GetWindow());
742 if(!hiddenDOMWindow
) break;
744 // 3. Get script global object for the window.
745 nsCOMPtr
<nsIScriptGlobalObject
> sgo
= docShell
->GetScriptGlobalObject();
746 if (!sgo
) { rv
= NS_ERROR_FAILURE
; break; }
748 // 4. Get script context from that.
749 nsIScriptContext
*scriptContext
= sgo
->GetContext();
750 if (!scriptContext
) { rv
= NS_ERROR_FAILURE
; break; }
752 // 5. Get JSContext from the script context.
753 JSContext
*jsContext
= scriptContext
->GetNativeContext();
754 if (!jsContext
) { rv
= NS_ERROR_FAILURE
; break; }
756 // Now, give results to caller.
757 *aWindow
= hiddenDOMWindow
.get();
758 NS_IF_ADDREF( *aWindow
);
759 *aJSContext
= jsContext
;
762 rv
= NS_ERROR_FAILURE
;
765 rv
= NS_ERROR_NULL_POINTER
;
771 nsAppShellService::GetApplicationProvidedHiddenWindow(bool* aAPHW
)
773 *aAPHW
= mApplicationProvidedHiddenWindow
;
778 * Register a new top level window (created elsewhere)
781 nsAppShellService::RegisterTopLevelWindow(nsIXULWindow
* aWindow
)
783 NS_ENSURE_ARG_POINTER(aWindow
);
785 nsCOMPtr
<nsIDocShell
> docShell
;
786 aWindow
->GetDocShell(getter_AddRefs(docShell
));
787 NS_ENSURE_TRUE(docShell
, NS_ERROR_FAILURE
);
789 nsCOMPtr
<nsPIDOMWindow
> domWindow(docShell
->GetWindow());
790 NS_ENSURE_TRUE(domWindow
, NS_ERROR_FAILURE
);
791 domWindow
->SetInitialPrincipalToSubject();
793 // tell the window mediator about the new window
794 nsCOMPtr
<nsIWindowMediator
> mediator
795 ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
) );
796 NS_ASSERTION(mediator
, "Couldn't get window mediator.");
799 mediator
->RegisterWindow(aWindow
);
801 // tell the window watcher about the new window
802 nsCOMPtr
<nsPIWindowWatcher
> wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID
) );
803 NS_ASSERTION(wwatcher
, "No windowwatcher?");
804 if (wwatcher
&& domWindow
) {
805 wwatcher
->AddWindow(domWindow
, 0);
808 // an ongoing attempt to quit is stopped by a newly opened window
809 nsCOMPtr
<nsIObserverService
> obssvc
=
810 do_GetService("@mozilla.org/observer-service;1");
811 NS_ASSERTION(obssvc
, "Couldn't get observer service.");
814 obssvc
->NotifyObservers(aWindow
, "xul-window-registered", nullptr);
821 nsAppShellService::UnregisterTopLevelWindow(nsIXULWindow
* aWindow
)
823 if (mXPCOMShuttingDown
) {
824 /* return an error code in order to:
825 - avoid doing anything with other member variables while we are in
827 - notify the caller not to release the AppShellService after
828 unregistering the window
829 (we don't want to be deleted twice consecutively to
830 mHiddenWindow->Destroy() in our destructor)
832 return NS_ERROR_FAILURE
;
835 NS_ENSURE_ARG_POINTER(aWindow
);
837 if (aWindow
== mHiddenWindow
) {
838 // CreateHiddenWindow() does not register the window, so we're done.
841 if (aWindow
== mHiddenPrivateWindow
) {
842 // CreateHiddenWindow() does not register the window, so we're done.
846 // tell the window mediator
847 nsCOMPtr
<nsIWindowMediator
> mediator
848 ( do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
) );
849 NS_ASSERTION(mediator
, "Couldn't get window mediator. Doing xpcom shutdown?");
852 mediator
->UnregisterWindow(aWindow
);
854 // tell the window watcher
855 nsCOMPtr
<nsPIWindowWatcher
> wwatcher ( do_GetService(NS_WINDOWWATCHER_CONTRACTID
) );
856 NS_ASSERTION(wwatcher
, "Couldn't get windowwatcher, doing xpcom shutdown?");
858 nsCOMPtr
<nsIDocShell
> docShell
;
859 aWindow
->GetDocShell(getter_AddRefs(docShell
));
861 nsCOMPtr
<nsIDOMWindow
> domWindow(docShell
->GetWindow());
863 wwatcher
->RemoveWindow(domWindow
);
872 nsAppShellService::Observe(nsISupports
* aSubject
, const char *aTopic
,
873 const char16_t
*aData
)
875 if (!strcmp(aTopic
, "xpcom-will-shutdown")) {
876 mXPCOMWillShutDown
= true;
877 } else if (!strcmp(aTopic
, "xpcom-shutdown")) {
878 mXPCOMShuttingDown
= true;
880 mHiddenWindow
->Destroy();
882 if (mHiddenPrivateWindow
) {
883 mHiddenPrivateWindow
->Destroy();
886 NS_ERROR("Unexpected observer topic!");
893 nsAppShellService::StartEventLoopLagTracking(bool* aResult
)
895 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
896 *aResult
= mozilla::InitEventTracing(true);
902 nsAppShellService::StopEventLoopLagTracking()
904 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
905 mozilla::ShutdownEventTracing();