15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_shutdown.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/about_flags.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/first_run/upgrade_util.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/common/crash_keys.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/switch_utils.h" 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/metrics_service.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_util_win.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/first_run/upgrade_util_win.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ENABLE_RLZ) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/rlz/rlz.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/boot_times_loader.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_FULL_PRINTING) 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/service_process/service_process_control.h" 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_shutdown { 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Whether the browser is trying to quit (e.g., Quit chosen from menu). 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_trying_to_quit = false; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)upgrade_util::RelaunchMode g_relaunch_mode = 650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) upgrade_util::RELAUNCH_MODE_DEFAULT; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Time* shutdown_started_ = NULL; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ShutdownType shutdown_type_ = NOT_VALID; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int shutdown_num_processes_; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int shutdown_num_processes_slow_; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kShutdownMsFile[] = "chrome_shutdown_ms.txt"; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char* ToShutdownTypeString(ShutdownType type) { 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (type) { 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case NOT_VALID: 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ""; 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case WINDOW_CLOSE: 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return "close"; 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case BROWSER_EXIT: 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return "exit"; 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case END_SESSION: 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return "end"; 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ""; 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} // namespace 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RegisterPrefs(PrefRegistrySimple* registry) { 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterIntegerPref(prefs::kShutdownType, NOT_VALID); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterIntegerPref(prefs::kShutdownNumProcesses, 0); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registry->RegisterIntegerPref(prefs::kShutdownNumProcessesSlow, 0); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ShutdownType GetShutdownType() { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shutdown_type_; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void OnShutdownStarting(ShutdownType type) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shutdown_type_ != NOT_VALID) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::debug::SetCrashKeyValue(crash_keys::kShutdownType, 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ToShutdownTypeString(type)); 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if !defined(OS_CHROMEOS) 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Start the shutdown tracing. Note that On ChromeOS we have started this 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // already. 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) chrome::StartShutdownTracing(); 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_type_ = type; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, we're only counting the number of renderer processes 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since we can't safely count the number of plugin processes from this 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread, and we'd really like to avoid anything which might add further 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delays to shutdown time. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!shutdown_started_); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_started_ = new Time(Time::Now()); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call FastShutdown on all of the RenderProcessHosts. This will be 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a no-op in some cases, so we still need to go through the normal 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown path for the ones that didn't exit here. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_num_processes_ = 0; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_num_processes_slow_ = 0; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (content::RenderProcessHost::iterator i( 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost::AllHostsIterator()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !i.IsAtEnd(); i.Advance()) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++shutdown_num_processes_; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!i.GetCurrentValue()->FastShutdownIfPossible()) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++shutdown_num_processes_slow_; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetShutdownMsPath() { 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath shutdown_ms_file; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PathService::Get(chrome::DIR_USER_DATA, &shutdown_ms_file); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return shutdown_ms_file.AppendASCII(kShutdownMsFile); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShutdownPreThreadsStop() { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "BrowserShutdownStarted", false); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_FULL_PRINTING) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shutdown the IPC channel to the service processes. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ServiceProcessControl::GetInstance()->Disconnect(); 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // ENABLE_FULL_PRINTING 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WARNING: During logoff/shutdown (WM_ENDSESSION) we may not have enough 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time to get here. If you have something that *must* happen on end session, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // consider putting it in BrowserProcessImpl::EndSession. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* prefs = g_browser_process->local_state(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci metrics::MetricsService* metrics = g_browser_process->metrics_service(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (metrics) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) metrics->RecordCompletedSessionEnd(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the shutdown info so that we can put it into a histogram at next 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // startup. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->SetInteger(prefs::kShutdownType, shutdown_type_); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->SetInteger(prefs::kShutdownNumProcesses, shutdown_num_processes_); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->SetInteger(prefs::kShutdownNumProcessesSlow, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_num_processes_slow_); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check local state for the restart flag so we can restart the session below. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool restart_last_session = false; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prefs->HasPrefPath(prefs::kRestartLastSessionOnShutdown)) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restart_last_session = 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->GetBoolean(prefs::kRestartLastSessionOnShutdown); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->ClearPref(prefs::kRestartLastSessionOnShutdown); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restart_last_session) { 1770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (prefs->HasPrefPath(prefs::kRelaunchMode)) { 1780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) g_relaunch_mode = upgrade_util::RelaunchModeStringToEnum( 1790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) prefs->GetString(prefs::kRelaunchMode)); 1800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) prefs->ClearPref(prefs::kRelaunchMode); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->CommitPendingWrite(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ENABLE_RLZ) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cleanup any statics created by RLZ. Must be done before NotificationService 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is destroyed. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RLZTracker::CleanupRlz(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return restart_last_session; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShutdownPostThreadsStop(bool restart_last_session) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete g_browser_process; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_browser_process = NULL; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // crbug.com/95079 - This needs to happen after the browser process object 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // goes away. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileManager::NukeDeletedProfilesFromDisk(); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("BrowserDeleted", 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!browser_util::IsBrowserAlreadyRunning() && 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_type_ != browser_shutdown::END_SESSION) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upgrade_util::SwapNewChromeExeIfPresent(); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restart_last_session) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_CHROMEOS) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure to relaunch the browser with the original command line plus 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the Restore Last Session flag. Note that Chrome can be launched (ie. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // through ShellExecute on Windows) with a switch argument terminator at 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the end (double dash, as described in b/1366444) plus a URL, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which prevents us from appending to the command line directly (issue 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 46182). We therefore use GetSwitches to copy the command line (it stops 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // at the switch argument terminator). 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine old_cl(*CommandLine::ForCurrentProcess()); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<CommandLine> new_cl(new CommandLine(old_cl.GetProgram())); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<std::string, CommandLine::StringType> switches = 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_cl.GetSwitches(); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove the switches that shouldn't persist across restart. 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) about_flags::RemoveFlagsSwitches(&switches); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::RemoveSwitchesForAutostart(&switches); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append the old switches to the new command line. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<std::string, CommandLine::StringType>::const_iterator i = 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches.begin(); i != switches.end(); ++i) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::StringType switch_value = i->second; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!switch_value.empty()) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_cl->AppendSwitchNative(i->first, i->second); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_cl->AppendSwitch(i->first); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 2440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) upgrade_util::RelaunchChromeWithMode(*new_cl.get(), g_relaunch_mode); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upgrade_util::RelaunchChromeBrowser(*new_cl.get()); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_WIN) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !defined(OS_CHROMEOS) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Measure total shutdown time as late in the process as possible 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and then write it to a file to be read at startup. 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can't use prefs since all services are shutdown at this point. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta shutdown_delta = Time::Now() - *shutdown_started_; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string shutdown_ms = 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Int64ToString(shutdown_delta.InMilliseconds()); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len = static_cast<int>(shutdown_ms.length()) + 1; 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath shutdown_ms_file = GetShutdownMsPath(); 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WriteFile(shutdown_ms_file, shutdown_ms.c_str(), len); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::NotifyAndTerminate(false); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ReadLastShutdownFile(ShutdownType type, 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_procs, 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_procs_slow) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath shutdown_ms_file = GetShutdownMsPath(); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string shutdown_ms_str; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 shutdown_ms = 0; 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (base::ReadFileToString(shutdown_ms_file, &shutdown_ms_str)) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringToInt64(shutdown_ms_str, &shutdown_ms); 2817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(shutdown_ms_file, false); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == NOT_VALID || shutdown_ms == 0 || num_procs == 0) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* time_fmt = "Shutdown.%s.time"; 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* time_per_fmt = "Shutdown.%s.time_per_process"; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string time; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string time_per; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == WINDOW_CLOSE) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = base::StringPrintf(time_fmt, "window_close"); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_per = base::StringPrintf(time_per_fmt, "window_close"); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == BROWSER_EXIT) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = base::StringPrintf(time_fmt, "browser_exit"); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_per = base::StringPrintf(time_per_fmt, "browser_exit"); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (type == END_SESSION) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time = base::StringPrintf(time_fmt, "end_session"); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_per = base::StringPrintf(time_per_fmt, "end_session"); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (time.empty()) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay): change these to UMA histograms after a bit more testing. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES(time.c_str(), 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromMilliseconds(shutdown_ms)); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_TIMES(time_per.c_str(), 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeDelta::FromMilliseconds(shutdown_ms / num_procs)); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.total", num_procs); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.slow", num_procs_slow); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReadLastShutdownInfo() { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* prefs = g_browser_process->local_state(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShutdownType type = 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ShutdownType>(prefs->GetInteger(prefs::kShutdownType)); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_procs = prefs->GetInteger(prefs::kShutdownNumProcesses); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_procs_slow = prefs->GetInteger(prefs::kShutdownNumProcessesSlow); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clear the prefs immediately so we don't pick them up on a future run 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->SetInteger(prefs::kShutdownType, NOT_VALID); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->SetInteger(prefs::kShutdownNumProcesses, 0); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->SetInteger(prefs::kShutdownNumProcessesSlow, 0); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read and delete the file on the file thread. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ReadLastShutdownFile, type, num_procs, num_procs_slow)); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetTryingToQuit(bool quitting) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_trying_to_quit = quitting; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsTryingToQuit() { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_trying_to_quit; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace browser_shutdown 341