Chromium Code Reviews| 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 22 matching lines...) Expand all Loading... | |
| 33 #include "chrome/browser/chromeos/cros/cros_library.h" | 33 #include "chrome/browser/chromeos/cros/cros_library.h" |
| 34 #include "chrome/browser/chromeos/cros/login_library.h" | 34 #include "chrome/browser/chromeos/cros/login_library.h" |
| 35 #include "chrome/browser/chromeos/cros/update_library.h" | 35 #include "chrome/browser/chromeos/cros/update_library.h" |
| 36 #if defined(TOOLKIT_USES_GTK) | 36 #if defined(TOOLKIT_USES_GTK) |
| 37 #include "chrome/browser/chromeos/wm_ipc.h" | 37 #include "chrome/browser/chromeos/wm_ipc.h" |
| 38 #endif | 38 #endif |
| 39 #endif | 39 #endif |
| 40 | 40 |
| 41 namespace { | 41 namespace { |
| 42 | 42 |
| 43 // ********************* IMPORTANT **************** | |
| 44 // Please read and update if you need to change the quit/shutdown | |
| 45 // process. | |
| 46 // | |
| 47 // This is an attempt to descritbe different kinds of quit/shutdown | |
| 48 // process that chrome may process. This overs only Windows and Linux | |
| 49 // because I (oshima) don't know about mac. Mac contribution to this | |
| 50 // comment would be greatly appreciated. | |
| 51 // | |
| 52 // Common behavior. | |
| 53 // APP_EXITING notification is always sent when chrome starts shutdown | |
| 54 // process (with one exception. see ChromeOS guest mode below). | |
| 55 // Note that shutdown process can be canceled, so APP_EXITING may | |
| 56 // be sent MORE THAN ONCE. | |
| 57 // | |
| 58 // Normal shutdown on Linux & Windows | |
| 59 // A user requested to quit the browser (win: by wrench menu or | |
| 60 // ctrl-alt-q, or linux:wrench menu, ctrl-alt-q or SIGTERM). | |
| 61 // It notifies APP_EXITING, then tries to close all browsers. | |
| 62 // When the last browser gets deleted, it sends out APP_TERMINATING | |
| 63 // notification as a signal that browser is really quitting. | |
| 64 // Shutdown may be blocked and canceled by beforeunload handler or | |
| 65 // downloads in progress. (in which case, APP_TERMINATING won't be sent) | |
| 66 // | |
| 67 // Restart on Linux & Windows | |
| 68 // A user requested to restart the browser. This can happen when | |
| 69 // certain preference has changed (flags page, language option), or | |
| 70 // update is availabe. Chrome sets kRestartLastSessionOnShutdown | |
| 71 // preference to true, follows normal shutdown process and re-launches | |
| 72 // itself at the end of the process (see browser_shutdown::Shutdown()). | |
| 73 // | |
| 74 // Logoff/power off on Windows | |
| 75 // This happens when chrome recieves WM_ENDSESSION message. It | |
| 76 // notifies APP_EXITING, then close all tabs forcibly. This | |
| 77 // process does send APP_TERMINATING notification. This shutdown | |
| 78 // process cannot be blocked nor canceled. | |
| 79 // | |
| 80 // X IO Error on Linux and ChromeOS: | |
| 81 // When X server reports IO error, it's most likely X has gone away and | |
| 82 // chrome needs has to shutdown without make another call to X. | |
| 83 // This is similar to Window's logoff/power off process, except that | |
| 84 // chrome doesn't try to close browsers nor tabs. APP_TERMINATING is sent | |
| 85 // after APP_EXITING. | |
| 86 // | |
| 87 // ChromeOS specific: | |
| 88 // Fast shutdown | |
| 89 // When a user requested to quit browser either by wrench menu or | |
| 90 // ctrl-alt-q, and we know that shutdown will not be canceled (that is, | |
| 91 // all contents have no beforeunload handlers and there is no | |
| 92 // downloads in progress), chrome quits using fast shutdown process. | |
| 93 // It notifies APP_EXITING, followed by APP_TERMINATING, then | |
| 94 // tells SessionManager to start shutdown process. SessionManager sends | |
| 95 // SIGTERM back to chrome, which closes all browsers. | |
| 96 // | |
| 97 // Slow shutdown | |
| 98 // If there is a tab with beforeunload handlers, or a download is | |
| 99 // in progress, it will follow normal shutdown process. That is, | |
| 100 // it notifies APP_EXITING, tries to closes all browsers. APP_TERMINATING | |
| 101 // will be sent when the last browser is closd. Shutdown may be cancelled | |
| 102 // either by beforeunload handler or download dialog. | |
| 103 // | |
| 104 // Restart | |
| 105 // ChromeOS does not support restarting. It follows regular shutdown process , | |
| 106 // | |
| 107 // Power off | |
| 108 // A user pressed power button, or closed a lid on login screen. This is | |
| 109 // similar to Windows log-off/power-off scenario. Chrome receives SIGTERM | |
| 110 // and start shutdown process. It will close all tabs forcibly and shutdown | |
| 111 // cannot be canceled. | |
| 112 // | |
| 113 // Signout from Screen locker. | |
| 114 // A user clicked signout button on screen locker. This is basically same | |
| 115 // as Power off. Chrome asks session manager to stop session and session | |
| 116 // manager sends SIGTERM to chrome. | |
| 117 // | |
| 118 // Switching to Guest mode | |
| 119 // When a user selected guest mode, Chrome first writes exit_cleanly bit | |
| 120 // off to the disk (see g_browser_process->EndSession() in | |
| 121 // chromeos/login_utils.cc), then tells SessionManager to switch to guest | |
| 122 // mode. Session manager kills and restarts Chrome with guest mode flag. | |
| 123 // This process never use method in BrowserList, nor sends APP_EXITING | |
| 124 // or APP_TERMINATING (to restart fast). | |
| 125 // | |
| 126 // Note that different shutdown path | |
| 127 // | |
| 128 // Mac: | |
| 129 // T.B.D. | |
| 130 // | |
| 131 | |
| 43 // This object is instantiated when the first Browser object is added to the | 132 // This object is instantiated when the first Browser object is added to the |
| 44 // list and delete when the last one is removed. It watches for loads and | 133 // list and delete when the last one is removed. It watches for loads and |
| 45 // creates histograms of some global object counts. | 134 // creates histograms of some global object counts. |
| 46 class BrowserActivityObserver : public NotificationObserver { | 135 class BrowserActivityObserver : public NotificationObserver { |
| 47 public: | 136 public: |
| 48 BrowserActivityObserver() { | 137 BrowserActivityObserver() { |
| 49 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 138 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 50 NotificationService::AllSources()); | 139 NotificationService::AllSources()); |
| 51 } | 140 } |
| 52 ~BrowserActivityObserver() {} | 141 ~BrowserActivityObserver() {} |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 194 (*i)->CheckDownloadsInProgress(&normal_downloads_are_present, | 283 (*i)->CheckDownloadsInProgress(&normal_downloads_are_present, |
| 195 &incognito_downloads_are_present); | 284 &incognito_downloads_are_present); |
| 196 if (normal_downloads_are_present || | 285 if (normal_downloads_are_present || |
| 197 incognito_downloads_are_present || | 286 incognito_downloads_are_present || |
| 198 (*i)->TabsNeedBeforeUnloadFired()) | 287 (*i)->TabsNeedBeforeUnloadFired()) |
| 199 return false; | 288 return false; |
| 200 } | 289 } |
| 201 return true; | 290 return true; |
| 202 } | 291 } |
| 203 | 292 |
| 293 // Sends out NOTIFICATION_APP_TERMINATING notification. | |
| 294 // Returns true if the notification is set, or false if the notification | |
| 295 // has already sent out before. | |
| 296 bool NotifyAppTerminating() { | |
| 297 static bool notified = false; | |
| 298 if (notified) | |
| 299 return false; | |
| 300 notified = true; | |
| 301 NotificationService::current()->Notify( | |
| 302 content::NOTIFICATION_APP_TERMINATING, | |
| 303 NotificationService::AllSources(), | |
| 304 NotificationService::NoDetails()); | |
| 305 return true; | |
| 306 } | |
| 307 | |
| 204 #if defined(OS_CHROMEOS) | 308 #if defined(OS_CHROMEOS) |
| 205 | 309 |
| 206 bool signout = false; | 310 bool explicit_signout = false; |
| 207 | 311 |
| 208 // Fast shutdown for ChromeOS. It tells session manager to start | 312 // Fast shutdown for ChromeOS. It tells session manager to start |
| 209 // shutdown process when closing browser windows won't be canceled. | 313 // shutdown process when closing browser windows won't be canceled. |
| 210 // Returns true if fast shutdown is successfully started. | 314 // Returns true if fast shutdown is successfully started. |
| 211 bool FastShutdown() { | 315 bool FastShutdown() { |
| 212 signout = true; | |
| 213 if (chromeos::CrosLibrary::Get()->EnsureLoaded() | 316 if (chromeos::CrosLibrary::Get()->EnsureLoaded() |
| 214 && AreAllBrowsersCloseable()) { | 317 && AreAllBrowsersCloseable()) { |
| 215 BrowserList::NotifyAndTerminate(true); | 318 BrowserList::NotifyAndTerminate(true); |
| 216 return true; | 319 return true; |
| 217 } | 320 } |
| 218 return false; | 321 return false; |
| 219 } | 322 } |
| 220 | 323 |
| 221 void NotifyWindowManagerAboutSignout() { | 324 void NotifyWindowManagerAboutSignout() { |
| 222 #if defined(TOOLKIT_USES_GTK) | 325 #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. | 383 // 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) | 384 // Terminate will result in a CloseAllBrowsers() call, and once (and if) |
| 282 // that is done, will cause the application to exit cleanly. | 385 // that is done, will cause the application to exit cleanly. |
| 283 chrome_browser_application_mac::Terminate(); | 386 chrome_browser_application_mac::Terminate(); |
| 284 #endif | 387 #endif |
| 285 } | 388 } |
| 286 | 389 |
| 287 // static | 390 // static |
| 288 void BrowserList::NotifyAndTerminate(bool fast_path) { | 391 void BrowserList::NotifyAndTerminate(bool fast_path) { |
| 289 #if defined(OS_CHROMEOS) | 392 #if defined(OS_CHROMEOS) |
| 290 if (!signout) | 393 if (browser_shutdown::ShutdownType() != browser_shutdown::BROWSER_EXIT); |
| 291 return; | 394 return; |
| 292 #endif | 395 #endif |
| 293 | 396 |
| 294 if (fast_path) { | 397 if (fast_path) { |
| 295 NotificationService::current()->Notify( | 398 NotifyAppTerminating(); |
| 296 content::NOTIFICATION_APP_TERMINATING, | |
| 297 NotificationService::AllSources(), | |
| 298 NotificationService::NoDetails()); | |
| 299 } | 399 } |
| 300 | 400 |
| 301 #if defined(OS_CHROMEOS) | 401 #if defined(OS_CHROMEOS) |
| 302 NotifyWindowManagerAboutSignout(); | 402 NotifyWindowManagerAboutSignout(); |
| 303 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); | 403 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); |
| 304 if (cros_library->EnsureLoaded()) { | 404 if (cros_library->EnsureLoaded()) { |
| 305 // If update has been installed, reboot, otherwise, sign out. | 405 // If update has been installed, reboot, otherwise, sign out. |
| 306 if (cros_library->GetUpdateLibrary()->status().status == | 406 if (cros_library->GetUpdateLibrary()->status().status == |
| 307 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { | 407 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { |
| 308 cros_library->GetUpdateLibrary()->RebootAfterUpdate(); | 408 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 | 450 // If we're exiting, send out the APP_TERMINATING notification to allow other |
| 351 // modules to shut themselves down. | 451 // modules to shut themselves down. |
| 352 if (browsers_.empty() && | 452 if (browsers_.empty() && |
| 353 (browser_shutdown::IsTryingToQuit() || | 453 (browser_shutdown::IsTryingToQuit() || |
| 354 g_browser_process->IsShuttingDown())) { | 454 g_browser_process->IsShuttingDown())) { |
| 355 // Last browser has just closed, and this is a user-initiated quit or there | 455 // 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 | 456 // is no module keeping the app alive, so send out our notification. No need |
| 357 // to call ProfileManager::ShutdownSessionServices() as part of the | 457 // to call ProfileManager::ShutdownSessionServices() as part of the |
| 358 // shutdown, because Browser::WindowClosing() already makes sure that the | 458 // shutdown, because Browser::WindowClosing() already makes sure that the |
| 359 // SessionService is created and notified. | 459 // SessionService is created and notified. |
| 360 NotificationService::current()->Notify( | 460 // On ChromeOS, APP_TERMINATING might have already been sent when |
| 361 content::NOTIFICATION_APP_TERMINATING, | 461 // shutdown is first requested. The call will be ignored in that case. |
| 362 NotificationService::AllSources(), | 462 NotifyAppTerminating(); |
| 363 NotificationService::NoDetails()); | |
| 364 AllBrowsersClosedAndAppExiting(); | 463 AllBrowsersClosedAndAppExiting(); |
| 365 } | 464 } |
| 366 } | 465 } |
| 367 | 466 |
| 368 // static | 467 // static |
| 369 void BrowserList::AddObserver(BrowserList::Observer* observer) { | 468 void BrowserList::AddObserver(BrowserList::Observer* observer) { |
| 370 observers_.AddObserver(observer); | 469 observers_.AddObserver(observer); |
| 371 } | 470 } |
| 372 | 471 |
| 373 // static | 472 // static |
| 374 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { | 473 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { |
| 375 observers_.RemoveObserver(observer); | 474 observers_.RemoveObserver(observer); |
| 376 } | 475 } |
| 377 | 476 |
| 378 // static | 477 // static |
| 379 void BrowserList::CloseAllBrowsers() { | 478 void BrowserList::CloseAllBrowsers() { |
| 479 browser_shutdown::ShutdownType shutdown_type = | |
| 480 browser_shutdown::GetShutdownType() | |
| 481 /* | |
| 380 bool session_ending = | 482 bool session_ending = |
| 381 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; | 483 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; |
| 382 bool force_exit = false; | 484 bool force_exit = false; |
| 383 #if defined(USE_X11) | 485 #if defined(USE_X11) |
| 384 if (session_ending) | 486 if (session_ending) |
| 385 force_exit = true; | 487 force_exit = true; |
| 386 #endif | 488 #endif |
| 489 */ | |
| 387 // Tell everyone that we are shutting down. | 490 // Tell everyone that we are shutting down. |
| 388 browser_shutdown::SetTryingToQuit(true); | 491 browser_shutdown::SetTryingToQuit(true); |
| 389 | 492 |
| 390 // Before we close the browsers shutdown all session services. That way an | 493 // Before we close the browsers shutdown all session services. That way an |
| 391 // exit can restore all browsers open before exiting. | 494 // exit can restore all browsers open before exiting. |
| 392 ProfileManager::ShutdownSessionServices(); | 495 ProfileManager::ShutdownSessionServices(); |
| 393 | 496 |
| 497 // If we're not closing browser, send APP_TERMINATING | |
| 498 if (shutdown_type == browser_shutdown::SHUTDOWN_WITHOUT_CLOSE) { | |
| 499 NotifyAppTerminating(); | |
| 500 return; | |
| 501 } | |
| 502 | |
| 394 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, | 503 // 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. | 504 // it will be sent by RemoveBrowser() when the last browser has closed. |
| 396 if (force_exit || browsers_.empty()) { | 505 if (force_exit || browsers_.empty()) { |
| 397 NotifyAndTerminate(true); | 506 NotifyAndTerminate(true); |
| 398 return; | 507 return; |
| 399 } | 508 } |
| 509 | |
| 400 #if defined(OS_CHROMEOS) | 510 #if defined(OS_CHROMEOS) |
| 401 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( | 511 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( |
| 402 "StartedClosingWindows", false); | 512 "StartedClosingWindows", false); |
| 403 #endif | 513 #endif |
| 514 | |
| 404 for (BrowserList::const_iterator i = BrowserList::begin(); | 515 for (BrowserList::const_iterator i = BrowserList::begin(); |
| 405 i != BrowserList::end();) { | 516 i != BrowserList::end();) { |
| 406 Browser* browser = *i; | 517 Browser* browser = *i; |
|
achuithb
2011/10/28 22:22:26
Do you think you could also clean this loop up if
| |
| 407 browser->window()->Close(); | 518 browser->window()->Close(); |
| 408 if (!session_ending) { | 519 if (shutdown_type != browser_shutdown::POWER_OFF) { |
| 409 ++i; | 520 ++i; |
| 410 } else { | 521 } else { |
| 411 // This path is hit during logoff/power-down. In this case we won't get | 522 // This path is hit during logoff/power-down. In this case we won't get |
| 412 // a final message and so we force the browser to be deleted. | 523 // a final message and so we force the browser to be deleted. |
| 413 // Close doesn't immediately destroy the browser | 524 // Close doesn't immediately destroy the browser |
| 414 // (Browser::TabStripEmpty() uses invoke later) but when we're ending the | 525 // (Browser::TabStripEmpty() uses invoke later) but when we're ending the |
| 415 // session we need to make sure the browser is destroyed now. So, invoke | 526 // session we need to make sure the browser is destroyed now. So, invoke |
| 416 // DestroyBrowser to make sure the browser is deleted and cleanup can | 527 // DestroyBrowser to make sure the browser is deleted and cleanup can |
| 417 // happen. | 528 // happen. |
| 418 while (browser->tab_count()) | 529 while (browser->tab_count()) |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 440 } | 551 } |
| 441 | 552 |
| 442 for (BrowserVector::const_iterator i = browsers_to_close.begin(); | 553 for (BrowserVector::const_iterator i = browsers_to_close.begin(); |
| 443 i != browsers_to_close.end(); ++i) { | 554 i != browsers_to_close.end(); ++i) { |
| 444 (*i)->window()->Close(); | 555 (*i)->window()->Close(); |
| 445 } | 556 } |
| 446 } | 557 } |
| 447 | 558 |
| 448 // static | 559 // static |
| 449 void BrowserList::AttemptUserExit() { | 560 void BrowserList::AttemptUserExit() { |
| 561 browser_shutdown::OnShutdownStarting(browser_shutdown::BROWSER_EXIT); | |
| 450 #if defined(OS_CHROMEOS) | 562 #if defined(OS_CHROMEOS) |
| 451 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutStarted", false); | 563 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutStarted", false); |
| 452 // Write /tmp/uptime-logout-started as well. | 564 // Write /tmp/uptime-logout-started as well. |
| 453 const char kLogoutStarted[] = "logout-started"; | 565 const char kLogoutStarted[] = "logout-started"; |
| 454 chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted); | 566 chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted); |
| 455 | 567 |
| 456 // Login screen should show up in owner's locale. | 568 // Login screen should show up in owner's locale. |
| 457 PrefService* state = g_browser_process->local_state(); | 569 PrefService* state = g_browser_process->local_state(); |
| 458 if (state) { | 570 if (state) { |
| 459 std::string owner_locale = state->GetString(prefs::kOwnerLocale); | 571 std::string owner_locale = state->GetString(prefs::kOwnerLocale); |
| 460 if (!owner_locale.empty() && | 572 if (!owner_locale.empty() && |
| 461 state->GetString(prefs::kApplicationLocale) != owner_locale && | 573 state->GetString(prefs::kApplicationLocale) != owner_locale && |
| 462 !state->IsManagedPreference(prefs::kApplicationLocale)) { | 574 !state->IsManagedPreference(prefs::kApplicationLocale)) { |
| 463 state->SetString(prefs::kApplicationLocale, owner_locale); | 575 state->SetString(prefs::kApplicationLocale, owner_locale); |
| 464 state->SavePersistentPrefs(); | 576 state->SavePersistentPrefs(); |
| 465 } | 577 } |
| 466 } | 578 } |
| 579 | |
| 467 if (FastShutdown()) | 580 if (FastShutdown()) |
| 468 return; | 581 return; |
| 469 #else | 582 #else |
| 470 // Reset the restart bit that might have been set in cancelled restart | 583 // Reset the restart bit that might have been set in cancelled restart |
| 471 // request. | 584 // request. |
| 472 PrefService* pref_service = g_browser_process->local_state(); | 585 PrefService* pref_service = g_browser_process->local_state(); |
| 473 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); | 586 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); |
| 474 #endif | 587 #endif |
| 475 AttemptExitInternal(); | 588 AttemptExitInternal(); |
| 476 } | 589 } |
| 477 | 590 |
| 478 // static | 591 // static |
| 479 void BrowserList::AttemptRestart() { | 592 void BrowserList::AttemptRestart() { |
| 480 #if defined(OS_CHROMEOS) | 593 #if defined(OS_CHROMEOS) |
| 481 // For CrOS instead of browser restart (which is not supported) perform a full | 594 // For CrOS instead of browser restart (which is not supported) perform a full |
| 482 // sign out. Session will be only restored if user has that setting set. | 595 // sign out. Session will be only restored if user has that setting set. |
| 483 // Same session restore behavior happens in case of full restart after update. | 596 // Same session restore behavior happens in case of full restart after update. |
| 597 // TODO(oshima): Should we use LoginLibrary::RestartJob()? | |
| 484 AttemptUserExit(); | 598 AttemptUserExit(); |
| 485 #else | 599 #else |
| 486 // Set the flag to restore state after the restart. | 600 // Set the flag to restore state after the restart. |
| 487 PrefService* pref_service = g_browser_process->local_state(); | 601 PrefService* pref_service = g_browser_process->local_state(); |
| 488 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true); | 602 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true); |
| 489 AttemptExit(); | 603 AttemptExit(); |
| 490 #endif | 604 #endif |
| 491 } | 605 } |
| 492 | 606 |
| 493 // static | 607 // static |
| 494 void BrowserList::AttemptExit() { | 608 void BrowserList::AttemptExit() { |
| 495 // If we know that all browsers can be closed without blocking, | 609 // If we know that all browsers can be closed without blocking, |
| 496 // don't notify users of crashes beyond this point. | 610 // don't notify users of crashes beyond this point. |
| 497 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit | 611 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit |
| 498 // so crashes during shutdown are still reported in UMA. | 612 // so crashes during shutdown are still reported in UMA. |
| 499 if (AreAllBrowsersCloseable()) | 613 if (AreAllBrowsersCloseable()) |
| 500 MarkAsCleanShutdown(); | 614 MarkAsCleanShutdown(); |
| 501 AttemptExitInternal(); | 615 AttemptExitInternal(); |
| 502 } | 616 } |
| 503 | 617 |
| 504 #if defined(OS_CHROMEOS) | 618 #if defined(OS_CHROMEOS) |
| 505 // static | 619 // static |
| 506 void BrowserList::ExitCleanly() { | 620 void BrowserList::ExitCleanly() { |
| 507 // We always mark exit cleanly. | 621 // We always mark exit cleanly. |
| 508 g_browser_process->EndSession(); | 622 g_browser_process->EndSession(); |
| 623 if (AreAllBrowsersCloseable()) | |
| 624 | |
| 509 AttemptExitInternal(); | 625 AttemptExitInternal(); |
| 510 } | 626 } |
| 511 #endif | 627 #endif |
| 512 | 628 |
| 513 static void TimeLimitedSessionEnding() { | 629 static void TimeLimitedForceShutdown(browser_shutdown::ShutdownType type) { |
| 514 // Start watching for hang during shutdown, and crash it if takes too long. | 630 // 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 | 631 // We disarm when |shutdown_watcher| object is destroyed, which is when we |
| 516 // exit this function. | 632 // exit this function. |
| 517 ShutdownWatcherHelper shutdown_watcher; | 633 ShutdownWatcherHelper shutdown_watcher; |
| 518 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90)); | 634 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90)); |
| 519 | 635 |
| 520 // EndSession is invoked once per frame. Only do something the first time. | 636 // EndSession is invoked once per frame. Only do something the first time. |
| 521 static bool already_ended = false; | 637 static bool already_ended = false; |
| 522 // We may get called in the middle of shutdown, e.g. http://crbug.com/70852 | 638 // We may get called in the middle of shutdown, e.g. http://crbug.com/70852 |
| 523 // In this case, do nothing. | 639 // In this case, do nothing. |
| 524 if (already_ended || !NotificationService::current()) | 640 if (already_ended || !NotificationService::current()) |
| 525 return; | 641 return; |
| 526 already_ended = true; | 642 already_ended = true; |
| 527 | 643 |
| 528 browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION); | 644 browser_shutdown::OnShutdownStarting(type); |
| 529 | 645 |
| 530 NotificationService::current()->Notify( | 646 NotificationService::current()->Notify( |
| 531 content::NOTIFICATION_APP_EXITING, | 647 content::NOTIFICATION_APP_EXITING, |
| 532 NotificationService::AllSources(), | 648 NotificationService::AllSources(), |
| 533 NotificationService::NoDetails()); | 649 NotificationService::NoDetails()); |
| 534 | 650 |
| 535 // Write important data first. | 651 // Write important data first. |
| 536 g_browser_process->EndSession(); | 652 g_browser_process->EndSession(); |
| 537 | 653 |
| 538 BrowserList::CloseAllBrowsers(); | 654 BrowserList::CloseAllBrowsers(); |
| 539 | 655 |
| 540 // Send out notification. This is used during testing so that the test harness | 656 // Send out notification. This is used during testing so that the test harness |
| 541 // can properly shutdown before we exit. | 657 // can properly shutdown before we exit. |
| 542 NotificationService::current()->Notify( | 658 NotificationService::current()->Notify( |
| 543 chrome::NOTIFICATION_SESSION_END, | 659 chrome::NOTIFICATION_SESSION_END, |
| 544 NotificationService::AllSources(), | 660 NotificationService::AllSources(), |
| 545 NotificationService::NoDetails()); | 661 NotificationService::NoDetails()); |
| 546 | 662 |
| 547 // And shutdown. | 663 // And shutdown. |
| 548 browser_shutdown::Shutdown(); | 664 browser_shutdown::Shutdown(); |
| 549 } | 665 } |
| 550 | 666 |
| 551 // static | 667 // static |
| 552 void BrowserList::SessionEnding() { | 668 void BrowserList::ForceShutdown(SessionEndingReason raeson) { |
| 553 TimeLimitedSessionEnding(); | 669 TimeLimitedForceShutdown(reason); |
| 554 | 670 |
| 555 #if defined(OS_WIN) | 671 #if defined(OS_WIN) |
| 556 // At this point the message loop is still running yet we've shut everything | 672 // At this point the message loop is still running yet we've shut everything |
| 557 // down. If any messages are processed we'll likely crash. Exit now. | 673 // down. If any messages are processed we'll likely crash. Exit now. |
| 558 ExitProcess(content::RESULT_CODE_NORMAL_EXIT); | 674 ExitProcess(content::RESULT_CODE_NORMAL_EXIT); |
| 559 #elif defined(OS_POSIX) && !defined(OS_MACOSX) | 675 #elif defined(OS_POSIX) && !defined(OS_MACOSX) |
| 560 _exit(content::RESULT_CODE_NORMAL_EXIT); | 676 _exit(content::RESULT_CODE_NORMAL_EXIT); |
| 561 #else | 677 #else |
| 562 NOTIMPLEMENTED(); | 678 NOTIMPLEMENTED(); |
| 563 #endif | 679 #endif |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 787 // If no more TabContents from Browsers, check the BackgroundPrintingManager. | 903 // If no more TabContents from Browsers, check the BackgroundPrintingManager. |
| 788 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { | 904 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { |
| 789 cur_ = *bg_printing_iterator_; | 905 cur_ = *bg_printing_iterator_; |
| 790 CHECK(cur_); | 906 CHECK(cur_); |
| 791 ++bg_printing_iterator_; | 907 ++bg_printing_iterator_; |
| 792 return; | 908 return; |
| 793 } | 909 } |
| 794 // Reached the end - no more TabContents. | 910 // Reached the end - no more TabContents. |
| 795 cur_ = NULL; | 911 cur_ = NULL; |
| 796 } | 912 } |
| OLD | NEW |