Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: chrome/browser/ui/browser_list.cc

Issue 8262009: Chrome OS: Shutdown without blocking when SIGTERM is received. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/chrome_browser_main_x11.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/chrome_browser_main_x11.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698