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 |