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

Unified Diff: chrome/browser/ui/browser_list.cc

Issue 10409022: Move application lifetime functionality off BrowserList. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/ui/browser_list.h ('k') | chrome/browser/ui/browser_list_aura.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/ui/browser_list.cc
===================================================================
--- chrome/browser/ui/browser_list.cc (revision 137868)
+++ chrome/browser/ui/browser_list.cc (working copy)
@@ -6,17 +6,14 @@
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
-#include "chrome/browser/download/download_service.h"
-#include "chrome/browser/metrics/thread_watcher.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/printing/background_printing_manager.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
@@ -31,17 +28,8 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/common/result_codes.h"
-#if defined(OS_MACOSX)
-#include "chrome/browser/chrome_browser_application_mac.h"
-#endif
-
#if defined(OS_CHROMEOS)
-#include "base/chromeos/chromeos_version.h"
-#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/login/user_manager.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/session_manager_client.h"
-#include "chromeos/dbus/update_engine_client.h"
#endif
using content::WebContents;
@@ -56,6 +44,8 @@
BrowserActivityObserver() {
registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
content::NotificationService::AllSources());
+ registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
+ content::NotificationService::AllSources());
}
~BrowserActivityObserver() {}
@@ -64,14 +54,17 @@
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK(type == content::NOTIFICATION_NAV_ENTRY_COMMITTED);
- const content::LoadCommittedDetails& load =
- *content::Details<content::LoadCommittedDetails>(details).ptr();
- if (!load.is_navigation_to_different_page())
- return; // Don't log for subframes or other trivial types.
+ if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
+ const content::LoadCommittedDetails& load =
+ *content::Details<content::LoadCommittedDetails>(details).ptr();
+ if (!load.is_navigation_to_different_page())
+ return; // Don't log for subframes or other trivial types.
- LogRenderProcessHostCount();
- LogBrowserTabCount();
+ LogRenderProcessHostCount();
+ LogBrowserTabCount();
+ } else if (type == content::NOTIFICATION_APP_TERMINATING) {
+ delete this;
+ }
}
// Counts the number of active RenderProcessHosts and logs them.
@@ -136,44 +129,6 @@
return g_browser_process->background_printing_manager();
}
-// Returns true if all browsers can be closed without user interaction.
-// This currently checks if there is pending download, or if it needs to
-// handle unload handler.
-bool AreAllBrowsersCloseable() {
- BrowserList::const_iterator browser_it = BrowserList::begin();
- if (browser_it == BrowserList::end())
- return true;
-
- // If there are any downloads active, all browsers are not closeable.
- if (DownloadService::DownloadCountAllProfiles() > 0)
- return false;
-
- // Check TabsNeedBeforeUnloadFired().
- for (; browser_it != BrowserList::end(); ++browser_it) {
- if ((*browser_it)->TabsNeedBeforeUnloadFired())
- return false;
- }
- return true;
-}
-
-// Emits APP_TERMINATING notification. It is guaranteed that the
-// notification is sent only once.
-void NotifyAppTerminating() {
- static bool notified = false;
- if (notified)
- return;
- notified = true;
- content::NotificationService::current()->Notify(
- content::NOTIFICATION_APP_TERMINATING,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
-}
-
-#if defined(OS_CHROMEOS)
-// Whether a session manager requested to shutdown.
-bool g_session_manager_requested_shutdown = true;
-#endif
-
} // namespace
// static
@@ -200,78 +155,6 @@
}
// static
-void BrowserList::MarkAsCleanShutdown() {
- for (const_iterator i = begin(); i != end(); ++i) {
- (*i)->profile()->MarkAsCleanShutdown();
- }
-}
-
-void BrowserList::AttemptExitInternal() {
- content::NotificationService::current()->Notify(
- content::NOTIFICATION_APP_EXITING,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
-
-#if !defined(OS_MACOSX)
- // On most platforms, closing all windows causes the application to exit.
- CloseAllBrowsers();
-#else
- // On the Mac, the application continues to run once all windows are closed.
- // Terminate will result in a CloseAllBrowsers() call, and once (and if)
- // that is done, will cause the application to exit cleanly.
- chrome_browser_application_mac::Terminate();
-#endif
-}
-
-// static
-void BrowserList::NotifyAndTerminate(bool fast_path) {
-#if defined(OS_CHROMEOS)
- static bool notified = false;
- // Don't ask SessionManager to shutdown if
- // a) a shutdown request has already been sent.
- // b) shutdown request comes from session manager.
- if (notified || g_session_manager_requested_shutdown)
- return;
- notified = true;
-#endif
-
- if (fast_path)
- NotifyAppTerminating();
-
-#if defined(OS_CHROMEOS)
- if (base::chromeos::IsRunningOnChromeOS()) {
- // If we're on a ChromeOS device, reboot if an update has been applied,
- // or else signal the session manager to log out.
- chromeos::UpdateEngineClient* update_engine_client
- = chromeos::DBusThreadManager::Get()->GetUpdateEngineClient();
- if (update_engine_client->GetLastStatus().status ==
- chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
- update_engine_client->RebootAfterUpdate();
- } else {
- chromeos::DBusThreadManager::Get()->GetSessionManagerClient()
- ->StopSession();
- }
- } else {
- // If running the Chrome OS build, but we're not on the device, act
- // as if we received signal from SessionManager.
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&BrowserList::ExitCleanly));
- }
-#endif
-}
-
-void BrowserList::OnAppExiting() {
- static bool notified = false;
- if (notified)
- return;
- notified = true;
-
- delete activity_observer;
- activity_observer = NULL;
- HandleAppExitingForPlatform();
-}
-
-// static
void BrowserList::RemoveBrowser(Browser* browser) {
RemoveBrowserFrom(browser, &last_active_browsers());
@@ -319,8 +202,8 @@
// to call ProfileManager::ShutdownSessionServices() as part of the
// shutdown, because Browser::WindowClosing() already makes sure that the
// SessionService is created and notified.
- NotifyAppTerminating();
- OnAppExiting();
+ browser::NotifyAppTerminating();
+ browser::OnAppExiting();
}
}
@@ -334,58 +217,6 @@
observers().RemoveObserver(observer);
}
-// static
-void BrowserList::CloseAllBrowsers() {
- bool session_ending =
- browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION;
- // Tell everyone that we are shutting down.
- browser_shutdown::SetTryingToQuit(true);
-
- // Before we close the browsers shutdown all session services. That way an
- // exit can restore all browsers open before exiting.
- ProfileManager::ShutdownSessionServices();
-
- // If there are no browsers, send the APP_TERMINATING action here. Otherwise,
- // it will be sent by RemoveBrowser() when the last browser has closed.
- if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() ||
- browsers().empty()) {
- NotifyAndTerminate(true);
- OnAppExiting();
- return;
- }
-
-#if defined(OS_CHROMEOS)
- chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
- "StartedClosingWindows", false);
-#endif
- for (BrowserList::const_iterator i = BrowserList::begin();
- i != BrowserList::end();) {
- Browser* browser = *i;
- browser->window()->Close();
- if (!session_ending) {
- ++i;
- } else {
- // This path is hit during logoff/power-down. In this case we won't get
- // a final message and so we force the browser to be deleted.
- // Close doesn't immediately destroy the browser
- // (Browser::TabStripEmpty() uses invoke later) but when we're ending the
- // session we need to make sure the browser is destroyed now. So, invoke
- // DestroyBrowser to make sure the browser is deleted and cleanup can
- // happen.
- while (browser->tab_count())
- delete browser->GetTabContentsWrapperAt(0);
- browser->window()->DestroyBrowser();
- i = BrowserList::begin();
- if (i != BrowserList::end() && browser == *i) {
- // Destroying the browser should have removed it from the browser list.
- // We should never get here.
- NOTREACHED();
- return;
- }
- }
- }
-}
-
void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) {
BrowserVector browsers_to_close;
for (BrowserList::const_iterator i = BrowserList::begin();
@@ -401,172 +232,6 @@
}
// static
-void BrowserList::AttemptUserExit() {
-#if defined(OS_CHROMEOS)
- chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutStarted", false);
- // Write /tmp/uptime-logout-started as well.
- const char kLogoutStarted[] = "logout-started";
- chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted);
-
- // Login screen should show up in owner's locale.
- PrefService* state = g_browser_process->local_state();
- if (state) {
- std::string owner_locale = state->GetString(prefs::kOwnerLocale);
- if (!owner_locale.empty() &&
- state->GetString(prefs::kApplicationLocale) != owner_locale &&
- !state->IsManagedPreference(prefs::kApplicationLocale)) {
- state->SetString(prefs::kApplicationLocale, owner_locale);
- state->CommitPendingWrite();
- }
- }
- g_session_manager_requested_shutdown = false;
- // On ChromeOS, always terminate the browser, regardless of the result of
- // AreAllBrowsersCloseable(). See crbug.com/123107.
- BrowserList::NotifyAndTerminate(true);
-#else
- // Reset the restart bit that might have been set in cancelled restart
- // request.
- PrefService* pref_service = g_browser_process->local_state();
- pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false);
- AttemptExitInternal();
-#endif
-}
-
-// static
-void BrowserList::AttemptRestart() {
- if (!CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableRestoreSessionState)) {
- BrowserVector::const_iterator it;
- for (it = begin(); it != end(); ++it)
- content::BrowserContext::SaveSessionState((*it)->profile());
- }
-
- PrefService* pref_service = g_browser_process->local_state();
- pref_service->SetBoolean(prefs::kWasRestarted, true);
-
-#if defined(OS_CHROMEOS)
- // For CrOS instead of browser restart (which is not supported) perform a full
- // sign out. Session will be only restored if user has that setting set.
- // Same session restore behavior happens in case of full restart after update.
- AttemptUserExit();
-#else
- // Set the flag to restore state after the restart.
- pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true);
- AttemptExit();
-#endif
-}
-
-// static
-void BrowserList::AttemptExit() {
- // If we know that all browsers can be closed without blocking,
- // don't notify users of crashes beyond this point.
- // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit
- // so crashes during shutdown are still reported in UMA.
- if (AreAllBrowsersCloseable())
- MarkAsCleanShutdown();
- AttemptExitInternal();
-}
-
-#if defined(OS_CHROMEOS)
-// A function called when SIGTERM is received.
-// static
-void BrowserList::ExitCleanly() {
- // We always mark exit cleanly because SessionManager may kill
- // chrome in 3 seconds after SIGTERM.
- g_browser_process->EndSession();
-
- // Don't block when SIGTERM is received. AreaAllBrowsersCloseable()
- // can be false in following cases. a) power-off b) signout from
- // screen locker.
- if (!AreAllBrowsersCloseable())
- browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
- AttemptExitInternal();
-}
-#endif
-
-// static
-void BrowserList::SessionEnding() {
- // This is a time-limited shutdown where we need to write as much to
- // disk as we can as soon as we can, and where we must kill the
- // process within a hang timeout to avoid user prompts.
-
- // Start watching for hang during shutdown, and crash it if takes too long.
- // We disarm when |shutdown_watcher| object is destroyed, which is when we
- // exit this function.
- ShutdownWatcherHelper shutdown_watcher;
- shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90));
-
- // EndSession is invoked once per frame. Only do something the first time.
- static bool already_ended = false;
- // We may get called in the middle of shutdown, e.g. http://crbug.com/70852
- // In this case, do nothing.
- if (already_ended || !content::NotificationService::current())
- return;
- already_ended = true;
-
- browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
-
- content::NotificationService::current()->Notify(
- content::NOTIFICATION_APP_EXITING,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
-
- // Write important data first.
- g_browser_process->EndSession();
-
- BrowserList::CloseAllBrowsers();
-
- // Send out notification. This is used during testing so that the test harness
- // can properly shutdown before we exit.
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_SESSION_END,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
-
- // This will end by terminating the process.
- content::ImmediateShutdownAndExitProcess();
-}
-
-// static
-int BrowserList::keep_alive_count_ = 0;
-
-// static
-void BrowserList::StartKeepAlive() {
- // Increment the browser process refcount as long as we're keeping the
- // application alive.
- if (!WillKeepAlive())
- g_browser_process->AddRefModule();
- keep_alive_count_++;
-}
-
-// static
-void BrowserList::EndKeepAlive() {
- DCHECK_GT(keep_alive_count_, 0);
- keep_alive_count_--;
-
- DCHECK(g_browser_process);
- // Although we should have a browser process, if there is none,
- // there is nothing to do.
- if (!g_browser_process) return;
-
- // Allow the app to shutdown again.
- if (!WillKeepAlive()) {
- g_browser_process->ReleaseModule();
- // If there are no browsers open and we aren't already shutting down,
- // initiate a shutdown. Also skips shutdown if this is a unit test
- // (MessageLoop::current() == null).
- if (browsers().empty() && !browser_shutdown::IsTryingToQuit() &&
- MessageLoop::current())
- CloseAllBrowsers();
- }
-}
-
-// static
-bool BrowserList::WillKeepAlive() {
- return keep_alive_count_ > 0;
-}
-
-// static
BrowserList::const_iterator BrowserList::begin() {
return browsers().begin();
}
« no previous file with comments | « chrome/browser/ui/browser_list.h ('k') | chrome/browser/ui/browser_list_aura.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698