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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 | 248 |
| 249 // Send out notifications after add has occurred. Do some basic checking to | 249 // Send out notifications after add has occurred. Do some basic checking to |
| 250 // try to catch evil observers that change the list from under us. | 250 // try to catch evil observers that change the list from under us. |
| 251 size_t original_count = observers_.size(); | 251 size_t original_count = observers_.size(); |
| 252 FOR_EACH_OBSERVER(Observer, observers_, OnBrowserAdded(browser)); | 252 FOR_EACH_OBSERVER(Observer, observers_, OnBrowserAdded(browser)); |
| 253 DCHECK_EQ(original_count, observers_.size()) | 253 DCHECK_EQ(original_count, observers_.size()) |
| 254 << "observer list modified during notification"; | 254 << "observer list modified during notification"; |
| 255 } | 255 } |
| 256 | 256 |
| 257 // static | 257 // static |
| 258 void BrowserList::MarkAsCleanShutdown() { | 258 void BrowserList::MarkAsCleanShutdownInUserProfiles() { |
| 259 for (const_iterator i = begin(); i != end(); ++i) { | 259 for (const_iterator i = begin(); i != end(); ++i) { |
| 260 (*i)->profile()->MarkAsCleanShutdown(); | 260 (*i)->profile()->MarkAsCleanShutdown(); |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 | 263 |
| 264 void BrowserList::AttemptExitInternal() { | 264 void BrowserList::AttemptExitInternal() { |
| 265 NotificationService::current()->Notify( | 265 NotificationService::current()->Notify( |
| 266 NotificationType::APP_EXITING, | 266 NotificationType::APP_EXITING, |
| 267 NotificationService::AllSources(), | 267 NotificationService::AllSources(), |
| 268 NotificationService::NoDetails()); | 268 NotificationService::NoDetails()); |
| 269 | 269 |
| 270 #if !defined(OS_MACOSX) | 270 #if !defined(OS_MACOSX) |
| 271 // On most platforms, closing all windows causes the application to exit. | 271 // On most platforms, closing all windows causes the application to exit. |
| 272 CloseAllBrowsers(); | 272 CloseAllBrowsers(); |
| 273 #else | 273 #else |
| 274 // On the Mac, the application continues to run once all windows are closed. | 274 // On the Mac, the application continues to run once all windows are closed. |
| 275 // Terminate will result in a CloseAllBrowsers() call, and once (and if) | 275 // Terminate will result in a CloseAllBrowsers() call, and once (and if) |
| 276 // that is done, will cause the application to exit cleanly. | 276 // that is done, will cause the application to exit cleanly. |
| 277 chrome_browser_application_mac::Terminate(); | 277 chrome_browser_application_mac::Terminate(); |
| 278 #endif | 278 #endif |
| 279 } | 279 } |
| 280 | 280 |
| 281 // static | 281 // static |
| 282 void BrowserList::NotifyAndTerminate(bool fast_path) { | 282 void BrowserList::NotifyAndTerminate(bool fast_path) { |
| 283 #if defined(OS_CHROMEOS) | 283 #if defined(OS_CHROMEOS) |
| 284 if (!signout) return; | 284 if (!signout) |
| 285 NotifyWindowManagerAboutSignout(); | 285 return; |
| 286 #endif | 286 #endif |
| 287 | 287 |
| 288 if (fast_path) { | 288 if (fast_path) { |
| 289 NotificationService::current()->Notify(NotificationType::APP_TERMINATING, | 289 NotificationService::current()->Notify(NotificationType::APP_TERMINATING, |
| 290 NotificationService::AllSources(), | 290 NotificationService::AllSources(), |
| 291 NotificationService::NoDetails()); | 291 NotificationService::NoDetails()); |
| 292 } | 292 } |
| 293 | 293 |
| 294 #if defined(OS_CHROMEOS) | 294 #if defined(OS_CHROMEOS) |
| 295 NotifyWindowManagerAboutSignout(); | |
| 295 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); | 296 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); |
| 296 if (cros_library->EnsureLoaded()) { | 297 if (cros_library->EnsureLoaded()) { |
| 297 // If update has been installed, reboot, otherwise, sign out. | 298 // If update has been installed, reboot, otherwise, sign out. |
| 298 if (cros_library->GetUpdateLibrary()->status().status == | 299 if (cros_library->GetUpdateLibrary()->status().status == |
| 299 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { | 300 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { |
| 300 cros_library->GetUpdateLibrary()->RebootAfterUpdate(); | 301 cros_library->GetUpdateLibrary()->RebootAfterUpdate(); |
| 301 } else { | 302 } else { |
| 302 cros_library->GetLoginLibrary()->StopSession(""); | 303 cros_library->GetLoginLibrary()->StopSession(""); |
| 303 } | 304 } |
| 304 return; | 305 return; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 362 } | 363 } |
| 363 | 364 |
| 364 // static | 365 // static |
| 365 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { | 366 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { |
| 366 observers_.RemoveObserver(observer); | 367 observers_.RemoveObserver(observer); |
| 367 } | 368 } |
| 368 | 369 |
| 369 // static | 370 // static |
| 370 void BrowserList::CloseAllBrowsers() { | 371 void BrowserList::CloseAllBrowsers() { |
| 371 bool session_ending = | 372 bool session_ending = |
| 372 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; | 373 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; |
|
achuithb
2011/06/29 20:46:57
session_ending is true when this function is calle
| |
| 373 bool force_exit = false; | 374 bool force_exit = false; |
| 374 #if defined(USE_X11) | 375 #if defined(USE_X11) |
| 375 if (session_ending) | 376 if (session_ending) |
| 376 force_exit = true; | 377 force_exit = true; |
|
achuithb
2011/06/29 20:46:57
force_exit is true
| |
| 377 #endif | 378 #endif |
| 378 // Tell everyone that we are shutting down. | 379 // Tell everyone that we are shutting down. |
| 379 browser_shutdown::SetTryingToQuit(true); | 380 browser_shutdown::SetTryingToQuit(true); |
| 380 | 381 |
| 381 // Before we close the browsers shutdown all session services. That way an | 382 // Before we close the browsers shutdown all session services. That way an |
| 382 // exit can restore all browsers open before exiting. | 383 // exit can restore all browsers open before exiting. |
| 383 ProfileManager::ShutdownSessionServices(); | 384 ProfileManager::ShutdownSessionServices(); |
| 384 | 385 |
| 385 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, | 386 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, |
| 386 // it will be sent by RemoveBrowser() when the last browser has closed. | 387 // it will be sent by RemoveBrowser() when the last browser has closed. |
| 387 if (force_exit || browsers_.empty()) { | 388 if (force_exit || browsers_.empty()) { |
| 388 NotifyAndTerminate(true); | 389 NotifyAndTerminate(true); |
| 389 return; | 390 return; |
|
achuithb
2011/06/29 20:46:57
We return here because force_exit is true. None of
| |
| 390 } | 391 } |
| 391 #if defined(OS_CHROMEOS) | 392 #if defined(OS_CHROMEOS) |
| 392 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( | 393 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( |
| 393 "StartedClosingWindows", false); | 394 "StartedClosingWindows", false); |
| 394 #endif | 395 #endif |
| 395 for (BrowserList::const_iterator i = BrowserList::begin(); | 396 for (BrowserList::const_iterator i = BrowserList::begin(); |
| 396 i != BrowserList::end();) { | 397 i != BrowserList::end();) { |
| 397 Browser* browser = *i; | 398 Browser* browser = *i; |
| 398 browser->window()->Close(); | 399 browser->window()->Close(); |
| 399 if (!session_ending) { | 400 if (!session_ending) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 429 chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted); | 430 chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted); |
| 430 | 431 |
| 431 // Login screen should show up in owner's locale. | 432 // Login screen should show up in owner's locale. |
| 432 PrefService* state = g_browser_process->local_state(); | 433 PrefService* state = g_browser_process->local_state(); |
| 433 if (state) { | 434 if (state) { |
| 434 std::string owner_locale = state->GetString(prefs::kOwnerLocale); | 435 std::string owner_locale = state->GetString(prefs::kOwnerLocale); |
| 435 if (!owner_locale.empty() && | 436 if (!owner_locale.empty() && |
| 436 state->GetString(prefs::kApplicationLocale) != owner_locale && | 437 state->GetString(prefs::kApplicationLocale) != owner_locale && |
| 437 !state->IsManagedPreference(prefs::kApplicationLocale)) { | 438 !state->IsManagedPreference(prefs::kApplicationLocale)) { |
| 438 state->SetString(prefs::kApplicationLocale, owner_locale); | 439 state->SetString(prefs::kApplicationLocale, owner_locale); |
| 439 state->ScheduleSavePersistentPrefs(); | 440 state->SavePersistentPrefs(); |
| 440 } | 441 } |
| 441 } | 442 } |
| 442 if (FastShutdown()) { | 443 if (FastShutdown()) |
| 443 return; | 444 return; |
| 444 } | |
| 445 #else | 445 #else |
| 446 // Reset the restart bit that might have been set in cancelled restart | 446 // Reset the restart bit that might have been set in cancelled restart |
| 447 // request. | 447 // request. |
| 448 PrefService* pref_service = g_browser_process->local_state(); | 448 PrefService* pref_service = g_browser_process->local_state(); |
| 449 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); | 449 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); |
| 450 #endif | 450 #endif |
| 451 AttemptExitInternal(); | 451 AttemptExitInternal(); |
| 452 } | 452 } |
| 453 | 453 |
| 454 // static | 454 // static |
| 455 void BrowserList::AttemptRestart() { | 455 void BrowserList::AttemptRestart() { |
| 456 #if defined(OS_CHROMEOS) | 456 #if defined(OS_CHROMEOS) |
| 457 // For CrOS instead of browser restart (which is not supported) perform a full | 457 // For CrOS instead of browser restart (which is not supported) perform a full |
| 458 // sign out. Session will be only restored if user has that setting set. | 458 // sign out. Session will be only restored if user has that setting set. |
| 459 // Same session restore behavior happens in case of full restart after update. | 459 // Same session restore behavior happens in case of full restart after update. |
| 460 AttemptUserExit(); | 460 AttemptUserExit(); |
| 461 #else | 461 #else |
| 462 // Set the flag to restore state after the restart. | 462 // Set the flag to restore state after the restart. |
| 463 PrefService* pref_service = g_browser_process->local_state(); | 463 PrefService* pref_service = g_browser_process->local_state(); |
| 464 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true); | 464 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true); |
| 465 AttemptExit(); | 465 AttemptExit(); |
| 466 #endif | 466 #endif |
| 467 } | 467 } |
| 468 | 468 |
| 469 // static | 469 // static |
| 470 void BrowserList::AttemptExit() { | 470 void BrowserList::AttemptExit() { |
| 471 // If we know that all browsers can be closed without blocking, | 471 // If we know that all browsers can be closed without blocking, |
| 472 // don't notify users of crashes beyond this point. | 472 // don't notify users of crashes beyond this point. Note that |
| 473 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit | 473 // MarkAsCleanShutdownInUserProfiles does not set UMA's exit cleanly |
| 474 // so crashes during shutdown are still reported in UMA. | 474 // bit so crashes during shutdown are still reported in UMA. |
| 475 if (AreAllBrowsersCloseable()) | 475 if (AreAllBrowsersCloseable()) |
| 476 MarkAsCleanShutdown(); | 476 MarkAsCleanShutdownInUserProfiles(); |
| 477 AttemptExitInternal(); | 477 AttemptExitInternal(); |
| 478 } | 478 } |
| 479 | 479 |
| 480 #if defined(OS_CHROMEOS) | |
| 481 // static | |
| 482 void BrowserList::ExitCleanly() { | |
| 483 // We always mark exit cleanly. | |
| 484 MarkAsCleanShutdown(); | |
| 485 AttemptExitInternal(); | |
| 486 } | |
| 487 #endif | |
| 488 | |
| 489 // static | 480 // static |
| 490 void BrowserList::SessionEnding() { | 481 void BrowserList::SessionEnding() { |
| 491 // EndSession is invoked once per frame. Only do something the first time. | 482 // EndSession is invoked once per frame. Only do something the first time. |
| 492 static bool already_ended = false; | 483 static bool already_ended = false; |
| 493 // We may get called in the middle of shutdown, e.g. http://crbug.com/70852 | 484 // We may get called in the middle of shutdown, e.g. http://crbug.com/70852 |
| 494 // In this case, do nothing. | 485 // In this case, do nothing. |
| 495 if (already_ended || !NotificationService::current()) | 486 if (already_ended || !NotificationService::current()) |
| 496 return; | 487 return; |
| 497 already_ended = true; | 488 already_ended = true; |
| 498 | 489 |
| 499 browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION); | 490 browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION); |
|
achuithb
2011/06/29 20:46:57
We set shutdown_type to END_SESSION here.
| |
| 500 | 491 |
| 501 NotificationService::current()->Notify( | 492 NotificationService::current()->Notify( |
| 502 NotificationType::APP_EXITING, | 493 NotificationType::APP_EXITING, |
| 503 NotificationService::AllSources(), | 494 NotificationService::AllSources(), |
| 504 NotificationService::NoDetails()); | 495 NotificationService::NoDetails()); |
| 505 | 496 |
| 506 // Write important data first. | 497 // Write important data first. |
| 507 g_browser_process->EndSession(); | 498 g_browser_process->EndSession(); |
| 508 | 499 |
| 509 BrowserList::CloseAllBrowsers(); | 500 BrowserList::CloseAllBrowsers(); |
|
achuithb
2011/06/29 20:46:57
This doesn't actually close any browser windows, a
| |
| 510 | 501 |
| 511 // Send out notification. This is used during testing so that the test harness | 502 // Send out notification. This is used during testing so that the test harness |
| 512 // can properly shutdown before we exit. | 503 // can properly shutdown before we exit. |
| 513 NotificationService::current()->Notify( | 504 NotificationService::current()->Notify( |
| 514 NotificationType::SESSION_END, | 505 NotificationType::SESSION_END, |
| 515 NotificationService::AllSources(), | 506 NotificationService::AllSources(), |
| 516 NotificationService::NoDetails()); | 507 NotificationService::NoDetails()); |
| 517 | 508 |
| 518 // And shutdown. | 509 // And shutdown. |
| 519 browser_shutdown::Shutdown(); | 510 browser_shutdown::Shutdown(); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 726 // If no more TabContents from Browsers, check the BackgroundPrintingManager. | 717 // If no more TabContents from Browsers, check the BackgroundPrintingManager. |
| 727 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { | 718 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { |
| 728 cur_ = *bg_printing_iterator_; | 719 cur_ = *bg_printing_iterator_; |
| 729 CHECK(cur_); | 720 CHECK(cur_); |
| 730 ++bg_printing_iterator_; | 721 ++bg_printing_iterator_; |
| 731 return; | 722 return; |
| 732 } | 723 } |
| 733 // Reached the end - no more TabContents. | 724 // Reached the end - no more TabContents. |
| 734 cur_ = NULL; | 725 cur_ = NULL; |
| 735 } | 726 } |
| OLD | NEW |