restoring rev 1.159 (bug 97514 r=hyatt,pchen). the root cause of bug 98732 (and rev 1.160) has been fixed elsewhere (bug 98785).

git-svn-id: svn://10.0.0.236/trunk@102559 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
danm%netscape.com
2001-09-07 23:37:16 +00:00
parent c2fbecce04
commit 301323f895

View File

@@ -69,6 +69,7 @@ static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
static NS_DEFINE_CID(kXPConnectCID, NS_XPCONNECT_CID);
static char *sWindowWatcherContractID = "@mozilla.org/embedcomp/window-watcher;1";
// copied from nsEventQueue.cpp
static char *gEQActivatedNotification = "nsIEventQueueActivated";
@@ -80,7 +81,6 @@ NS_NAMED_LITERAL_STRING(gInstallRestartTopic, "xpinstall-restart");
nsAppShellService::nsAppShellService() :
mAppShell( nsnull ),
mWindowList( nsnull ),
mCmdLineService( nsnull ),
mWindowMediator( nsnull ),
mHiddenWindow( nsnull ),
@@ -133,18 +133,11 @@ nsAppShellService::Initialize( nsICmdLineService *aCmdLineService,
mCmdLineService = aCmdLineService;
// Remember where the native app support lives.
mNativeAppSupport = do_QueryInterface( aNativeAppSupportOrSplashScreen );
mNativeAppSupport = do_QueryInterface(aNativeAppSupportOrSplashScreen);
// Or, remember the splash screen (for backward compatibility).
if ( !mNativeAppSupport ) {
mSplashScreen = do_QueryInterface( aNativeAppSupportOrSplashScreen );
}
// Create the toplevel window list...
rv = NS_NewISupportsArray(getter_AddRefs(mWindowList));
if (NS_FAILED(rv)) {
goto done;
}
if (!mNativeAppSupport)
mSplashScreen = do_QueryInterface(aNativeAppSupportOrSplashScreen);
NS_TIMELINE_ENTER("nsComponentManager::CreateInstance.");
// Create widget application shell
@@ -152,25 +145,21 @@ nsAppShellService::Initialize( nsICmdLineService *aCmdLineService,
NS_GET_IID(nsIAppShell),
(void**)getter_AddRefs(mAppShell));
NS_TIMELINE_LEAVE("nsComponentManager::CreateInstance");
if (NS_FAILED(rv)) {
if (NS_FAILED(rv))
goto done;
}
rv = mAppShell->Create(0, nsnull);
if (NS_FAILED(rv)) {
goto done;
}
if (NS_FAILED(rv))
goto done;
// listen to EventQueues' comings and goings. do this after the appshell
// has been created, but after the event queue has been created. that
// latter bit is unfortunate, but we deal with it.
RegisterObserver(PR_TRUE);
// enable window mediation
mWindowMediator = do_GetService(kWindowMediatorCID);
// CreateHiddenWindow(); // rjc: now require this to be explicitly called
// enable window mediation (and fail if we can't get the mediator)
mWindowMediator = do_GetService(kWindowMediatorCID, &rv);
mWindowWatcher = do_GetService(sWindowWatcherContractID);
done:
return rv;
@@ -464,86 +453,86 @@ nsAppShellService::Quit()
// through any events in the queue. This guarantees a tidy cleanup.
nsresult rv = NS_OK;
if (! mShuttingDown) {
mShuttingDown = PR_TRUE;
if (mShuttingDown)
return NS_OK;
// Shutdown native app support; doing this first will prevent new
// requests to open additional windows coming in.
if ( mNativeAppSupport ) {
mNativeAppSupport->Quit();
mNativeAppSupport = 0;
}
mShuttingDown = PR_TRUE;
// Enumerate through each open window and close it
if (mWindowMediator) {
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
rv = mWindowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
// Shutdown native app support; doing this first will prevent new
// requests to open additional windows coming in.
if (mNativeAppSupport) {
mNativeAppSupport->Quit();
mNativeAppSupport = 0;
}
if (NS_SUCCEEDED(rv)) {
PRBool more;
// Enumerate through each open window and close it
if (mWindowMediator) {
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
mWindowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
while (1) {
rv = windowEnumerator->HasMoreElements(&more);
if (NS_FAILED(rv) || !more)
break;
if (windowEnumerator) {
PRBool more;
nsCOMPtr<nsISupports> isupports;
rv = windowEnumerator->GetNext(getter_AddRefs(isupports));
if (NS_FAILED(rv))
break;
while (1) {
rv = windowEnumerator->HasMoreElements(&more);
if (NS_FAILED(rv) || !more)
break;
nsCOMPtr<nsIDOMWindowInternal> window = do_QueryInterface(isupports);
NS_ASSERTION(window != nsnull, "not an nsIDOMWindowInternal");
if (! window)
continue;
nsCOMPtr<nsISupports> isupports;
rv = windowEnumerator->GetNext(getter_AddRefs(isupports));
if (NS_FAILED(rv))
break;
window->Close();
}
nsCOMPtr<nsIDOMWindowInternal> window = do_QueryInterface(isupports);
NS_ASSERTION(window != nsnull, "not an nsIDOMWindowInternal");
if (! window)
continue;
window->Close();
}
}
}
{
nsCOMPtr<nsIWebShellWindow> hiddenWin(do_QueryInterface(mHiddenWindow));
if (hiddenWin) {
ClearXPConnectSafeContext();
hiddenWin->Close();
}
mHiddenWindow = nsnull;
{
nsCOMPtr<nsIWebShellWindow> hiddenWin(do_QueryInterface(mHiddenWindow));
if (hiddenWin) {
ClearXPConnectSafeContext();
hiddenWin->Close();
}
// Note that we don't allow any premature returns from the above
// loop: no matter what, make sure we send the exit event. If
// worst comes to worst, we'll do a leaky shutdown but we WILL
// shut down. Well, assuming that all *this* stuff works ;-).
nsCOMPtr<nsIEventQueueService> svc = do_GetService(kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
mHiddenWindow = nsnull;
}
// Note that we don't allow any premature returns from the above
// loop: no matter what, make sure we send the exit event. If
// worst comes to worst, we'll do a leaky shutdown but we WILL
// shut down. Well, assuming that all *this* stuff works ;-).
nsCOMPtr<nsIEventQueueService> svc = do_GetService(kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> queue;
rv = svc->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> queue;
rv = svc->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
if (NS_FAILED(rv)) return rv;
ExitEvent* event = new ExitEvent;
if (! event)
return NS_ERROR_OUT_OF_MEMORY;
ExitEvent* event = new ExitEvent;
if (!event)
return NS_ERROR_OUT_OF_MEMORY;
PL_InitEvent(NS_REINTERPRET_CAST(PLEvent*, event),
nsnull,
HandleExitEvent,
DestroyExitEvent);
PL_InitEvent(NS_REINTERPRET_CAST(PLEvent*, event),
nsnull,
HandleExitEvent,
DestroyExitEvent);
event->mService = this;
NS_ADDREF(event->mService);
event->mService = this;
NS_ADDREF(event->mService);
rv = queue->EnterMonitor();
if (NS_SUCCEEDED(rv)) {
rv = queue->PostEvent(NS_REINTERPRET_CAST(PLEvent*, event));
}
(void) queue->ExitMonitor();
rv = queue->EnterMonitor();
if (NS_SUCCEEDED(rv))
rv = queue->PostEvent(NS_REINTERPRET_CAST(PLEvent*, event));
queue->ExitMonitor();
if (NS_FAILED(rv)) {
NS_RELEASE(event->mService);
delete event;
}
if (NS_FAILED(rv)) {
NS_RELEASE(event->mService);
delete event;
}
return rv;
@@ -808,64 +797,105 @@ nsAppShellService::GetHiddenWindowAndJSContext(nsIDOMWindowInternal **aWindow,
NS_IMETHODIMP
nsAppShellService::RegisterTopLevelWindow(nsIXULWindow* aWindow)
{
mWindowList->AppendElement(aWindow);
// tell the window mediator about the new window
if (mWindowMediator)
mWindowMediator->RegisterWindow(aWindow);
if(mWindowMediator)
mWindowMediator->RegisterWindow(aWindow);
// tell the window watcher about the new window
if (mWindowWatcher) {
nsCOMPtr<nsIDocShell> docShell;
aWindow->GetDocShell(getter_AddRefs(docShell));
if (docShell) {
nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(docShell));
if (domWindow)
mWindowWatcher->AddWindow(domWindow, 0);
}
}
return NS_OK;
return NS_OK;
}
#define SOMEBODY_SET_UP_US_THE_NULL_POINTER 1
// to be turned off once we fix callers who do that to us
NS_IMETHODIMP
nsAppShellService::UnregisterTopLevelWindow(nsIXULWindow* aWindow)
{
if (mDeleteCalled) {
// return an error code in order to:
// - avoid doing anything with other member variables while we are in the destructor
// - notify the caller not to release the AppShellService after unregistering the window
// (we don't want to be deleted twice consecutively to mHiddenWindow->Close() in our destructor)
return NS_ERROR_FAILURE;
}
PRBool windowsRemain = PR_TRUE;
if (mDeleteCalled) {
/* return an error code in order to:
- avoid doing anything with other member variables while we are in
the destructor
- notify the caller not to release the AppShellService after
unregistering the window
(we don't want to be deleted twice consecutively to
mHiddenWindow->Close() in our destructor)
*/
return NS_ERROR_FAILURE;
}
if(mWindowMediator)
mWindowMediator->UnregisterWindow(aWindow);
#ifdef SOMEBODY_SET_UP_US_THE_NULL_POINTER
if (aWindow) {
#else
NS_ENSURE_ARG_POINTER(aWindow);
#endif
// tell the window mediator
if (mWindowMediator) {
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
mWindowMediator->UnregisterWindow(aWindow);
mWindowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator));
if (windowEnumerator)
windowEnumerator->HasMoreElements(&windowsRemain);
}
nsresult rv;
// tell the window watcher
if (mWindowWatcher) {
nsCOMPtr<nsIDocShell> docShell;
aWindow->GetDocShell(getter_AddRefs(docShell));
if (docShell) {
nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(docShell));
if (domWindow)
mWindowWatcher->RemoveWindow(domWindow);
}
}
#ifdef SOMEBODY_SET_UP_US_THE_NULL_POINTER
}
#endif
mWindowList->RemoveElement(aWindow);
// now quit if the last window has been unregistered (unless we shouldn't)
PRUint32 cnt;
rv = mWindowList->Count(&cnt);
if (NS_FAILED(rv)) return rv;
if (0 == cnt)
{
if (!mQuitOnLastWindowClosing)
return NS_OK;
if (!mQuitOnLastWindowClosing)
return NS_OK;
if (!windowsRemain) {
#if XP_MAC
// if no hidden window is available (perhaps due to initial
// Profile Manager window being cancelled), then just quit. We don't have
// to worry about focussing the hidden window, because it will get activated
// by the OS since it is visible (but waaaay offscreen).
nsCOMPtr<nsIBaseWindow> hiddenWin(do_QueryInterface(mHiddenWindow));
if (!hiddenWin)
Quit();
#else
#if XP_MAC
// if no hidden window is available (perhaps due to initial
// Profile Manager window being cancelled), then just quit. We don't have
// to worry about focussing the hidden window, because it will get activated
// by the OS since it is visible (but waaaay offscreen).
nsCOMPtr<nsIBaseWindow> hiddenWin(do_QueryInterface(mHiddenWindow));
if (!hiddenWin)
Quit();
#else
// Check to see if we should quit in this case.
if (mNativeAppSupport) {
PRBool serverMode = PR_FALSE;
mNativeAppSupport->GetIsServerMode(&serverMode);
if (serverMode) {
mNativeAppSupport->OnLastWindowClosing(aWindow);
return NS_OK;
}
PRBool serverMode = PR_FALSE;
mNativeAppSupport->GetIsServerMode(&serverMode);
if (serverMode) {
mNativeAppSupport->OnLastWindowClosing(aWindow);
return NS_OK;
}
}
Quit();
#endif
#endif
}
return rv;
return NS_OK;
}
NS_IMETHODIMP