Bug 372453 - XULRunner apps on mac without a hiddenwindow should be able to quit
authorgijskruitbosch@gmail.com
Thu, 23 Aug 2007 14:30:29 -0700
changeset 5221 73b7cd9d61bd1aa5ee99986571e5b79bee589535
parent 5220 24752d838d33fdce7601e4b699a4e748a4433264
child 5222 20be7fc11319f051f623d0b74ac09a58c9cb1fa9
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs372453
milestone1.9a8pre
Bug 372453 - XULRunner apps on mac without a hiddenwindow should be able to quit r=benjamin@smedbergs.us r=joshmoz@gmail.com a=bzbarsky@mit.edu
toolkit/components/startup/src/nsAppStartup.cpp
xpfe/appshell/public/nsIAppShellService.idl
xpfe/appshell/src/nsAppShellService.cpp
xpfe/appshell/src/nsAppShellService.h
--- a/toolkit/components/startup/src/nsAppStartup.cpp
+++ b/toolkit/components/startup/src/nsAppStartup.cpp
@@ -202,19 +202,43 @@ nsAppStartup::Quit(PRUint32 aMode)
     NS_WARNING("attempted to force quit");
     // it will be treated the same as eAttemptQuit, below
   }
 
   mShuttingDown = PR_TRUE;
   if (!mRestart) 
     mRestart = aMode & eRestart;
 
-  if (ferocity == eConsiderQuit && mConsiderQuitStopper == 0) {
-    // attempt quit if the last window has been unregistered/closed
-    ferocity = eAttemptQuit;
+  // If we're considering quitting, we will only do so if:
+  if (ferocity == eConsiderQuit) {
+    if (mConsiderQuitStopper == 0) {
+      // there are no windows...
+      ferocity = eAttemptQuit;
+    }
+#ifdef XP_MACOSX
+    else if (mConsiderQuitStopper == 1) {
+      // ... or there is only a hiddenWindow left, and it's useless:
+      nsCOMPtr<nsIAppShellService> appShell
+        (do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
+
+      // Failure shouldn't be fatal, but will abort quit attempt:
+      if (!appShell)
+        return NS_OK;
+
+      PRBool usefulHiddenWindow;
+      appShell->GetApplicationProvidedHiddenWindow(&usefulHiddenWindow);
+      nsCOMPtr<nsIXULWindow> hiddenWindow;
+      appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
+      // If the one window is useful, we won't quit:
+      if (!hiddenWindow || usefulHiddenWindow)
+        return NS_OK;
+
+      ferocity = eAttemptQuit;
+    }
+#endif
   }
 
   /* Currently ferocity can never have the value of eForceQuit here.
      That's temporary (in an unscheduled kind of way) and logically
      this code is part of the eForceQuit case, so I'm checking against
      that value anyway. Reviewers made me add this comment. */
   if (ferocity == eAttemptQuit || ferocity == eForceQuit) {
 
@@ -364,18 +388,23 @@ nsAppStartup::EnterLastWindowClosingSurv
 
 
 NS_IMETHODIMP
 nsAppStartup::ExitLastWindowClosingSurvivalArea(void)
 {
   NS_ASSERTION(mConsiderQuitStopper > 0, "consider quit stopper out of bounds");
   --mConsiderQuitStopper;
 
-  if (!mShuttingDown && mRunning && mConsiderQuitStopper == 0)
-    Quit(eAttemptQuit);
+#ifdef XP_MACOSX
+  if (!mShuttingDown && mRunning && (mConsiderQuitStopper <= 1))
+    Quit(eConsiderQuit);
+#else
+  if (!mShuttingDown && mRunning && (mConsiderQuitStopper == 0))
+    Quit(eConsiderQuit);
+#endif
 
   return NS_OK;
 }
 
 //
 // nsAppStartup->nsIWindowCreator
 //
 
--- a/xpfe/appshell/public/nsIAppShellService.idl
+++ b/xpfe/appshell/public/nsIAppShellService.idl
@@ -106,16 +106,23 @@ interface nsIAppShellService : nsISuppor
    * @aHiddenDOMWindow the hidden window QI'd to type nsIDOMWindowInternal
    * @aJSContext       the corresponding JavaScript context
    */
   [noscript]
   void getHiddenWindowAndJSContext(out nsIDOMWindowInternal aHiddenDOMWindow,
                                    out JSContext aJSContext);
 
   /**
+   * Return true if the application hidden window was provided by the
+   * application. If it wasn't, the default hidden window was used. This will
+   * usually be false on all non-mac platforms.
+   */
+  readonly attribute boolean applicationProvidedHiddenWindow;
+
+  /**
    * Add a window to the application's registry of windows.  These windows
    * are generally shown in the Windows taskbar, and the application
    * knows it can't quit until it's out of registered windows.
    * @param aWindow the window to register
    * @note When this method is successful, it fires the global notification
    *       "xul-window-registered"
    */
   void registerTopLevelWindow(in nsIXULWindow aWindow);
--- a/xpfe/appshell/src/nsAppShellService.cpp
+++ b/xpfe/appshell/src/nsAppShellService.cpp
@@ -79,17 +79,18 @@
 
 // Default URL for the hidden window, can be overridden by a pref on Mac
 #define DEFAULT_HIDDENWINDOW_URL "resource://gre/res/hiddenWindow.html"
 
 class nsIAppShell;
 
 nsAppShellService::nsAppShellService() : 
   mXPCOMShuttingDown(PR_FALSE),
-  mModalWindowCount(0)
+  mModalWindowCount(0),
+  mApplicationProvidedHiddenWindow(PR_FALSE)
 {
   nsCOMPtr<nsIObserverService> obs
     (do_GetService("@mozilla.org/observer-service;1"));
 
   if (obs)
     obs->AddObserver(this, "xpcom-shutdown", PR_FALSE);
 }
 
@@ -157,16 +158,17 @@ nsAppShellService::CreateHiddenWindow(ns
 #ifdef XP_MACOSX
   PRUint32    chromeMask = 0;
   nsCOMPtr<nsIPrefBranch> prefBranch;
   nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
   prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
   nsXPIDLCString prefVal;
   rv = prefBranch->GetCharPref("browser.hiddenWindowChromeURL", getter_Copies(prefVal));
   const char* hiddenWindowURL = prefVal.get() ? prefVal.get() : DEFAULT_HIDDENWINDOW_URL;
+  mApplicationProvidedHiddenWindow = prefVal.get() ? PR_TRUE : PR_FALSE;
 #else
   static const char hiddenWindowURL[] = DEFAULT_HIDDENWINDOW_URL;
   PRUint32    chromeMask =  nsIWebBrowserChrome::CHROME_ALL;
 #endif
 
   nsCOMPtr<nsIURI> url;
   rv = NS_NewURI(getter_AddRefs(url), hiddenWindowURL);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -441,16 +443,23 @@ nsAppShellService::GetHiddenWindowAndJSC
             rv = NS_ERROR_FAILURE;
         }
     } else {
         rv = NS_ERROR_NULL_POINTER;
     }
     return rv;
 }
 
+NS_IMETHODIMP
+nsAppShellService::GetApplicationProvidedHiddenWindow(PRBool* aAPHW)
+{
+    *aAPHW = mApplicationProvidedHiddenWindow;
+    return NS_OK;
+}
+
 /*
  * Register a new top level window (created elsewhere)
  */
 NS_IMETHODIMP
 nsAppShellService::RegisterTopLevelWindow(nsIXULWindow* aWindow)
 {
   // tell the window mediator about the new window
   nsCOMPtr<nsIWindowMediator> mediator
--- a/xpfe/appshell/src/nsAppShellService.h
+++ b/xpfe/appshell/src/nsAppShellService.h
@@ -71,11 +71,12 @@ protected:
                                nsWebShellWindow **aResult);
   PRUint32 CalculateWindowZLevel(nsIXULWindow *aParent, PRUint32 aChromeMask);
   nsresult SetXPConnectSafeContext();
   nsresult ClearXPConnectSafeContext();
 
   nsRefPtr<nsWebShellWindow>  mHiddenWindow;
   PRPackedBool                mXPCOMShuttingDown;
   PRUint16                    mModalWindowCount;
+  PRPackedBool                mApplicationProvidedHiddenWindow;
 };
 
 #endif