OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/browser_list.h" | 5 #include "chrome/browser/ui/browser_list.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
194 (*i)->CheckDownloadsInProgress(&normal_downloads_are_present, | 194 (*i)->CheckDownloadsInProgress(&normal_downloads_are_present, |
195 &incognito_downloads_are_present); | 195 &incognito_downloads_are_present); |
196 if (normal_downloads_are_present || | 196 if (normal_downloads_are_present || |
197 incognito_downloads_are_present || | 197 incognito_downloads_are_present || |
198 (*i)->TabsNeedBeforeUnloadFired()) | 198 (*i)->TabsNeedBeforeUnloadFired()) |
199 return false; | 199 return false; |
200 } | 200 } |
201 return true; | 201 return true; |
202 } | 202 } |
203 | 203 |
204 // Emits APP_TERMINATING notification. It is guaranteed that the | |
205 // notification is sent only once. | |
206 void NotifyAppTerminating() { | |
207 static bool notified = false; | |
208 if (notified) | |
209 return; | |
210 notified = true; | |
211 NotificationService::current()->Notify(content::NOTIFICATION_APP_TERMINATING, | |
212 NotificationService::AllSources(), | |
213 NotificationService::NoDetails()); | |
214 } | |
215 | |
204 #if defined(OS_CHROMEOS) | 216 #if defined(OS_CHROMEOS) |
205 | 217 |
206 bool signout = false; | |
207 | |
208 // Fast shutdown for ChromeOS. It tells session manager to start | 218 // Fast shutdown for ChromeOS. It tells session manager to start |
209 // shutdown process when closing browser windows won't be canceled. | 219 // shutdown process when closing browser windows won't be canceled. |
210 // Returns true if fast shutdown is successfully started. | 220 // Returns true if fast shutdown is successfully started. |
211 bool FastShutdown() { | 221 bool FastShutdown() { |
212 signout = true; | |
213 if (chromeos::CrosLibrary::Get()->EnsureLoaded() | 222 if (chromeos::CrosLibrary::Get()->EnsureLoaded() |
214 && AreAllBrowsersCloseable()) { | 223 && AreAllBrowsersCloseable()) { |
215 BrowserList::NotifyAndTerminate(true); | 224 BrowserList::NotifyAndTerminate(true); |
216 return true; | 225 return true; |
217 } | 226 } |
218 return false; | 227 return false; |
219 } | 228 } |
220 | 229 |
221 void NotifyWindowManagerAboutSignout() { | 230 void NotifyWindowManagerAboutSignout() { |
222 #if defined(TOOLKIT_USES_GTK) | 231 #if defined(TOOLKIT_USES_GTK) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
280 // On the Mac, the application continues to run once all windows are closed. | 289 // On the Mac, the application continues to run once all windows are closed. |
281 // Terminate will result in a CloseAllBrowsers() call, and once (and if) | 290 // Terminate will result in a CloseAllBrowsers() call, and once (and if) |
282 // that is done, will cause the application to exit cleanly. | 291 // that is done, will cause the application to exit cleanly. |
283 chrome_browser_application_mac::Terminate(); | 292 chrome_browser_application_mac::Terminate(); |
284 #endif | 293 #endif |
285 } | 294 } |
286 | 295 |
287 // static | 296 // static |
288 void BrowserList::NotifyAndTerminate(bool fast_path) { | 297 void BrowserList::NotifyAndTerminate(bool fast_path) { |
289 #if defined(OS_CHROMEOS) | 298 #if defined(OS_CHROMEOS) |
290 if (!signout) | 299 static bool notified = false; |
300 // Do nothing if shutdown request has already been sent. | |
301 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
| |
291 return; | 302 return; |
303 notified = true; | |
292 #endif | 304 #endif |
293 | 305 |
294 if (fast_path) { | 306 if (fast_path) { |
295 NotificationService::current()->Notify( | 307 NotifyAppTerminating(); |
296 content::NOTIFICATION_APP_TERMINATING, | |
297 NotificationService::AllSources(), | |
298 NotificationService::NoDetails()); | |
299 } | 308 } |
300 | 309 |
301 #if defined(OS_CHROMEOS) | 310 #if defined(OS_CHROMEOS) |
302 NotifyWindowManagerAboutSignout(); | 311 NotifyWindowManagerAboutSignout(); |
303 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); | 312 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); |
304 if (cros_library->EnsureLoaded()) { | 313 if (cros_library->EnsureLoaded()) { |
305 // If update has been installed, reboot, otherwise, sign out. | 314 // If update has been installed, reboot, otherwise, sign out. |
306 if (cros_library->GetUpdateLibrary()->status().status == | 315 if (cros_library->GetUpdateLibrary()->status().status == |
307 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { | 316 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { |
308 cros_library->GetUpdateLibrary()->RebootAfterUpdate(); | 317 cros_library->GetUpdateLibrary()->RebootAfterUpdate(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 // If we're exiting, send out the APP_TERMINATING notification to allow other | 359 // If we're exiting, send out the APP_TERMINATING notification to allow other |
351 // modules to shut themselves down. | 360 // modules to shut themselves down. |
352 if (browsers_.empty() && | 361 if (browsers_.empty() && |
353 (browser_shutdown::IsTryingToQuit() || | 362 (browser_shutdown::IsTryingToQuit() || |
354 g_browser_process->IsShuttingDown())) { | 363 g_browser_process->IsShuttingDown())) { |
355 // Last browser has just closed, and this is a user-initiated quit or there | 364 // Last browser has just closed, and this is a user-initiated quit or there |
356 // is no module keeping the app alive, so send out our notification. No need | 365 // is no module keeping the app alive, so send out our notification. No need |
357 // to call ProfileManager::ShutdownSessionServices() as part of the | 366 // to call ProfileManager::ShutdownSessionServices() as part of the |
358 // shutdown, because Browser::WindowClosing() already makes sure that the | 367 // shutdown, because Browser::WindowClosing() already makes sure that the |
359 // SessionService is created and notified. | 368 // SessionService is created and notified. |
360 NotificationService::current()->Notify( | 369 NotifyAppTerminating(); |
361 content::NOTIFICATION_APP_TERMINATING, | |
362 NotificationService::AllSources(), | |
363 NotificationService::NoDetails()); | |
364 AllBrowsersClosedAndAppExiting(); | 370 AllBrowsersClosedAndAppExiting(); |
365 } | 371 } |
366 } | 372 } |
367 | 373 |
368 // static | 374 // static |
369 void BrowserList::AddObserver(BrowserList::Observer* observer) { | 375 void BrowserList::AddObserver(BrowserList::Observer* observer) { |
370 observers_.AddObserver(observer); | 376 observers_.AddObserver(observer); |
371 } | 377 } |
372 | 378 |
373 // static | 379 // static |
374 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { | 380 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { |
375 observers_.RemoveObserver(observer); | 381 observers_.RemoveObserver(observer); |
376 } | 382 } |
377 | 383 |
378 // static | 384 // static |
379 void BrowserList::CloseAllBrowsers() { | 385 void BrowserList::CloseAllBrowsers() { |
380 bool session_ending = | 386 bool session_ending = |
381 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; | 387 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; |
382 bool force_exit = false; | |
383 #if defined(USE_X11) | |
384 if (session_ending) | |
385 force_exit = true; | |
386 #endif | |
387 // Tell everyone that we are shutting down. | 388 // Tell everyone that we are shutting down. |
388 browser_shutdown::SetTryingToQuit(true); | 389 browser_shutdown::SetTryingToQuit(true); |
389 | 390 |
390 // Before we close the browsers shutdown all session services. That way an | 391 // Before we close the browsers shutdown all session services. That way an |
391 // exit can restore all browsers open before exiting. | 392 // exit can restore all browsers open before exiting. |
392 ProfileManager::ShutdownSessionServices(); | 393 ProfileManager::ShutdownSessionServices(); |
393 | 394 |
394 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, | 395 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, |
395 // it will be sent by RemoveBrowser() when the last browser has closed. | 396 // it will be sent by RemoveBrowser() when the last browser has closed. |
396 if (force_exit || browsers_.empty()) { | 397 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() || |
398 browsers_.empty()) { | |
397 NotifyAndTerminate(true); | 399 NotifyAndTerminate(true); |
398 return; | 400 return; |
399 } | 401 } |
402 | |
400 #if defined(OS_CHROMEOS) | 403 #if defined(OS_CHROMEOS) |
401 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( | 404 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( |
402 "StartedClosingWindows", false); | 405 "StartedClosingWindows", false); |
403 #endif | 406 #endif |
404 for (BrowserList::const_iterator i = BrowserList::begin(); | 407 for (BrowserList::const_iterator i = BrowserList::begin(); |
405 i != BrowserList::end();) { | 408 i != BrowserList::end();) { |
406 Browser* browser = *i; | 409 Browser* browser = *i; |
407 browser->window()->Close(); | 410 browser->window()->Close(); |
408 if (!session_ending) { | 411 if (!session_ending) { |
409 ++i; | 412 ++i; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
495 // If we know that all browsers can be closed without blocking, | 498 // If we know that all browsers can be closed without blocking, |
496 // don't notify users of crashes beyond this point. | 499 // don't notify users of crashes beyond this point. |
497 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit | 500 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit |
498 // so crashes during shutdown are still reported in UMA. | 501 // so crashes during shutdown are still reported in UMA. |
499 if (AreAllBrowsersCloseable()) | 502 if (AreAllBrowsersCloseable()) |
500 MarkAsCleanShutdown(); | 503 MarkAsCleanShutdown(); |
501 AttemptExitInternal(); | 504 AttemptExitInternal(); |
502 } | 505 } |
503 | 506 |
504 #if defined(OS_CHROMEOS) | 507 #if defined(OS_CHROMEOS) |
508 // A function called when SIGTERM is received. | |
505 // static | 509 // static |
506 void BrowserList::ExitCleanly() { | 510 void BrowserList::ExitCleanly() { |
507 // We always mark exit cleanly. | 511 // We always mark exit cleanly because SessionManager may kill |
512 // chrome in 3 seconds after SIGTERM. | |
508 g_browser_process->EndSession(); | 513 g_browser_process->EndSession(); |
514 | |
515 // Don't block when SIGTERM is received. AreaAllBrowsersCloseable() | |
516 // can be false in following cases. a) power-off b) signout from | |
517 // screen locker. | |
518 if (!AreAllBrowsersCloseable()) | |
519 browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION); | |
509 AttemptExitInternal(); | 520 AttemptExitInternal(); |
510 } | 521 } |
511 #endif | 522 #endif |
512 | 523 |
513 static void TimeLimitedSessionEnding() { | 524 static void TimeLimitedSessionEnding() { |
514 // Start watching for hang during shutdown, and crash it if takes too long. | 525 // Start watching for hang during shutdown, and crash it if takes too long. |
515 // We disarm when |shutdown_watcher| object is destroyed, which is when we | 526 // We disarm when |shutdown_watcher| object is destroyed, which is when we |
516 // exit this function. | 527 // exit this function. |
517 ShutdownWatcherHelper shutdown_watcher; | 528 ShutdownWatcherHelper shutdown_watcher; |
518 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90)); | 529 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90)); |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
787 // If no more TabContents from Browsers, check the BackgroundPrintingManager. | 798 // If no more TabContents from Browsers, check the BackgroundPrintingManager. |
788 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { | 799 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { |
789 cur_ = *bg_printing_iterator_; | 800 cur_ = *bg_printing_iterator_; |
790 CHECK(cur_); | 801 CHECK(cur_); |
791 ++bg_printing_iterator_; | 802 ++bg_printing_iterator_; |
792 return; | 803 return; |
793 } | 804 } |
794 // Reached the end - no more TabContents. | 805 // Reached the end - no more TabContents. |
795 cur_ = NULL; | 806 cur_ = NULL; |
796 } | 807 } |
OLD | NEW |