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