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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 (*i)->CheckDownloadsInProgress(&normal_downloads_are_present, | 195 (*i)->CheckDownloadsInProgress(&normal_downloads_are_present, |
196 &incognito_downloads_are_present); | 196 &incognito_downloads_are_present); |
197 if (normal_downloads_are_present || | 197 if (normal_downloads_are_present || |
198 incognito_downloads_are_present || | 198 incognito_downloads_are_present || |
199 (*i)->TabsNeedBeforeUnloadFired()) | 199 (*i)->TabsNeedBeforeUnloadFired()) |
200 return false; | 200 return false; |
201 } | 201 } |
202 return true; | 202 return true; |
203 } | 203 } |
204 | 204 |
| 205 // Emits APP_TERMINATING notification. It is guaranteed that the |
| 206 // notification is sent only once. |
| 207 void NotifyAppTerminating() { |
| 208 static bool notified = false; |
| 209 if (notified) |
| 210 return; |
| 211 notified = true; |
| 212 content::NotificationService::current()->Notify( |
| 213 content::NOTIFICATION_APP_TERMINATING, |
| 214 content::NotificationService::AllSources(), |
| 215 content::NotificationService::NoDetails()); |
| 216 } |
| 217 |
205 #if defined(OS_CHROMEOS) | 218 #if defined(OS_CHROMEOS) |
206 | 219 |
207 bool signout = false; | 220 // Whether a session manager requested to shutdown. |
| 221 bool g_session_manager_requested_shutdown = true; |
208 | 222 |
209 // Fast shutdown for ChromeOS. It tells session manager to start | 223 // Fast shutdown for ChromeOS. It tells session manager to start |
210 // shutdown process when closing browser windows won't be canceled. | 224 // shutdown process when closing browser windows won't be canceled. |
211 // Returns true if fast shutdown is successfully started. | 225 // Returns true if fast shutdown is successfully started. |
212 bool FastShutdown() { | 226 bool FastShutdown() { |
213 signout = true; | |
214 if (chromeos::CrosLibrary::Get()->EnsureLoaded() | 227 if (chromeos::CrosLibrary::Get()->EnsureLoaded() |
215 && AreAllBrowsersCloseable()) { | 228 && AreAllBrowsersCloseable()) { |
216 BrowserList::NotifyAndTerminate(true); | 229 BrowserList::NotifyAndTerminate(true); |
217 return true; | 230 return true; |
218 } | 231 } |
219 return false; | 232 return false; |
220 } | 233 } |
221 | 234 |
222 void NotifyWindowManagerAboutSignout() { | 235 void NotifyWindowManagerAboutSignout() { |
223 #if defined(TOOLKIT_USES_GTK) | 236 #if defined(TOOLKIT_USES_GTK) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 // On the Mac, the application continues to run once all windows are closed. | 294 // On the Mac, the application continues to run once all windows are closed. |
282 // Terminate will result in a CloseAllBrowsers() call, and once (and if) | 295 // Terminate will result in a CloseAllBrowsers() call, and once (and if) |
283 // that is done, will cause the application to exit cleanly. | 296 // that is done, will cause the application to exit cleanly. |
284 chrome_browser_application_mac::Terminate(); | 297 chrome_browser_application_mac::Terminate(); |
285 #endif | 298 #endif |
286 } | 299 } |
287 | 300 |
288 // static | 301 // static |
289 void BrowserList::NotifyAndTerminate(bool fast_path) { | 302 void BrowserList::NotifyAndTerminate(bool fast_path) { |
290 #if defined(OS_CHROMEOS) | 303 #if defined(OS_CHROMEOS) |
291 if (!signout) | 304 static bool notified = false; |
| 305 // Don't ask SessionManager to shutdown if |
| 306 // a) a shutdown request has already been sent. |
| 307 // b) shutdown request comes from session manager. |
| 308 if (notified || g_session_manager_requested_shutdown) |
292 return; | 309 return; |
| 310 notified = true; |
293 #endif | 311 #endif |
294 | 312 |
295 if (fast_path) { | 313 if (fast_path) |
296 content::NotificationService::current()->Notify( | 314 NotifyAppTerminating(); |
297 content::NOTIFICATION_APP_TERMINATING, | |
298 content::NotificationService::AllSources(), | |
299 content::NotificationService::NoDetails()); | |
300 } | |
301 | 315 |
302 #if defined(OS_CHROMEOS) | 316 #if defined(OS_CHROMEOS) |
303 NotifyWindowManagerAboutSignout(); | 317 NotifyWindowManagerAboutSignout(); |
304 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); | 318 chromeos::CrosLibrary* cros_library = chromeos::CrosLibrary::Get(); |
305 if (cros_library->EnsureLoaded()) { | 319 if (cros_library->EnsureLoaded()) { |
306 // If update has been installed, reboot, otherwise, sign out. | 320 // If update has been installed, reboot, otherwise, sign out. |
307 if (cros_library->GetUpdateLibrary()->status().status == | 321 if (cros_library->GetUpdateLibrary()->status().status == |
308 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { | 322 chromeos::UPDATE_STATUS_UPDATED_NEED_REBOOT) { |
309 cros_library->GetUpdateLibrary()->RebootAfterUpdate(); | 323 cros_library->GetUpdateLibrary()->RebootAfterUpdate(); |
310 } else { | 324 } else { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 // If we're exiting, send out the APP_TERMINATING notification to allow other | 367 // If we're exiting, send out the APP_TERMINATING notification to allow other |
354 // modules to shut themselves down. | 368 // modules to shut themselves down. |
355 if (browsers_.empty() && | 369 if (browsers_.empty() && |
356 (browser_shutdown::IsTryingToQuit() || | 370 (browser_shutdown::IsTryingToQuit() || |
357 g_browser_process->IsShuttingDown())) { | 371 g_browser_process->IsShuttingDown())) { |
358 // Last browser has just closed, and this is a user-initiated quit or there | 372 // Last browser has just closed, and this is a user-initiated quit or there |
359 // is no module keeping the app alive, so send out our notification. No need | 373 // is no module keeping the app alive, so send out our notification. No need |
360 // to call ProfileManager::ShutdownSessionServices() as part of the | 374 // to call ProfileManager::ShutdownSessionServices() as part of the |
361 // shutdown, because Browser::WindowClosing() already makes sure that the | 375 // shutdown, because Browser::WindowClosing() already makes sure that the |
362 // SessionService is created and notified. | 376 // SessionService is created and notified. |
363 content::NotificationService::current()->Notify( | 377 NotifyAppTerminating(); |
364 content::NOTIFICATION_APP_TERMINATING, | |
365 content::NotificationService::AllSources(), | |
366 content::NotificationService::NoDetails()); | |
367 AllBrowsersClosedAndAppExiting(); | 378 AllBrowsersClosedAndAppExiting(); |
368 } | 379 } |
369 } | 380 } |
370 | 381 |
371 // static | 382 // static |
372 void BrowserList::AddObserver(BrowserList::Observer* observer) { | 383 void BrowserList::AddObserver(BrowserList::Observer* observer) { |
373 observers_.AddObserver(observer); | 384 observers_.AddObserver(observer); |
374 } | 385 } |
375 | 386 |
376 // static | 387 // static |
377 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { | 388 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { |
378 observers_.RemoveObserver(observer); | 389 observers_.RemoveObserver(observer); |
379 } | 390 } |
380 | 391 |
381 // static | 392 // static |
382 void BrowserList::CloseAllBrowsers() { | 393 void BrowserList::CloseAllBrowsers() { |
383 bool session_ending = | 394 bool session_ending = |
384 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; | 395 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; |
385 bool force_exit = false; | |
386 #if defined(USE_X11) | |
387 if (session_ending) | |
388 force_exit = true; | |
389 #endif | |
390 // Tell everyone that we are shutting down. | 396 // Tell everyone that we are shutting down. |
391 browser_shutdown::SetTryingToQuit(true); | 397 browser_shutdown::SetTryingToQuit(true); |
392 | 398 |
393 // Before we close the browsers shutdown all session services. That way an | 399 // Before we close the browsers shutdown all session services. That way an |
394 // exit can restore all browsers open before exiting. | 400 // exit can restore all browsers open before exiting. |
395 ProfileManager::ShutdownSessionServices(); | 401 ProfileManager::ShutdownSessionServices(); |
396 | 402 |
397 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, | 403 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, |
398 // it will be sent by RemoveBrowser() when the last browser has closed. | 404 // it will be sent by RemoveBrowser() when the last browser has closed. |
399 if (force_exit || browsers_.empty()) { | 405 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() || |
| 406 browsers_.empty()) { |
400 NotifyAndTerminate(true); | 407 NotifyAndTerminate(true); |
401 return; | 408 return; |
402 } | 409 } |
| 410 |
403 #if defined(OS_CHROMEOS) | 411 #if defined(OS_CHROMEOS) |
404 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( | 412 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( |
405 "StartedClosingWindows", false); | 413 "StartedClosingWindows", false); |
406 #endif | 414 #endif |
407 for (BrowserList::const_iterator i = BrowserList::begin(); | 415 for (BrowserList::const_iterator i = BrowserList::begin(); |
408 i != BrowserList::end();) { | 416 i != BrowserList::end();) { |
409 Browser* browser = *i; | 417 Browser* browser = *i; |
410 browser->window()->Close(); | 418 browser->window()->Close(); |
411 if (!session_ending) { | 419 if (!session_ending) { |
412 ++i; | 420 ++i; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 PrefService* state = g_browser_process->local_state(); | 468 PrefService* state = g_browser_process->local_state(); |
461 if (state) { | 469 if (state) { |
462 std::string owner_locale = state->GetString(prefs::kOwnerLocale); | 470 std::string owner_locale = state->GetString(prefs::kOwnerLocale); |
463 if (!owner_locale.empty() && | 471 if (!owner_locale.empty() && |
464 state->GetString(prefs::kApplicationLocale) != owner_locale && | 472 state->GetString(prefs::kApplicationLocale) != owner_locale && |
465 !state->IsManagedPreference(prefs::kApplicationLocale)) { | 473 !state->IsManagedPreference(prefs::kApplicationLocale)) { |
466 state->SetString(prefs::kApplicationLocale, owner_locale); | 474 state->SetString(prefs::kApplicationLocale, owner_locale); |
467 state->SavePersistentPrefs(); | 475 state->SavePersistentPrefs(); |
468 } | 476 } |
469 } | 477 } |
| 478 g_session_manager_requested_shutdown = false; |
470 if (FastShutdown()) | 479 if (FastShutdown()) |
471 return; | 480 return; |
472 #else | 481 #else |
473 // Reset the restart bit that might have been set in cancelled restart | 482 // Reset the restart bit that might have been set in cancelled restart |
474 // request. | 483 // request. |
475 PrefService* pref_service = g_browser_process->local_state(); | 484 PrefService* pref_service = g_browser_process->local_state(); |
476 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); | 485 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); |
477 #endif | 486 #endif |
478 AttemptExitInternal(); | 487 AttemptExitInternal(); |
479 } | 488 } |
(...skipping 18 matching lines...) Expand all Loading... |
498 // If we know that all browsers can be closed without blocking, | 507 // If we know that all browsers can be closed without blocking, |
499 // don't notify users of crashes beyond this point. | 508 // don't notify users of crashes beyond this point. |
500 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit | 509 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit |
501 // so crashes during shutdown are still reported in UMA. | 510 // so crashes during shutdown are still reported in UMA. |
502 if (AreAllBrowsersCloseable()) | 511 if (AreAllBrowsersCloseable()) |
503 MarkAsCleanShutdown(); | 512 MarkAsCleanShutdown(); |
504 AttemptExitInternal(); | 513 AttemptExitInternal(); |
505 } | 514 } |
506 | 515 |
507 #if defined(OS_CHROMEOS) | 516 #if defined(OS_CHROMEOS) |
| 517 // A function called when SIGTERM is received. |
508 // static | 518 // static |
509 void BrowserList::ExitCleanly() { | 519 void BrowserList::ExitCleanly() { |
510 // We always mark exit cleanly. | 520 // We always mark exit cleanly because SessionManager may kill |
| 521 // chrome in 3 seconds after SIGTERM. |
511 g_browser_process->EndSession(); | 522 g_browser_process->EndSession(); |
| 523 |
| 524 // Don't block when SIGTERM is received. AreaAllBrowsersCloseable() |
| 525 // can be false in following cases. a) power-off b) signout from |
| 526 // screen locker. |
| 527 if (!AreAllBrowsersCloseable()) |
| 528 browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION); |
512 AttemptExitInternal(); | 529 AttemptExitInternal(); |
513 } | 530 } |
514 #endif | 531 #endif |
515 | 532 |
516 static void TimeLimitedSessionEnding() { | 533 static void TimeLimitedSessionEnding() { |
517 // Start watching for hang during shutdown, and crash it if takes too long. | 534 // Start watching for hang during shutdown, and crash it if takes too long. |
518 // We disarm when |shutdown_watcher| object is destroyed, which is when we | 535 // We disarm when |shutdown_watcher| object is destroyed, which is when we |
519 // exit this function. | 536 // exit this function. |
520 ShutdownWatcherHelper shutdown_watcher; | 537 ShutdownWatcherHelper shutdown_watcher; |
521 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90)); | 538 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90)); |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 // If no more TabContents from Browsers, check the BackgroundPrintingManager. | 807 // If no more TabContents from Browsers, check the BackgroundPrintingManager. |
791 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { | 808 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { |
792 cur_ = *bg_printing_iterator_; | 809 cur_ = *bg_printing_iterator_; |
793 CHECK(cur_); | 810 CHECK(cur_); |
794 ++bg_printing_iterator_; | 811 ++bg_printing_iterator_; |
795 return; | 812 return; |
796 } | 813 } |
797 // Reached the end - no more TabContents. | 814 // Reached the end - no more TabContents. |
798 cur_ = NULL; | 815 cur_ = NULL; |
799 } | 816 } |
OLD | NEW |