| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/browser_list.h" | 5 #include "chrome/browser/lifetime/application_lifetime.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| 11 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
| 12 #include "chrome/browser/browser_shutdown.h" | 12 #include "chrome/browser/browser_shutdown.h" |
| 13 #include "chrome/browser/download/download_service.h" | 13 #include "chrome/browser/download/download_service.h" |
| 14 #include "chrome/browser/metrics/thread_watcher.h" | 14 #include "chrome/browser/metrics/thread_watcher.h" |
| 15 #include "chrome/browser/prefs/pref_service.h" | 15 #include "chrome/browser/prefs/pref_service.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/profiles/profile_manager.h" | 17 #include "chrome/browser/profiles/profile_manager.h" |
| 18 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
| 19 #include "chrome/browser/ui/browser_list.h" |
| 19 #include "chrome/browser/ui/browser_tabstrip.h" | 20 #include "chrome/browser/ui/browser_tabstrip.h" |
| 20 #include "chrome/browser/ui/browser_window.h" | 21 #include "chrome/browser/ui/browser_window.h" |
| 21 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 22 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 22 #include "chrome/common/chrome_notification_types.h" | 23 #include "chrome/common/chrome_notification_types.h" |
| 23 #include "chrome/common/chrome_switches.h" | 24 #include "chrome/common/chrome_switches.h" |
| 24 #include "chrome/common/pref_names.h" | 25 #include "chrome/common/pref_names.h" |
| 25 #include "content/public/browser/browser_shutdown.h" | 26 #include "content/public/browser/browser_shutdown.h" |
| 26 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 27 #include "content/public/browser/navigation_details.h" | 28 #include "content/public/browser/navigation_details.h" |
| 28 #include "content/public/browser/notification_service.h" | 29 #include "content/public/browser/notification_service.h" |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 // On the Mac, the application continues to run once all windows are closed. | 98 // On the Mac, the application continues to run once all windows are closed. |
| 98 // Terminate will result in a CloseAllBrowsers() call, and once (and if) | 99 // Terminate will result in a CloseAllBrowsers() call, and once (and if) |
| 99 // that is done, will cause the application to exit cleanly. | 100 // that is done, will cause the application to exit cleanly. |
| 100 chrome_browser_application_mac::Terminate(); | 101 chrome_browser_application_mac::Terminate(); |
| 101 #else | 102 #else |
| 102 // On most platforms, closing all windows causes the application to exit. | 103 // On most platforms, closing all windows causes the application to exit. |
| 103 CloseAllBrowsers(); | 104 CloseAllBrowsers(); |
| 104 #endif | 105 #endif |
| 105 } | 106 } |
| 106 | 107 |
| 107 void NotifyAppTerminating() { | |
| 108 static bool notified = false; | |
| 109 if (notified) | |
| 110 return; | |
| 111 notified = true; | |
| 112 content::NotificationService::current()->Notify( | |
| 113 chrome::NOTIFICATION_APP_TERMINATING, | |
| 114 content::NotificationService::AllSources(), | |
| 115 content::NotificationService::NoDetails()); | |
| 116 } | |
| 117 | |
| 118 void NotifyAndTerminate(bool fast_path) { | |
| 119 #if defined(OS_CHROMEOS) | |
| 120 static bool notified = false; | |
| 121 // Don't ask SessionManager to shutdown if | |
| 122 // a) a shutdown request has already been sent. | |
| 123 // b) shutdown request comes from session manager. | |
| 124 if (notified || g_session_manager_requested_shutdown) | |
| 125 return; | |
| 126 notified = true; | |
| 127 #endif | |
| 128 | |
| 129 if (fast_path) | |
| 130 NotifyAppTerminating(); | |
| 131 | |
| 132 #if defined(OS_CHROMEOS) | |
| 133 if (base::chromeos::IsRunningOnChromeOS()) { | |
| 134 // If we're on a ChromeOS device, reboot if an update has been applied, | |
| 135 // or else signal the session manager to log out. | |
| 136 chromeos::UpdateEngineClient* update_engine_client | |
| 137 = chromeos::DBusThreadManager::Get()->GetUpdateEngineClient(); | |
| 138 if (update_engine_client->GetLastStatus().status == | |
| 139 chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { | |
| 140 update_engine_client->RebootAfterUpdate(); | |
| 141 } else { | |
| 142 chromeos::DBusThreadManager::Get()->GetSessionManagerClient() | |
| 143 ->StopSession(); | |
| 144 } | |
| 145 } else { | |
| 146 // If running the Chrome OS build, but we're not on the device, act | |
| 147 // as if we received signal from SessionManager. | |
| 148 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
| 149 base::Bind(&browser::ExitCleanly)); | |
| 150 } | |
| 151 #endif | |
| 152 } | |
| 153 | |
| 154 void OnAppExiting() { | |
| 155 static bool notified = false; | |
| 156 if (notified) | |
| 157 return; | |
| 158 notified = true; | |
| 159 HandleAppExitingForPlatform(); | |
| 160 } | |
| 161 | |
| 162 void CloseAllBrowsers() { | 108 void CloseAllBrowsers() { |
| 163 bool session_ending = | 109 bool session_ending = |
| 164 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; | 110 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; |
| 165 // Tell everyone that we are shutting down. | 111 // Tell everyone that we are shutting down. |
| 166 browser_shutdown::SetTryingToQuit(true); | 112 browser_shutdown::SetTryingToQuit(true); |
| 167 | 113 |
| 168 #if defined(ENABLE_SESSION_SERVICE) | 114 #if defined(ENABLE_SESSION_SERVICE) |
| 169 // Before we close the browsers shutdown all session services. That way an | 115 // Before we close the browsers shutdown all session services. That way an |
| 170 // exit can restore all browsers open before exiting. | 116 // exit can restore all browsers open before exiting. |
| 171 ProfileManager::ShutdownSessionServices(); | 117 ProfileManager::ShutdownSessionServices(); |
| 172 #endif | 118 #endif |
| 173 | 119 |
| 174 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, | 120 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, |
| 175 // it will be sent by RemoveBrowser() when the last browser has closed. | 121 // it will be sent by RemoveBrowser() when the last browser has closed. |
| 176 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() || | 122 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() || |
| 177 BrowserList::empty()) { | 123 BrowserList::empty()) { |
| 178 NotifyAndTerminate(true); | 124 chrome::NotifyAndTerminate(true); |
| 179 OnAppExiting(); | 125 chrome::OnAppExiting(); |
| 180 return; | 126 return; |
| 181 } | 127 } |
| 182 | 128 |
| 183 #if defined(OS_CHROMEOS) | 129 #if defined(OS_CHROMEOS) |
| 184 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( | 130 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( |
| 185 "StartedClosingWindows", false); | 131 "StartedClosingWindows", false); |
| 186 #endif | 132 #endif |
| 187 for (BrowserList::const_iterator i = BrowserList::begin(); | 133 for (BrowserList::const_iterator i = BrowserList::begin(); |
| 188 i != BrowserList::end();) { | 134 i != BrowserList::end();) { |
| 189 Browser* browser = *i; | 135 Browser* browser = *i; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 if (!owner_locale.empty() && | 172 if (!owner_locale.empty() && |
| 227 state->GetString(prefs::kApplicationLocale) != owner_locale && | 173 state->GetString(prefs::kApplicationLocale) != owner_locale && |
| 228 !state->IsManagedPreference(prefs::kApplicationLocale)) { | 174 !state->IsManagedPreference(prefs::kApplicationLocale)) { |
| 229 state->SetString(prefs::kApplicationLocale, owner_locale); | 175 state->SetString(prefs::kApplicationLocale, owner_locale); |
| 230 state->CommitPendingWrite(); | 176 state->CommitPendingWrite(); |
| 231 } | 177 } |
| 232 } | 178 } |
| 233 g_session_manager_requested_shutdown = false; | 179 g_session_manager_requested_shutdown = false; |
| 234 // On ChromeOS, always terminate the browser, regardless of the result of | 180 // On ChromeOS, always terminate the browser, regardless of the result of |
| 235 // AreAllBrowsersCloseable(). See crbug.com/123107. | 181 // AreAllBrowsersCloseable(). See crbug.com/123107. |
| 236 NotifyAndTerminate(true); | 182 chrome::NotifyAndTerminate(true); |
| 237 #else | 183 #else |
| 238 // Reset the restart bit that might have been set in cancelled restart | 184 // Reset the restart bit that might have been set in cancelled restart |
| 239 // request. | 185 // request. |
| 240 PrefService* pref_service = g_browser_process->local_state(); | 186 PrefService* pref_service = g_browser_process->local_state(); |
| 241 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); | 187 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false); |
| 242 AttemptExitInternal(); | 188 AttemptExitInternal(); |
| 243 #endif | 189 #endif |
| 244 } | 190 } |
| 245 | 191 |
| 246 // The Android implementation is in application_lifetime_android.cc | 192 // The Android implementation is in application_lifetime_android.cc |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 // can properly shutdown before we exit. | 287 // can properly shutdown before we exit. |
| 342 content::NotificationService::current()->Notify( | 288 content::NotificationService::current()->Notify( |
| 343 chrome::NOTIFICATION_SESSION_END, | 289 chrome::NOTIFICATION_SESSION_END, |
| 344 content::NotificationService::AllSources(), | 290 content::NotificationService::AllSources(), |
| 345 content::NotificationService::NoDetails()); | 291 content::NotificationService::NoDetails()); |
| 346 | 292 |
| 347 // This will end by terminating the process. | 293 // This will end by terminating the process. |
| 348 content::ImmediateShutdownAndExitProcess(); | 294 content::ImmediateShutdownAndExitProcess(); |
| 349 } | 295 } |
| 350 | 296 |
| 297 } // namespace browser |
| 298 |
| 299 namespace chrome { |
| 300 |
| 351 void StartKeepAlive() { | 301 void StartKeepAlive() { |
| 352 // Increment the browser process refcount as long as we're keeping the | 302 // Increment the browser process refcount as long as we're keeping the |
| 353 // application alive. | 303 // application alive. |
| 354 if (!WillKeepAlive()) | 304 if (!WillKeepAlive()) |
| 355 g_browser_process->AddRefModule(); | 305 g_browser_process->AddRefModule(); |
| 356 ++g_keep_alive_count; | 306 ++browser::g_keep_alive_count; |
| 357 } | 307 } |
| 358 | 308 |
| 359 void EndKeepAlive() { | 309 void EndKeepAlive() { |
| 360 DCHECK_GT(g_keep_alive_count, 0); | 310 DCHECK_GT(browser::g_keep_alive_count, 0); |
| 361 --g_keep_alive_count; | 311 --browser::g_keep_alive_count; |
| 362 | 312 |
| 363 DCHECK(g_browser_process); | 313 DCHECK(g_browser_process); |
| 364 // Although we should have a browser process, if there is none, | 314 // Although we should have a browser process, if there is none, |
| 365 // there is nothing to do. | 315 // there is nothing to do. |
| 366 if (!g_browser_process) return; | 316 if (!g_browser_process) return; |
| 367 | 317 |
| 368 // Allow the app to shutdown again. | 318 // Allow the app to shutdown again. |
| 369 if (!WillKeepAlive()) { | 319 if (!WillKeepAlive()) { |
| 370 g_browser_process->ReleaseModule(); | 320 g_browser_process->ReleaseModule(); |
| 371 // If there are no browsers open and we aren't already shutting down, | 321 // If there are no browsers open and we aren't already shutting down, |
| 372 // initiate a shutdown. Also skips shutdown if this is a unit test | 322 // initiate a shutdown. Also skips shutdown if this is a unit test |
| 373 // (MessageLoop::current() == null). | 323 // (MessageLoop::current() == null). |
| 374 if (BrowserList::empty() && !browser_shutdown::IsTryingToQuit() && | 324 if (BrowserList::empty() && !browser_shutdown::IsTryingToQuit() && |
| 375 MessageLoop::current()) | 325 MessageLoop::current()) |
| 376 CloseAllBrowsers(); | 326 browser::CloseAllBrowsers(); |
| 377 } | 327 } |
| 378 } | 328 } |
| 379 | 329 |
| 380 bool WillKeepAlive() { | 330 bool WillKeepAlive() { |
| 381 return g_keep_alive_count > 0; | 331 return browser::g_keep_alive_count > 0; |
| 382 } | 332 } |
| 383 | 333 |
| 384 } // namespace browser | 334 void NotifyAppTerminating() { |
| 335 static bool notified = false; |
| 336 if (notified) |
| 337 return; |
| 338 notified = true; |
| 339 content::NotificationService::current()->Notify( |
| 340 chrome::NOTIFICATION_APP_TERMINATING, |
| 341 content::NotificationService::AllSources(), |
| 342 content::NotificationService::NoDetails()); |
| 343 } |
| 344 |
| 345 void NotifyAndTerminate(bool fast_path) { |
| 346 #if defined(OS_CHROMEOS) |
| 347 static bool notified = false; |
| 348 // Don't ask SessionManager to shutdown if |
| 349 // a) a shutdown request has already been sent. |
| 350 // b) shutdown request comes from session manager. |
| 351 if (notified || browser::g_session_manager_requested_shutdown) |
| 352 return; |
| 353 notified = true; |
| 354 #endif |
| 355 |
| 356 if (fast_path) |
| 357 NotifyAppTerminating(); |
| 358 |
| 359 #if defined(OS_CHROMEOS) |
| 360 if (base::chromeos::IsRunningOnChromeOS()) { |
| 361 // If we're on a ChromeOS device, reboot if an update has been applied, |
| 362 // or else signal the session manager to log out. |
| 363 chromeos::UpdateEngineClient* update_engine_client |
| 364 = chromeos::DBusThreadManager::Get()->GetUpdateEngineClient(); |
| 365 if (update_engine_client->GetLastStatus().status == |
| 366 chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) { |
| 367 update_engine_client->RebootAfterUpdate(); |
| 368 } else { |
| 369 chromeos::DBusThreadManager::Get()->GetSessionManagerClient() |
| 370 ->StopSession(); |
| 371 } |
| 372 } else { |
| 373 // If running the Chrome OS build, but we're not on the device, act |
| 374 // as if we received signal from SessionManager. |
| 375 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
| 376 base::Bind(&browser::ExitCleanly)); |
| 377 } |
| 378 #endif |
| 379 } |
| 380 |
| 381 void OnAppExiting() { |
| 382 static bool notified = false; |
| 383 if (notified) |
| 384 return; |
| 385 notified = true; |
| 386 HandleAppExitingForPlatform(); |
| 387 } |
| 388 |
| 389 } // namespace chrome |
| OLD | NEW |