This source file includes following definitions.
- AreAllBrowsersCloseable
- MarkAsCleanShutdown
- AttemptExitInternal
- CloseAllBrowsersAndQuit
- CloseAllBrowsers
- AttemptUserExit
- StartShutdownTracing
- AttemptRestart
- AttemptExit
- ExitCleanly
- SessionEnding
- IncrementKeepAliveCount
- DecrementKeepAliveCount
- WillKeepAlive
- NotifyAppTerminating
- NotifyAndTerminate
- OnAppExiting
- ShouldStartShutdown
#include "chrome/browser/lifetime/application_lifetime.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/prefs/pref_service.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/download/download_service.h"
#include "chrome/browser/lifetime/browser_close_manager.h"
#include "chrome/browser/metrics/thread_watcher.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_finder.h"
#include "chrome/browser/ui/browser_iterator.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_shutdown.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/notification_service.h"
#if defined(OS_CHROMEOS)
#include "base/sys_info.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
#if defined(OS_WIN)
#include "base/win/win_util.h"
#endif
namespace chrome {
namespace {
#if !defined(OS_ANDROID)
bool AreAllBrowsersCloseable() {
chrome::BrowserIterator browser_it;
if (browser_it.done())
return true;
if (DownloadService::NonMaliciousDownloadCountAllProfiles() > 0)
return false;
for (; !browser_it.done(); browser_it.Next()) {
if (browser_it->TabsNeedBeforeUnloadFired())
return false;
}
return true;
}
#endif
int g_keep_alive_count = 0;
#if defined(OS_CHROMEOS)
bool g_send_stop_request_to_session_manager = false;
#endif
}
void MarkAsCleanShutdown() {
for (chrome::BrowserIterator it; !it.done(); it.Next())
it->profile()->SetExitType(Profile::EXIT_NORMAL);
}
void AttemptExitInternal(bool try_to_quit_application) {
#if !defined(OS_MACOSX)
if (try_to_quit_application)
browser_shutdown::SetTryingToQuit(true);
#endif
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
g_browser_process->platform_part()->AttemptExit();
}
void CloseAllBrowsersAndQuit() {
browser_shutdown::SetTryingToQuit(true);
CloseAllBrowsers();
}
void CloseAllBrowsers() {
if (chrome::GetTotalBrowserCount() == 0 &&
(browser_shutdown::IsTryingToQuit() || !chrome::WillKeepAlive())) {
browser_shutdown::SetTryingToQuit(true);
#if defined(ENABLE_SESSION_SERVICE)
ProfileManager::ShutdownSessionServices();
#endif
chrome::NotifyAndTerminate(true);
chrome::OnAppExiting();
return;
}
#if defined(OS_CHROMEOS)
chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
"StartedClosingWindows", false);
#endif
scoped_refptr<BrowserCloseManager> browser_close_manager =
new BrowserCloseManager;
browser_close_manager->StartClosingBrowsers();
}
void AttemptUserExit() {
#if defined(OS_CHROMEOS)
StartShutdownTracing();
chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutStarted", false);
const char kLogoutStarted[] = "logout-started";
chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted);
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);
TRACE_EVENT0("shutdown", "CommitPendingWrite");
state->CommitPendingWrite();
}
}
g_send_stop_request_to_session_manager = true;
chrome::NotifyAndTerminate(true);
#else
PrefService* pref_service = g_browser_process->local_state();
pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false);
AttemptExitInternal(false);
#endif
}
void StartShutdownTracing() {
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kTraceShutdown)) {
base::debug::CategoryFilter category_filter(
command_line.GetSwitchValueASCII(switches::kTraceShutdown));
base::debug::TraceLog::GetInstance()->SetEnabled(
category_filter,
base::debug::TraceLog::RECORDING_MODE,
base::debug::TraceLog::RECORD_UNTIL_FULL);
}
TRACE_EVENT0("shutdown", "StartShutdownTracing");
}
#if !defined(OS_ANDROID)
void AttemptRestart() {
for (chrome::BrowserIterator it; !it.done(); it.Next())
content::BrowserContext::SaveSessionState(it->profile());
PrefService* pref_service = g_browser_process->local_state();
pref_service->SetBoolean(prefs::kWasRestarted, true);
#if defined(OS_CHROMEOS)
DCHECK(!g_send_stop_request_to_session_manager);
g_send_stop_request_to_session_manager = false;
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&ExitCleanly));
#else
pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true);
AttemptExit();
#endif
}
#endif
void AttemptExit() {
#if defined(OS_CHROMEOS)
AttemptUserExit();
#else
#if !defined(OS_ANDROID)
if (AreAllBrowsersCloseable())
MarkAsCleanShutdown();
#endif
AttemptExitInternal(true);
#endif
}
#if defined(OS_CHROMEOS)
void ExitCleanly() {
g_browser_process->EndSession();
if (!AreAllBrowsersCloseable())
browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
else
browser_shutdown::OnShutdownStarting(browser_shutdown::BROWSER_EXIT);
AttemptExitInternal(true);
}
#endif
void SessionEnding() {
ShutdownWatcherHelper shutdown_watcher;
shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90));
static bool already_ended = false;
if (already_ended || !content::NotificationService::current())
return;
already_ended = true;
browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
g_browser_process->EndSession();
CloseAllBrowsers();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_SESSION_END,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
#if defined(OS_WIN)
base::win::SetShouldCrashOnProcessDetach(false);
#endif
content::ImmediateShutdownAndExitProcess();
}
void IncrementKeepAliveCount() {
if (!WillKeepAlive())
g_browser_process->AddRefModule();
++g_keep_alive_count;
}
void DecrementKeepAliveCount() {
DCHECK_GT(g_keep_alive_count, 0);
--g_keep_alive_count;
DCHECK(g_browser_process);
if (!g_browser_process) return;
if (!WillKeepAlive()) {
g_browser_process->ReleaseModule();
if (chrome::GetTotalBrowserCount() == 0 &&
!browser_shutdown::IsTryingToQuit() &&
base::MessageLoop::current()) {
CloseAllBrowsers();
}
}
}
bool WillKeepAlive() {
return g_keep_alive_count > 0;
}
void NotifyAppTerminating() {
static bool notified = false;
if (notified)
return;
notified = true;
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_APP_TERMINATING,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
}
void NotifyAndTerminate(bool fast_path) {
#if defined(OS_CHROMEOS)
static bool notified = false;
if (notified)
return;
notified = true;
#endif
if (fast_path)
NotifyAppTerminating();
#if defined(OS_CHROMEOS)
if (base::SysInfo::IsRunningOnChromeOS()) {
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 if (g_send_stop_request_to_session_manager) {
chromeos::DBusThreadManager::Get()->GetSessionManagerClient()
->StopSession();
}
} else {
if (g_send_stop_request_to_session_manager) {
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&ExitCleanly));
}
}
#endif
}
void OnAppExiting() {
static bool notified = false;
if (notified)
return;
notified = true;
HandleAppExitingForPlatform();
}
bool ShouldStartShutdown(Browser* browser) {
if (BrowserList::GetInstance(browser->host_desktop_type())->size() > 1)
return false;
#if defined(OS_WIN)
if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_NATIVE)
return !ash::Shell::HasInstance();
else if (browser->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH)
return BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE)->empty();
#endif
return true;
}
}