| 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();
|
| }
|
|
|