browser_shutdown.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_shutdown.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/resource_bundle.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_path.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/histogram.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/process_util.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/thread.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/waitable_event.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "build/build_config.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chrome_thread.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/dom_ui/chrome_url_data_manager.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/first_run.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/jankometer.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/metrics/metrics_service.h" 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/plugin_process_host.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/pref_service.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_process_host.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_widget_host.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_plugin_lib.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/predictor_api.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/rlz/rlz.h" 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::Time; 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing base::TimeDelta; 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_shutdown { 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Whether the browser is trying to quit (e.g., Quit chosen from menu). 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool g_trying_to_quit = false; 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTime shutdown_started_; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochShutdownType shutdown_type_ = NOT_VALID; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint shutdown_num_processes_; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint shutdown_num_processes_slow_; 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool delete_resources_on_shutdown = true; 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kShutdownMsFile[] = "chrome_shutdown_ms.txt"; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid RegisterPrefs(PrefService* local_state) { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kShutdownType, NOT_VALID); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kShutdownNumProcesses, 0); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch local_state->RegisterIntegerPref(prefs::kShutdownNumProcessesSlow, 0); 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochShutdownType GetShutdownType() { 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return shutdown_type_; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid OnShutdownStarting(ShutdownType type) { 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (shutdown_type_ != NOT_VALID) 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shutdown_type_ = type; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For now, we're only counting the number of renderer processes 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // since we can't safely count the number of plugin processes from this 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // thread, and we'd really like to avoid anything which might add further 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // delays to shutdown time. 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shutdown_started_ = Time::Now(); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Call FastShutdown on all of the RenderProcessHosts. This will be 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a no-op in some cases, so we still need to go through the normal 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // shutdown path for the ones that didn't exit here. 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shutdown_num_processes_ = 0; 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shutdown_num_processes_slow_ = 0; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !i.IsAtEnd(); i.Advance()) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++shutdown_num_processes_; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!i.GetCurrentValue()->FastShutdownIfPossible()) 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++shutdown_num_processes_slow_; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFilePath GetShutdownMsPath() { 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath shutdown_ms_file; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PathService::Get(chrome::DIR_USER_DATA, &shutdown_ms_file); 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return shutdown_ms_file.AppendASCII(kShutdownMsFile); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid Shutdown() { 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unload plugins. This needs to happen on the IO thread. 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::PostTask( 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::IO, FROM_HERE, 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableFunction(&ChromePluginLib::UnloadAllPlugins)); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // WARNING: During logoff/shutdown (WM_ENDSESSION) we may not have enough 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // time to get here. If you have something that *must* happen on end session, 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // consider putting it in BrowserProcessImpl::EndSession. 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(g_browser_process); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notifies we are going away. 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_browser_process->shutdown_event()->Signal(); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* prefs = g_browser_process->local_state(); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome_browser_net::SavePredictorStateForNextStartupAndTrim(prefs); 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MetricsService* metrics = g_browser_process->metrics_service(); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (metrics) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metrics->RecordCleanShutdown(); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metrics->RecordCompletedSessionEnd(); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) { 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Record the shutdown info so that we can put it into a histogram at next 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // startup. 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetInteger(prefs::kShutdownType, shutdown_type_); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetInteger(prefs::kShutdownNumProcesses, shutdown_num_processes_); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetInteger(prefs::kShutdownNumProcessesSlow, 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shutdown_num_processes_slow_); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check local state for the restart flag so we can restart the session below. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool restart_last_session = false; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (prefs->HasPrefPath(prefs::kRestartLastSessionOnShutdown)) { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch restart_last_session = 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->GetBoolean(prefs::kRestartLastSessionOnShutdown); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->ClearPref(prefs::kRestartLastSessionOnShutdown); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SavePersistentPrefs(); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Cleanup any statics created by RLZ. Must be done before NotificationService 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // is destroyed. 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch RLZTracker::CleanupRlz(); 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The jank'o'meter requires that the browser process has been destroyed 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // before calling UninstallJankometer(). 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete g_browser_process; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_browser_process = NULL; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Uninstall Jank-O-Meter here after the IO thread is no longer running. 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UninstallJankometer(); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (delete_resources_on_shutdown) 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceBundle::CleanupSharedInstance(); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!Upgrade::IsBrowserAlreadyRunning() && 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shutdown_type_ != browser_shutdown::END_SESSION) { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Upgrade::SwapNewChromeExeIfPresent(); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (restart_last_session) { 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if !defined(OS_CHROMEOS) 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Make sure to relaunch the browser with the original command line plus 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the Restore Last Session flag. Note that Chrome can be launched (ie. 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // through ShellExecute on Windows) with a switch argument terminator at 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the end (double dash, as described in b/1366444) plus a URL, 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // which prevents us from appending to the command line directly (issue 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 46182). We therefore use GetSwitches to copy the command line (it stops 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // at the switch argument terminator). 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CommandLine old_cl(*CommandLine::ForCurrentProcess()); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<CommandLine> new_cl(new CommandLine(old_cl.GetProgram())); 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::map<std::string, CommandLine::StringType> switches = 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch old_cl.GetSwitches(); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Append the old switches to the new command line. 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (std::map<std::string, CommandLine::StringType>::const_iterator i = 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switches.begin(); i != switches.end(); ++i) { 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CommandLine::StringType switch_value = i->second; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!switch_value.empty()) 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_cl->AppendSwitchWithValue(i->first, i->second); 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_cl->AppendSwitch(i->first); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ensure restore last session is set. 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!new_cl->HasSwitch(switches::kRestoreLastSession)) 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_cl->AppendSwitch(switches::kRestoreLastSession); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) || defined(OS_LINUX) 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Upgrade::RelaunchChromeBrowser(*new_cl.get()); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // defined(OS_WIN) || defined(OS_LINUX) 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX) 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_cl->AppendSwitch(switches::kActivateOnLaunch); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::LaunchApp(*new_cl.get(), false, false, NULL); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // defined(OS_MACOSX) 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTIMPLEMENTED(); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // !defined(OS_CHROMEOS) 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) { 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Measure total shutdown time as late in the process as possible 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and then write it to a file to be read at startup. 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We can't use prefs since all services are shutdown at this point. 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta shutdown_delta = Time::Now() - shutdown_started_; 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string shutdown_ms = Int64ToString(shutdown_delta.InMilliseconds()); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int len = static_cast<int>(shutdown_ms.length()) + 1; 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath shutdown_ms_file = GetShutdownMsPath(); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::WriteFile(shutdown_ms_file, shutdown_ms.c_str(), len); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnregisterURLRequestChromeJob(); 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ReadLastShutdownFile( 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ShutdownType type, 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_procs, 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_procs_slow) { 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath shutdown_ms_file = GetShutdownMsPath(); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string shutdown_ms_str; 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 shutdown_ms = 0; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (file_util::ReadFileToString(shutdown_ms_file, &shutdown_ms_str)) 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shutdown_ms = StringToInt64(shutdown_ms_str); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch file_util::Delete(shutdown_ms_file, false); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == NOT_VALID || shutdown_ms == 0 || num_procs == 0) 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char *time_fmt = "Shutdown.%s.time"; 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char *time_per_fmt = "Shutdown.%s.time_per_process"; 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string time; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string time_per; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == WINDOW_CLOSE) { 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch time = StringPrintf(time_fmt, "window_close"); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch time_per = StringPrintf(time_per_fmt, "window_close"); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type == BROWSER_EXIT) { 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch time = StringPrintf(time_fmt, "browser_exit"); 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch time_per = StringPrintf(time_per_fmt, "browser_exit"); 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (type == END_SESSION) { 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch time = StringPrintf(time_fmt, "end_session"); 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch time_per = StringPrintf(time_per_fmt, "end_session"); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (time.empty()) 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(erikkay): change these to UMA histograms after a bit more testing. 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_TIMES(time.c_str(), 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromMilliseconds(shutdown_ms)); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_TIMES(time_per.c_str(), 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TimeDelta::FromMilliseconds(shutdown_ms / num_procs)); 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.total", num_procs); 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.slow", num_procs_slow); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ReadLastShutdownInfo() { 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PrefService* prefs = g_browser_process->local_state(); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ShutdownType type = 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<ShutdownType>(prefs->GetInteger(prefs::kShutdownType)); 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_procs = prefs->GetInteger(prefs::kShutdownNumProcesses); 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int num_procs_slow = prefs->GetInteger(prefs::kShutdownNumProcessesSlow); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // clear the prefs immediately so we don't pick them up on a future run 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetInteger(prefs::kShutdownType, NOT_VALID); 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetInteger(prefs::kShutdownNumProcesses, 0); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs->SetInteger(prefs::kShutdownNumProcessesSlow, 0); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Read and delete the file on the file thread. 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::PostTask( 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::FILE, FROM_HERE, 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableFunction( 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &ReadLastShutdownFile, type, num_procs, num_procs_slow)); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SetTryingToQuit(bool quitting) { 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch g_trying_to_quit = quitting; 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsTryingToQuit() { 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return g_trying_to_quit; 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace browser_shutdown 291