[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 313fce1 | 2013-01-30 17:09:04 | [diff] [blame] | 5 | #include "chrome/browser/lifetime/application_lifetime.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 6 | |
dcheng | 4af4858 | 2016-04-19 00:29:35 | [diff] [blame] | 7 | #include <memory> |
manzagop | b5f74db | 2016-11-28 18:05:52 | [diff] [blame] | 8 | #include <string> |
dcheng | 4af4858 | 2016-04-19 00:29:35 | [diff] [blame] | 9 | |
[email protected] | 2e9d79f | 2013-08-16 05:45:56 | [diff] [blame] | 10 | #include "base/bind.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 11 | #include "base/logging.h" |
rvargas | 486b2f56 | 2015-03-18 01:36:33 | [diff] [blame] | 12 | #include "base/process/process.h" |
rvargas | 079d184 | 2014-10-17 22:32:16 | [diff] [blame] | 13 | #include "base/process/process_handle.h" |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 14 | #include "base/task/post_task.h" |
Greg Thompson | f9928d98 | 2019-11-21 14:35:56 | [diff] [blame] | 15 | #include "base/util/type_safety/strong_alias.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 16 | #include "build/build_config.h" |
| 17 | #include "chrome/browser/browser_process.h" |
[email protected] | 612d3bf | 2013-05-22 10:10:46 | [diff] [blame] | 18 | #include "chrome/browser/browser_process_platform_part.h" |
[email protected] | 9ea0cd3 | 2013-07-12 01:50:36 | [diff] [blame] | 19 | #include "chrome/browser/chrome_notification_types.h" |
peter | ccb33e8 | 2017-05-02 19:00:44 | [diff] [blame] | 20 | #include "chrome/browser/download/download_core_service.h" |
[email protected] | 2e9d79f | 2013-08-16 05:45:56 | [diff] [blame] | 21 | #include "chrome/browser/lifetime/browser_close_manager.h" |
Avi Drissman | d3092734 | 2018-05-22 15:04:27 | [diff] [blame] | 22 | #include "chrome/browser/lifetime/browser_shutdown.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 23 | #include "chrome/browser/metrics/thread_watcher.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 24 | #include "chrome/browser/profiles/profile.h" |
| 25 | #include "chrome/browser/profiles/profile_manager.h" |
Scott Violet | 6200d33 | 2018-02-23 21:29:23 | [diff] [blame] | 26 | #include "chrome/common/buildflags.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 27 | #include "chrome/common/pref_names.h" |
Michael Giuffrida | 2dbce0d1 | 2017-09-02 03:30:59 | [diff] [blame] | 28 | #include "components/keep_alive_registry/keep_alive_registry.h" |
Ran Ji | 73f3b43 | 2018-07-15 22:10:27 | [diff] [blame] | 29 | #include "components/language/core/browser/pref_names.h" |
Claudio Magni | e0a80bb | 2018-01-31 02:52:58 | [diff] [blame] | 30 | #include "components/language/core/common/locale_util.h" |
brettw | b1fc1b8 | 2016-02-02 00:19:08 | [diff] [blame] | 31 | #include "components/prefs/pref_service.h" |
Eric Seckler | 8652dcd5 | 2018-09-20 10:42:28 | [diff] [blame] | 32 | #include "content/public/browser/browser_task_traits.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 33 | #include "content/public/browser/browser_thread.h" |
| 34 | #include "content/public/browser/navigation_details.h" |
| 35 | #include "content/public/browser/notification_service.h" |
| 36 | |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 37 | #if !defined(OS_ANDROID) |
| 38 | #include "chrome/browser/lifetime/termination_notification.h" |
| 39 | #include "chrome/browser/ui/browser.h" |
| 40 | #include "chrome/browser/ui/browser_finder.h" |
| 41 | #include "chrome/browser/ui/browser_list.h" |
| 42 | #include "chrome/browser/ui/browser_tabstrip.h" |
| 43 | #include "chrome/browser/ui/browser_window.h" |
| 44 | #endif |
| 45 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 46 | #if defined(OS_CHROMEOS) |
tfarina | 0923ac5 | 2015-01-07 03:21:22 | [diff] [blame] | 47 | #include "chrome/browser/chromeos/boot_times_recorder.h" |
pmarko | 8c3ffb5 | 2017-02-08 12:18:35 | [diff] [blame] | 48 | #include "chrome/browser/chromeos/settings/cros_settings.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 49 | #include "chromeos/dbus/dbus_thread_manager.h" |
Steven Bennetts | 3330b9f | 2019-03-15 20:24:13 | [diff] [blame] | 50 | #include "chromeos/dbus/power/power_policy_controller.h" |
Daniel Erat | 03de51e2 | 2017-09-09 00:51:51 | [diff] [blame] | 51 | #include "third_party/cros_system_api/dbus/service_constants.h" |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 52 | #endif |
| 53 | |
Mike Wasserman | 0fc30aa4 | 2018-02-08 18:43:20 | [diff] [blame] | 54 | #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) |
| 55 | #include "chrome/browser/ui/user_manager.h" |
| 56 | #endif |
| 57 | |
[email protected] | e88332a | 2013-08-20 11:42:38 | [diff] [blame] | 58 | #if defined(OS_WIN) |
| 59 | #include "base/win/win_util.h" |
[email protected] | e88332a | 2013-08-20 11:42:38 | [diff] [blame] | 60 | #endif |
| 61 | |
[email protected] | 0c98ab65 | 2013-02-18 00:39:37 | [diff] [blame] | 62 | namespace chrome { |
Greg Thompson | ae8a5b1 | 2019-11-21 12:35:36 | [diff] [blame] | 63 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 64 | namespace { |
| 65 | |
[email protected] | 1d51882f | 2013-11-12 01:59:02 | [diff] [blame] | 66 | #if !defined(OS_ANDROID) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 67 | // Returns true if all browsers can be closed without user interaction. |
| 68 | // This currently checks if there is pending download, or if it needs to |
| 69 | // handle unload handler. |
| 70 | bool AreAllBrowsersCloseable() { |
scottmg | 8abbff83 | 2016-01-28 22:57:37 | [diff] [blame] | 71 | if (BrowserList::GetInstance()->empty()) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 72 | return true; |
| 73 | |
| 74 | // If there are any downloads active, all browsers are not closeable. |
[email protected] | 422a7d1 | 2013-10-21 12:10:42 | [diff] [blame] | 75 | // However, this does not block for malicious downloads. |
peter | ccb33e8 | 2017-05-02 19:00:44 | [diff] [blame] | 76 | if (DownloadCoreService::NonMaliciousDownloadCountAllProfiles() > 0) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 77 | return false; |
| 78 | |
| 79 | // Check TabsNeedBeforeUnloadFired(). |
scottmg | 8abbff83 | 2016-01-28 22:57:37 | [diff] [blame] | 80 | for (auto* browser : *BrowserList::GetInstance()) { |
| 81 | if (browser->TabsNeedBeforeUnloadFired()) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 82 | return false; |
| 83 | } |
| 84 | return true; |
| 85 | } |
tzik | a2f1ff9 | 2016-02-10 22:59:54 | [diff] [blame] | 86 | #endif // !defined(OS_ANDROID) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 87 | |
| 88 | #if defined(OS_CHROMEOS) |
pmarko | 8c3ffb5 | 2017-02-08 12:18:35 | [diff] [blame] | 89 | // Sets kApplicationLocale in |local_state| for the login screen on the next |
| 90 | // application start, if it is forced to a specific value due to enterprise |
| 91 | // policy or the owner's locale. Returns true if any pref has been modified. |
| 92 | bool SetLocaleForNextStart(PrefService* local_state) { |
| 93 | // If a policy mandates the login screen locale, use it. |
| 94 | chromeos::CrosSettings* cros_settings = chromeos::CrosSettings::Get(); |
| 95 | const base::ListValue* login_screen_locales = nullptr; |
| 96 | std::string login_screen_locale; |
| 97 | if (cros_settings->GetList(chromeos::kDeviceLoginScreenLocales, |
| 98 | &login_screen_locales) && |
| 99 | !login_screen_locales->empty() && |
| 100 | login_screen_locales->GetString(0, &login_screen_locale)) { |
Ran Ji | 73f3b43 | 2018-07-15 22:10:27 | [diff] [blame] | 101 | local_state->SetString(language::prefs::kApplicationLocale, |
| 102 | login_screen_locale); |
pmarko | 8c3ffb5 | 2017-02-08 12:18:35 | [diff] [blame] | 103 | return true; |
| 104 | } |
| 105 | |
| 106 | // Login screen should show up in owner's locale. |
| 107 | std::string owner_locale = local_state->GetString(prefs::kOwnerLocale); |
Ran Ji | 73f3b43 | 2018-07-15 22:10:27 | [diff] [blame] | 108 | std::string pref_locale = |
| 109 | local_state->GetString(language::prefs::kApplicationLocale); |
Claudio Magni | e0a80bb | 2018-01-31 02:52:58 | [diff] [blame] | 110 | language::ConvertToActualUILocale(&pref_locale); |
| 111 | if (!owner_locale.empty() && pref_locale != owner_locale && |
Ran Ji | 73f3b43 | 2018-07-15 22:10:27 | [diff] [blame] | 112 | !local_state->IsManagedPreference(language::prefs::kApplicationLocale)) { |
| 113 | local_state->SetString(language::prefs::kApplicationLocale, owner_locale); |
pmarko | 8c3ffb5 | 2017-02-08 12:18:35 | [diff] [blame] | 114 | return true; |
| 115 | } |
| 116 | |
| 117 | return false; |
| 118 | } |
| 119 | |
[email protected] | 7df2c03 | 2014-01-22 10:42:01 | [diff] [blame] | 120 | // Whether chrome should send stop request to a session manager. |
| 121 | bool g_send_stop_request_to_session_manager = false; |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 122 | #endif |
| 123 | |
Greg Thompson | f9928d98 | 2019-11-21 14:35:56 | [diff] [blame] | 124 | #if !defined(OS_ANDROID) |
| 125 | using IgnoreUnloadHandlers = |
| 126 | util::StrongAlias<class IgnoreUnloadHandlersTag, bool>; |
| 127 | |
| 128 | void AttemptRestartInternal(IgnoreUnloadHandlers ignore_unload_handlers) { |
| 129 | // TODO(beng): Can this use ProfileManager::GetLoadedProfiles instead? |
| 130 | for (auto* browser : *BrowserList::GetInstance()) |
| 131 | content::BrowserContext::SaveSessionState(browser->profile()); |
| 132 | |
| 133 | PrefService* pref_service = g_browser_process->local_state(); |
| 134 | pref_service->SetBoolean(prefs::kWasRestarted, true); |
| 135 | |
| 136 | #if defined(OS_CHROMEOS) |
| 137 | chromeos::BootTimesRecorder::Get()->set_restart_requested(); |
| 138 | |
| 139 | DCHECK(!g_send_stop_request_to_session_manager); |
| 140 | // Make sure we don't send stop request to the session manager. |
| 141 | g_send_stop_request_to_session_manager = false; |
| 142 | // Run exit process in clean stack. |
| 143 | base::PostTask(FROM_HERE, {content::BrowserThread::UI}, |
| 144 | base::BindOnce(&ExitIgnoreUnloadHandlers)); |
| 145 | #else |
| 146 | // Set the flag to restore state after the restart. |
| 147 | pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true); |
| 148 | if (ignore_unload_handlers) |
| 149 | ExitIgnoreUnloadHandlers(); |
| 150 | else |
| 151 | AttemptExit(); |
| 152 | #endif |
| 153 | } |
| 154 | #endif // !defined(OS_ANDROID) |
| 155 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 156 | } // namespace |
| 157 | |
thestig | 7987e976 | 2016-04-13 21:52:17 | [diff] [blame] | 158 | #if !defined(OS_ANDROID) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 159 | void MarkAsCleanShutdown() { |
| 160 | // TODO(beng): Can this use ProfileManager::GetLoadedProfiles() instead? |
scottmg | 8abbff83 | 2016-01-28 22:57:37 | [diff] [blame] | 161 | for (auto* browser : *BrowserList::GetInstance()) |
| 162 | browser->profile()->SetExitType(Profile::EXIT_NORMAL); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 163 | } |
thestig | 7987e976 | 2016-04-13 21:52:17 | [diff] [blame] | 164 | #endif |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 165 | |
[email protected] | 0c95faf4 | 2013-10-28 06:27:20 | [diff] [blame] | 166 | void AttemptExitInternal(bool try_to_quit_application) { |
| 167 | // On Mac, the platform-specific part handles setting this. |
| 168 | #if !defined(OS_MACOSX) |
| 169 | if (try_to_quit_application) |
| 170 | browser_shutdown::SetTryingToQuit(true); |
| 171 | #endif |
| 172 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 173 | content::NotificationService::current()->Notify( |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 174 | NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 175 | content::NotificationService::AllSources(), |
| 176 | content::NotificationService::NoDetails()); |
| 177 | |
Avi Drissman | f19bb47 | 2018-11-29 19:51:28 | [diff] [blame] | 178 | g_browser_process->platform_part()->AttemptExit(try_to_quit_application); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 179 | } |
| 180 | |
tzik | a2f1ff9 | 2016-02-10 22:59:54 | [diff] [blame] | 181 | #if !defined(OS_ANDROID) |
[email protected] | 0c95faf4 | 2013-10-28 06:27:20 | [diff] [blame] | 182 | void CloseAllBrowsersAndQuit() { |
| 183 | browser_shutdown::SetTryingToQuit(true); |
| 184 | CloseAllBrowsers(); |
| 185 | } |
| 186 | |
dgn | fe075c8 | 2016-03-18 11:25:35 | [diff] [blame] | 187 | void ShutdownIfNoBrowsers() { |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 188 | if (GetTotalBrowserCount() > 0) |
dgn | fe075c8 | 2016-03-18 11:25:35 | [diff] [blame] | 189 | return; |
| 190 | |
| 191 | // Tell everyone that we are shutting down. |
| 192 | browser_shutdown::SetTryingToQuit(true); |
| 193 | |
brettw | 9e85ef4 | 2016-11-01 21:01:24 | [diff] [blame] | 194 | #if BUILDFLAG(ENABLE_SESSION_SERVICE) |
dgn | fe075c8 | 2016-03-18 11:25:35 | [diff] [blame] | 195 | // If ShuttingDownWithoutClosingBrowsers() returns true, the session |
| 196 | // services may not get a chance to shut down normally, so explicitly shut |
| 197 | // them down here to ensure they have a chance to persist their data. |
| 198 | ProfileManager::ShutdownSessionServices(); |
| 199 | #endif |
| 200 | |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 201 | browser_shutdown::NotifyAndTerminate(true /* fast_path */); |
| 202 | OnAppExiting(); |
dgn | fe075c8 | 2016-03-18 11:25:35 | [diff] [blame] | 203 | } |
| 204 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 205 | void CloseAllBrowsers() { |
[email protected] | 0c95faf4 | 2013-10-28 06:27:20 | [diff] [blame] | 206 | // If there are no browsers and closing the last browser would quit the |
| 207 | // application, send the APP_TERMINATING action here. Otherwise, it will be |
| 208 | // sent by RemoveBrowser() when the last browser has closed. |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 209 | if (GetTotalBrowserCount() == 0 && |
dgn | 0237778 | 2016-03-12 00:58:38 | [diff] [blame] | 210 | (browser_shutdown::IsTryingToQuit() || |
| 211 | !KeepAliveRegistry::GetInstance()->IsKeepingAlive())) { |
dgn | fe075c8 | 2016-03-18 11:25:35 | [diff] [blame] | 212 | ShutdownIfNoBrowsers(); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 213 | return; |
| 214 | } |
| 215 | |
| 216 | #if defined(OS_CHROMEOS) |
tfarina | 0923ac5 | 2015-01-07 03:21:22 | [diff] [blame] | 217 | chromeos::BootTimesRecorder::Get()->AddLogoutTimeMarker( |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 218 | "StartedClosingWindows", false); |
| 219 | #endif |
[email protected] | 2e9d79f | 2013-08-16 05:45:56 | [diff] [blame] | 220 | scoped_refptr<BrowserCloseManager> browser_close_manager = |
| 221 | new BrowserCloseManager; |
| 222 | browser_close_manager->StartClosingBrowsers(); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 223 | } |
tzik | a2f1ff9 | 2016-02-10 22:59:54 | [diff] [blame] | 224 | #endif // !defined(OS_ANDROID) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 225 | |
| 226 | void AttemptUserExit() { |
| 227 | #if defined(OS_CHROMEOS) |
achuith | 9d97f2c9 | 2016-08-19 08:03:06 | [diff] [blame] | 228 | VLOG(1) << "AttemptUserExit"; |
tfarina | 0923ac5 | 2015-01-07 03:21:22 | [diff] [blame] | 229 | chromeos::BootTimesRecorder::Get()->AddLogoutTimeMarker("LogoutStarted", |
| 230 | false); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 231 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 232 | PrefService* state = g_browser_process->local_state(); |
| 233 | if (state) { |
tfarina | 0923ac5 | 2015-01-07 03:21:22 | [diff] [blame] | 234 | chromeos::BootTimesRecorder::Get()->OnLogoutStarted(state); |
[email protected] | b01b9e2 | 2014-06-03 22:20:19 | [diff] [blame] | 235 | |
pmarko | 8c3ffb5 | 2017-02-08 12:18:35 | [diff] [blame] | 236 | if (SetLocaleForNextStart(state)) { |
[email protected] | 89af400 | 2013-09-06 07:47:07 | [diff] [blame] | 237 | TRACE_EVENT0("shutdown", "CommitPendingWrite"); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 238 | state->CommitPendingWrite(); |
| 239 | } |
| 240 | } |
[email protected] | 7df2c03 | 2014-01-22 10:42:01 | [diff] [blame] | 241 | g_send_stop_request_to_session_manager = true; |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 242 | // On ChromeOS, always terminate the browser, regardless of the result of |
| 243 | // AreAllBrowsersCloseable(). See crbug.com/123107. |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 244 | browser_shutdown::NotifyAndTerminate(true /* fast_path */); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 245 | #else |
| 246 | // Reset the restart bit that might have been set in cancelled restart |
| 247 | // request. |
thestig | 7987e976 | 2016-04-13 21:52:17 | [diff] [blame] | 248 | #if !defined(OS_ANDROID) |
noms | d710bc83 | 2014-10-15 20:27:37 | [diff] [blame] | 249 | UserManager::Hide(); |
thestig | 7987e976 | 2016-04-13 21:52:17 | [diff] [blame] | 250 | #endif |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 251 | PrefService* pref_service = g_browser_process->local_state(); |
| 252 | pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); |
[email protected] | 0c95faf4 | 2013-10-28 06:27:20 | [diff] [blame] | 253 | AttemptExitInternal(false); |
thestig | 7987e976 | 2016-04-13 21:52:17 | [diff] [blame] | 254 | #endif // defined(OS_CHROMEOS) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 255 | } |
| 256 | |
[email protected] | 4052d83 | 2013-01-16 05:31:01 | [diff] [blame] | 257 | // The Android implementation is in application_lifetime_android.cc |
| 258 | #if !defined(OS_ANDROID) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 259 | void AttemptRestart() { |
Greg Thompson | f9928d98 | 2019-11-21 14:35:56 | [diff] [blame] | 260 | AttemptRestartInternal(IgnoreUnloadHandlers(false)); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 261 | } |
dpapad | 615a956 | 2016-06-07 02:10:29 | [diff] [blame] | 262 | #endif // !defined(OS_ANDROID) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 263 | |
dpapad | 374368fd | 2016-06-09 04:04:42 | [diff] [blame] | 264 | void AttemptRelaunch() { |
| 265 | #if defined(OS_CHROMEOS) |
Evan Stade | 523f7fc | 2019-03-02 19:20:51 | [diff] [blame] | 266 | chromeos::PowerManagerClient::Get()->RequestRestart( |
Daniel Erat | 03de51e2 | 2017-09-09 00:51:51 | [diff] [blame] | 267 | power_manager::REQUEST_RESTART_OTHER, "Chrome relaunch"); |
dpapad | 374368fd | 2016-06-09 04:04:42 | [diff] [blame] | 268 | // If running the Chrome OS build, but we're not on the device, fall through. |
| 269 | #endif |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 270 | AttemptRestart(); |
dpapad | 374368fd | 2016-06-09 04:04:42 | [diff] [blame] | 271 | } |
| 272 | |
Greg Thompson | f9928d98 | 2019-11-21 14:35:56 | [diff] [blame] | 273 | #if !defined(OS_ANDROID) |
| 274 | void RelaunchIgnoreUnloadHandlers() { |
| 275 | #if defined(OS_CHROMEOS) |
| 276 | chromeos::PowerManagerClient::Get()->RequestRestart( |
| 277 | power_manager::REQUEST_RESTART_OTHER, "Chrome relaunch"); |
| 278 | // If running the Chrome OS build, but we're not on the device, fall through. |
| 279 | #endif |
| 280 | AttemptRestartInternal(IgnoreUnloadHandlers(true)); |
| 281 | } |
| 282 | #endif |
| 283 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 284 | void AttemptExit() { |
[email protected] | 7df2c03 | 2014-01-22 10:42:01 | [diff] [blame] | 285 | #if defined(OS_CHROMEOS) |
| 286 | // On ChromeOS, user exit and system exits are the same. |
| 287 | AttemptUserExit(); |
| 288 | #else |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 289 | // If we know that all browsers can be closed without blocking, |
| 290 | // don't notify users of crashes beyond this point. |
[email protected] | 6c0ca7fc | 2012-10-05 16:27:22 | [diff] [blame] | 291 | // Note that MarkAsCleanShutdown() does not set UMA's exit cleanly bit |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 292 | // so crashes during shutdown are still reported in UMA. |
[email protected] | 4052d83 | 2013-01-16 05:31:01 | [diff] [blame] | 293 | #if !defined(OS_ANDROID) |
| 294 | // Android doesn't use Browser. |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 295 | if (AreAllBrowsersCloseable()) |
| 296 | MarkAsCleanShutdown(); |
[email protected] | 4052d83 | 2013-01-16 05:31:01 | [diff] [blame] | 297 | #endif |
[email protected] | 0c95faf4 | 2013-10-28 06:27:20 | [diff] [blame] | 298 | AttemptExitInternal(true); |
[email protected] | 7df2c03 | 2014-01-22 10:42:01 | [diff] [blame] | 299 | #endif |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 300 | } |
| 301 | |
Andrey Lushnikov | c08ae9e | 2018-12-21 01:32:40 | [diff] [blame] | 302 | void ExitIgnoreUnloadHandlers() { |
| 303 | VLOG(1) << "ExitIgnoreUnloadHandlers"; |
| 304 | #if !defined(OS_ANDROID) |
hashimoto | 16a569a | 2015-04-09 11:25:28 | [diff] [blame] | 305 | // We always mark exit cleanly. |
| 306 | MarkAsCleanShutdown(); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 307 | |
Greg Thompson | f9928d98 | 2019-11-21 14:35:56 | [diff] [blame] | 308 | #if defined(OS_CHROMEOS) |
Andrey Lushnikov | c08ae9e | 2018-12-21 01:32:40 | [diff] [blame] | 309 | // On ChromeOS ExitIgnoreUnloadHandlers() is used to handle SIGTERM. |
| 310 | // In this case, AreAllBrowsersCloseable() |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 311 | // can be false in following cases. a) power-off b) signout from |
| 312 | // screen locker. |
Greg Thompson | ae8a5b1 | 2019-11-21 12:35:36 | [diff] [blame] | 313 | browser_shutdown::OnShutdownStarting( |
| 314 | AreAllBrowsersCloseable() ? browser_shutdown::ShutdownType::kBrowserExit |
| 315 | : browser_shutdown::ShutdownType::kEndSession); |
Greg Thompson | f9928d98 | 2019-11-21 14:35:56 | [diff] [blame] | 316 | #else // defined(OS_CHROMEOS) |
| 317 | // For desktop browsers, always perform a silent exit. |
| 318 | browser_shutdown::OnShutdownStarting( |
| 319 | browser_shutdown::ShutdownType::kSilentExit); |
| 320 | #endif // defined(OS_CHROMEOS) |
| 321 | #endif // !defined(OS_ANDROID) |
[email protected] | 0c95faf4 | 2013-10-28 06:27:20 | [diff] [blame] | 322 | AttemptExitInternal(true); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 323 | } |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 324 | |
Andrey Lushnikov | c08ae9e | 2018-12-21 01:32:40 | [diff] [blame] | 325 | #if defined(OS_CHROMEOS) |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 326 | bool IsAttemptingShutdown() { |
| 327 | return g_send_stop_request_to_session_manager; |
| 328 | } |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 329 | #endif |
| 330 | |
tzik | a2f1ff9 | 2016-02-10 22:59:54 | [diff] [blame] | 331 | #if !defined(OS_ANDROID) |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 332 | void SessionEnding() { |
| 333 | // This is a time-limited shutdown where we need to write as much to |
| 334 | // disk as we can as soon as we can, and where we must kill the |
| 335 | // process within a hang timeout to avoid user prompts. |
| 336 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 337 | // EndSession is invoked once per frame. Only do something the first time. |
| 338 | static bool already_ended = false; |
| 339 | // We may get called in the middle of shutdown, e.g. http://crbug.com/70852 |
| 340 | // In this case, do nothing. |
| 341 | if (already_ended || !content::NotificationService::current()) |
| 342 | return; |
| 343 | already_ended = true; |
| 344 | |
sky | 0e07a14 | 2016-03-25 21:27:31 | [diff] [blame] | 345 | // ~ShutdownWatcherHelper uses IO (it joins a thread). We'll only trigger that |
| 346 | // if Terminate() fails, which leaves us in a weird state, or the OS is going |
| 347 | // to kill us soon. Either way we don't care about that here. |
| 348 | base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 349 | |
| 350 | // Start watching for hang during shutdown, and crash it if takes too long. |
| 351 | // We disarm when |shutdown_watcher| object is destroyed, which is when we |
| 352 | // exit this function. |
| 353 | ShutdownWatcherHelper shutdown_watcher; |
| 354 | shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90)); |
sky | 0e07a14 | 2016-03-25 21:27:31 | [diff] [blame] | 355 | |
Greg Thompson | ae8a5b1 | 2019-11-21 12:35:36 | [diff] [blame] | 356 | browser_shutdown::OnShutdownStarting( |
| 357 | browser_shutdown::ShutdownType::kEndSession); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 358 | |
hashimoto | dc347b7 | 2016-09-16 07:23:40 | [diff] [blame] | 359 | // In a clean shutdown, browser_shutdown::OnShutdownStarting sets |
| 360 | // g_shutdown_type, and browser_shutdown::ShutdownPreThreadsStop calls |
| 361 | // RecordShutdownInfoPrefs to update the pref with the value. However, here |
| 362 | // the process is going to exit without calling ShutdownPreThreadsStop. |
| 363 | // Instead, here we call RecordShutdownInfoPrefs to record the shutdown info. |
| 364 | browser_shutdown::RecordShutdownInfoPrefs(); |
| 365 | |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 366 | content::NotificationService::current()->Notify( |
thestig | ea81c77b5 | 2017-04-17 23:19:11 | [diff] [blame] | 367 | NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST, |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 368 | content::NotificationService::AllSources(), |
| 369 | content::NotificationService::NoDetails()); |
| 370 | |
| 371 | // Write important data first. |
| 372 | g_browser_process->EndSession(); |
| 373 | |
[email protected] | 7a6af7e | 2014-07-08 20:11:13 | [diff] [blame] | 374 | #if defined(OS_WIN) |
| 375 | base::win::SetShouldCrashOnProcessDetach(false); |
[email protected] | cc2ebc7 | 2014-07-15 23:57:36 | [diff] [blame] | 376 | #endif |
Greg Thompson | ae8a5b1 | 2019-11-21 12:35:36 | [diff] [blame] | 377 | |
siggi | 5ed6480a | 2014-12-05 15:44:26 | [diff] [blame] | 378 | // On Windows 7 and later, the system will consider the process ripe for |
| 379 | // termination as soon as it hides or destroys its windows. Since any |
| 380 | // execution past that point will be non-deterministically cut short, we |
| 381 | // might as well put ourselves out of that misery deterministically. |
Wez | 9a0f723 | 2018-02-08 17:14:29 | [diff] [blame] | 382 | base::Process::TerminateCurrentProcessImmediately(0); |
[email protected] | 2e6389f | 2012-05-18 19:41:25 | [diff] [blame] | 383 | } |
| 384 | |
dgn | fe075c8 | 2016-03-18 11:25:35 | [diff] [blame] | 385 | void ShutdownIfNeeded() { |
oshima | fc74eba2 | 2017-04-04 23:36:30 | [diff] [blame] | 386 | if (browser_shutdown::IsTryingToQuit()) |
| 387 | return; |
| 388 | |
| 389 | ShutdownIfNoBrowsers(); |
skyostil | 0becb33 | 2015-04-27 17:59:37 | [diff] [blame] | 390 | } |
| 391 | |
[email protected] | 313fce1 | 2013-01-30 17:09:04 | [diff] [blame] | 392 | void OnAppExiting() { |
| 393 | static bool notified = false; |
| 394 | if (notified) |
| 395 | return; |
| 396 | notified = true; |
| 397 | HandleAppExitingForPlatform(); |
| 398 | } |
tzik | a2f1ff9 | 2016-02-10 22:59:54 | [diff] [blame] | 399 | #endif // !defined(OS_ANDROID) |
skyostil | 0becb33 | 2015-04-27 17:59:37 | [diff] [blame] | 400 | |
[email protected] | 313fce1 | 2013-01-30 17:09:04 | [diff] [blame] | 401 | } // namespace chrome |