| Index: chrome/browser/lifetime/application_lifetime_desktop.cc
|
| diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime_desktop.cc
|
| similarity index 67%
|
| copy from chrome/browser/lifetime/application_lifetime.cc
|
| copy to chrome/browser/lifetime/application_lifetime_desktop.cc
|
| index 1986d1b3a5c44e9159c4943b7a1919cb8b1c3d0a..fd83411d42d6deffaf757a4033d41644afd171f8 100644
|
| --- a/chrome/browser/lifetime/application_lifetime.cc
|
| +++ b/chrome/browser/lifetime/application_lifetime_desktop.cc
|
| @@ -1,24 +1,20 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "chrome/browser/lifetime/application_lifetime.h"
|
| +#include "chrome/browser/lifetime/application_lifetime_desktop.h"
|
|
|
| -#include "base/bind.h"
|
| -#include "base/command_line.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 "base/process/process.h"
|
| #include "base/process/process_handle.h"
|
| #include "base/trace_event/trace_event.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/application_lifetime.h"
|
| +#include "chrome/browser/lifetime/application_lifetime_internal.h"
|
| #include "chrome/browser/lifetime/browser_close_manager.h"
|
| #include "chrome/browser/metrics/thread_watcher.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| @@ -26,39 +22,30 @@
|
| #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/browser/ui/user_manager.h"
|
| #include "chrome/common/chrome_constants.h"
|
| -#include "chrome/common/chrome_switches.h"
|
| #include "chrome/common/pref_names.h"
|
| -#include "components/tracing/tracing_switches.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/bind.h"
|
| #include "base/sys_info.h"
|
| #include "chrome/browser/chromeos/boot_times_recorder.h"
|
| #include "chromeos/dbus/dbus_thread_manager.h"
|
| #include "chromeos/dbus/session_manager_client.h"
|
| #include "chromeos/dbus/update_engine_client.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| #endif
|
|
|
| #if defined(OS_WIN)
|
| -#include "base/win/win_util.h"
|
| -#include "components/browser_watcher/exit_funnel_win.h"
|
| -#endif
|
| -
|
| -#if defined(USE_ASH)
|
| #include "ash/shell.h"
|
| +#include "base/win/win_util.h"
|
| #endif
|
|
|
| namespace chrome {
|
| +
|
| namespace {
|
|
|
| -#if !defined(OS_ANDROID)
|
| // 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.
|
| @@ -79,7 +66,6 @@ bool AreAllBrowsersCloseable() {
|
| }
|
| return true;
|
| }
|
| -#endif // !defined(OS_ANDROID)
|
|
|
| int g_keep_alive_count = 0;
|
| bool g_disable_shutdown_for_testing = false;
|
| @@ -89,28 +75,60 @@ bool g_disable_shutdown_for_testing = false;
|
| bool g_send_stop_request_to_session_manager = false;
|
| #endif
|
|
|
| -} // namespace
|
| -
|
| void MarkAsCleanShutdown() {
|
| // TODO(beng): Can this use ProfileManager::GetLoadedProfiles() instead?
|
| for (chrome::BrowserIterator it; !it.done(); it.Next())
|
| it->profile()->SetExitType(Profile::EXIT_NORMAL);
|
| }
|
|
|
| -void AttemptExitInternal(bool try_to_quit_application) {
|
| - // On Mac, the platform-specific part handles setting this.
|
| -#if !defined(OS_MACOSX)
|
| - if (try_to_quit_application)
|
| - browser_shutdown::SetTryingToQuit(true);
|
| -#endif
|
| +void CloseAllBrowsersIfNeeded() {
|
| + // 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 or explicitly disabled).
|
| + if (chrome::GetTotalBrowserCount() == 0 &&
|
| + !browser_shutdown::IsTryingToQuit() && base::MessageLoop::current() &&
|
| + !g_disable_shutdown_for_testing) {
|
| + CloseAllBrowsers();
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
|
|
| - content::NotificationService::current()->Notify(
|
| - chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
|
| - content::NotificationService::AllSources(),
|
| - content::NotificationService::NoDetails());
|
| +namespace internal {
|
|
|
| - g_browser_process->platform_part()->AttemptExit();
|
| +#if defined(OS_CHROMEOS)
|
| +void NotifyAndTerminateInternalCrOS() {
|
| + if (base::SysInfo::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 if (g_send_stop_request_to_session_manager) {
|
| + // Don't ask SessionManager to stop session if the shutdown request comes
|
| + // from session manager.
|
| + chromeos::DBusThreadManager::Get()->GetSessionManagerClient()
|
| + ->StopSession();
|
| + }
|
| + } else {
|
| + if (g_send_stop_request_to_session_manager) {
|
| + // 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(&ExitCleanly));
|
| + }
|
| + }
|
| }
|
| +#else
|
| +void AttemptExitInternalDesktop() {
|
| + if (AreAllBrowsersCloseable())
|
| + MarkAsCleanShutdown();
|
| +}
|
| +#endif
|
| +
|
| +} // namespace internal
|
|
|
| void CloseAllBrowsersAndQuit() {
|
| browser_shutdown::SetTryingToQuit(true);
|
| @@ -177,25 +195,11 @@ void AttemptUserExit() {
|
| UserManager::Hide();
|
| PrefService* pref_service = g_browser_process->local_state();
|
| pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false);
|
| - AttemptExitInternal(false);
|
| -#endif
|
| -}
|
| -
|
| -void StartShutdownTracing() {
|
| - const base::CommandLine& command_line =
|
| - *base::CommandLine::ForCurrentProcess();
|
| - if (command_line.HasSwitch(switches::kTraceShutdown)) {
|
| - base::trace_event::TraceConfig trace_config(
|
| - command_line.GetSwitchValueASCII(switches::kTraceShutdown), "");
|
| - base::trace_event::TraceLog::GetInstance()->SetEnabled(
|
| - trace_config,
|
| - base::trace_event::TraceLog::RECORDING_MODE);
|
| - }
|
| - TRACE_EVENT0("shutdown", "StartShutdownTracing");
|
| + internal::AttemptExitInternal(false);
|
| +#endif // defined(OS_CHROMEOS)
|
| }
|
|
|
| // The Android implementation is in application_lifetime_android.cc
|
| -#if !defined(OS_ANDROID)
|
| void AttemptRestart() {
|
| // TODO(beng): Can this use ProfileManager::GetLoadedProfiles instead?
|
| for (chrome::BrowserIterator it; !it.done(); it.Next())
|
| @@ -219,25 +223,6 @@ void AttemptRestart() {
|
| AttemptExit();
|
| #endif
|
| }
|
| -#endif
|
| -
|
| -void AttemptExit() {
|
| -#if defined(OS_CHROMEOS)
|
| - // On ChromeOS, user exit and system exits are the same.
|
| - AttemptUserExit();
|
| -#else
|
| - // 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 !defined(OS_ANDROID)
|
| - // Android doesn't use Browser.
|
| - if (AreAllBrowsersCloseable())
|
| - MarkAsCleanShutdown();
|
| -#endif
|
| - AttemptExitInternal(true);
|
| -#endif
|
| -}
|
|
|
| #if defined(OS_CHROMEOS)
|
| // A function called when SIGTERM is received.
|
| @@ -252,65 +237,10 @@ void ExitCleanly() {
|
| browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
|
| else
|
| browser_shutdown::OnShutdownStarting(browser_shutdown::BROWSER_EXIT);
|
| - AttemptExitInternal(true);
|
| + internal::AttemptExitInternal(true);
|
| }
|
| #endif
|
|
|
| -void SessionEnding() {
|
| -#if defined(OS_WIN)
|
| - browser_watcher::ExitFunnel funnel;
|
| -
|
| - funnel.Init(kBrowserExitCodesRegistryPath, base::GetCurrentProcessHandle());
|
| - funnel.RecordEvent(L"SessionEnding");
|
| -#endif
|
| - // 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(
|
| - chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST,
|
| - content::NotificationService::AllSources(),
|
| - content::NotificationService::NoDetails());
|
| -
|
| -#if defined(OS_WIN)
|
| - funnel.RecordEvent(L"EndSession");
|
| -#endif
|
| - // Write important data first.
|
| - g_browser_process->EndSession();
|
| -
|
| -#if defined(OS_WIN)
|
| - base::win::SetShouldCrashOnProcessDetach(false);
|
| -#endif
|
| -
|
| -#if defined(OS_WIN)
|
| - // KillProcess ought to terminate the process without further ado, so if
|
| - // execution gets to this point, presumably this is normal exit.
|
| - funnel.RecordEvent(L"KillProcess");
|
| -#endif
|
| -
|
| - // On Windows 7 and later, the system will consider the process ripe for
|
| - // termination as soon as it hides or destroys its windows. Since any
|
| - // execution past that point will be non-deterministically cut short, we
|
| - // might as well put ourselves out of that misery deterministically.
|
| - base::Process::Current().Terminate(0, false);
|
| -}
|
| -
|
| void IncrementKeepAliveCount() {
|
| // Increment the browser process refcount as long as we're keeping the
|
| // application alive.
|
| @@ -319,17 +249,6 @@ void IncrementKeepAliveCount() {
|
| ++g_keep_alive_count;
|
| }
|
|
|
| -void CloseAllBrowsersIfNeeded() {
|
| - // 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 or explicitly disabled).
|
| - if (chrome::GetTotalBrowserCount() == 0 &&
|
| - !browser_shutdown::IsTryingToQuit() && base::MessageLoop::current() &&
|
| - !g_disable_shutdown_for_testing) {
|
| - CloseAllBrowsers();
|
| - }
|
| -}
|
| -
|
| void DecrementKeepAliveCount() {
|
| DCHECK_GT(g_keep_alive_count, 0);
|
| --g_keep_alive_count;
|
| @@ -348,55 +267,6 @@ 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;
|
| - // Return if a shutdown request has already been sent.
|
| - if (notified)
|
| - return;
|
| - notified = true;
|
| -#endif
|
| -
|
| - if (fast_path)
|
| - NotifyAppTerminating();
|
| -
|
| -#if defined(OS_CHROMEOS)
|
| - if (base::SysInfo::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 if (g_send_stop_request_to_session_manager) {
|
| - // Don't ask SessionManager to stop session if the shutdown request comes
|
| - // from session manager.
|
| - chromeos::DBusThreadManager::Get()->GetSessionManagerClient()
|
| - ->StopSession();
|
| - }
|
| - } else {
|
| - if (g_send_stop_request_to_session_manager) {
|
| - // 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(&ExitCleanly));
|
| - }
|
| - }
|
| -#endif
|
| -}
|
| -
|
| void OnAppExiting() {
|
| static bool notified = false;
|
| if (notified)
|
| @@ -420,7 +290,7 @@ bool ShouldStartShutdown(Browser* browser) {
|
| 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
|
| +#endif // defined(OS_WIN)
|
| return true;
|
| }
|
|
|
|
|