From 301323f89528d3cbf43a4b1f5e3c48326bf7bc88 Mon Sep 17 00:00:00 2001 From: "danm%netscape.com" Date: Fri, 7 Sep 2001 23:37:16 +0000 Subject: [PATCH] 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 --- .../xpfe/appshell/src/nsAppShellService.cpp | 276 ++++++++++-------- 1 file changed, 153 insertions(+), 123 deletions(-) diff --git a/mozilla/xpfe/appshell/src/nsAppShellService.cpp b/mozilla/xpfe/appshell/src/nsAppShellService.cpp index 169dd2a1e4b..0553dcc07d6 100644 --- a/mozilla/xpfe/appshell/src/nsAppShellService.cpp +++ b/mozilla/xpfe/appshell/src/nsAppShellService.cpp @@ -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 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 windowEnumerator; + mWindowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator)); - while (1) { - rv = windowEnumerator->HasMoreElements(&more); - if (NS_FAILED(rv) || !more) - break; + if (windowEnumerator) { + PRBool more; - nsCOMPtr 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 window = do_QueryInterface(isupports); - NS_ASSERTION(window != nsnull, "not an nsIDOMWindowInternal"); - if (! window) - continue; + nsCOMPtr isupports; + rv = windowEnumerator->GetNext(getter_AddRefs(isupports)); + if (NS_FAILED(rv)) + break; - window->Close(); - } + nsCOMPtr window = do_QueryInterface(isupports); + NS_ASSERTION(window != nsnull, "not an nsIDOMWindowInternal"); + if (! window) + continue; + + window->Close(); } } + } - { - nsCOMPtr hiddenWin(do_QueryInterface(mHiddenWindow)); - if (hiddenWin) { - ClearXPConnectSafeContext(); - hiddenWin->Close(); - } - mHiddenWindow = nsnull; + { + nsCOMPtr 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 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 svc = do_GetService(kEventQueueServiceCID, &rv); + if (NS_FAILED(rv)) return rv; - nsCOMPtr queue; - rv = svc->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue)); - if (NS_FAILED(rv)) return rv; + nsCOMPtr 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 docShell; + aWindow->GetDocShell(getter_AddRefs(docShell)); + if (docShell) { + nsCOMPtr 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 windowEnumerator; + mWindowMediator->UnregisterWindow(aWindow); + + mWindowMediator->GetEnumerator(nsnull, getter_AddRefs(windowEnumerator)); + if (windowEnumerator) + windowEnumerator->HasMoreElements(&windowsRemain); + } - nsresult rv; + // tell the window watcher + if (mWindowWatcher) { + nsCOMPtr docShell; + aWindow->GetDocShell(getter_AddRefs(docShell)); + if (docShell) { + nsCOMPtr 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 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 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