Index: chrome/browser/ui/browser_list.cc |
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc |
index be11579dd2359840435112537ac8179c225e8e87..75cc1d64b8f337b71dbf8a4ef343f52c9a12a42e 100644 |
--- a/chrome/browser/ui/browser_list.cc |
+++ b/chrome/browser/ui/browser_list.cc |
@@ -201,15 +201,24 @@ bool AreAllBrowsersCloseable() { |
return true; |
} |
-#if defined(OS_CHROMEOS) |
+// Emits APP_TERMINATING notification. It is guaranteed that the |
+// notification is sent only once. |
+void NotifyAppTerminating() { |
+ static bool notified = false; |
+ if (notified) |
+ return; |
+ notified = true; |
+ NotificationService::current()->Notify(content::NOTIFICATION_APP_TERMINATING, |
+ NotificationService::AllSources(), |
+ NotificationService::NoDetails()); |
+} |
-bool signout = false; |
+#if defined(OS_CHROMEOS) |
// Fast shutdown for ChromeOS. It tells session manager to start |
// shutdown process when closing browser windows won't be canceled. |
// Returns true if fast shutdown is successfully started. |
bool FastShutdown() { |
- signout = true; |
if (chromeos::CrosLibrary::Get()->EnsureLoaded() |
&& AreAllBrowsersCloseable()) { |
BrowserList::NotifyAndTerminate(true); |
@@ -287,15 +296,15 @@ void BrowserList::AttemptExitInternal() { |
// static |
void BrowserList::NotifyAndTerminate(bool fast_path) { |
#if defined(OS_CHROMEOS) |
- if (!signout) |
+ static bool notified = false; |
+ // Do nothing if shutdown request has already been sent. |
+ if (notified) |
DaveMoore
2011/10/13 16:50:06
Is double protecting this the right thing to do? C
oshima
2011/10/13 17:55:03
The way I understanding is that once we notified W
|
return; |
+ notified = true; |
#endif |
if (fast_path) { |
- NotificationService::current()->Notify( |
- content::NOTIFICATION_APP_TERMINATING, |
- NotificationService::AllSources(), |
- NotificationService::NoDetails()); |
+ NotifyAppTerminating(); |
} |
#if defined(OS_CHROMEOS) |
@@ -357,10 +366,7 @@ void BrowserList::RemoveBrowser(Browser* browser) { |
// to call ProfileManager::ShutdownSessionServices() as part of the |
// shutdown, because Browser::WindowClosing() already makes sure that the |
// SessionService is created and notified. |
- NotificationService::current()->Notify( |
- content::NOTIFICATION_APP_TERMINATING, |
- NotificationService::AllSources(), |
- NotificationService::NoDetails()); |
+ NotifyAppTerminating(); |
AllBrowsersClosedAndAppExiting(); |
} |
} |
@@ -379,11 +385,6 @@ void BrowserList::RemoveObserver(BrowserList::Observer* observer) { |
void BrowserList::CloseAllBrowsers() { |
bool session_ending = |
browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; |
- bool force_exit = false; |
-#if defined(USE_X11) |
- if (session_ending) |
- force_exit = true; |
-#endif |
// Tell everyone that we are shutting down. |
browser_shutdown::SetTryingToQuit(true); |
@@ -393,10 +394,12 @@ void BrowserList::CloseAllBrowsers() { |
// If there are no browsers, send the APP_TERMINATING action here. Otherwise, |
// it will be sent by RemoveBrowser() when the last browser has closed. |
- if (force_exit || browsers_.empty()) { |
+ if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() || |
+ browsers_.empty()) { |
NotifyAndTerminate(true); |
return; |
} |
+ |
#if defined(OS_CHROMEOS) |
chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( |
"StartedClosingWindows", false); |
@@ -502,10 +505,18 @@ void BrowserList::AttemptExit() { |
} |
#if defined(OS_CHROMEOS) |
+// A function called when SIGTERM is received. |
// static |
void BrowserList::ExitCleanly() { |
- // We always mark exit cleanly. |
+ // We always mark exit cleanly because SessionManager may kill |
+ // chrome in 3 seconds after SIGTERM. |
g_browser_process->EndSession(); |
+ |
+ // Don't block when SIGTERM is received. AreaAllBrowsersCloseable() |
+ // can be false in following cases. a) power-off b) signout from |
+ // screen locker. |
+ if (!AreAllBrowsersCloseable()) |
+ browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION); |
AttemptExitInternal(); |
} |
#endif |