// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file defines the methods useful for uninstalling Chrome.

#include "chrome/installer/setup/uninstall.h"

#include <windows.h>

#include <vector>

#include "base/base_paths.h"
#include "base/file_util.h"
#include "base/files/file_enumerator.h"
#include "base/path_service.h"
#include "base/process/kill.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#include "base/win/scoped_handle.h"
#include "base/win/shortcut.h"
#include "base/win/windows_version.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_result_codes.h"
#include "chrome/installer/launcher_support/chrome_launcher_support.h"
#include "chrome/installer/setup/install.h"
#include "chrome/installer/setup/install_worker.h"
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/setup/setup_util.h"
#include "chrome/installer/util/auto_launch_util.h"
#include "chrome/installer/util/browser_distribution.h"
#include "chrome/installer/util/channel_info.h"
#include "chrome/installer/util/delete_after_reboot_helper.h"
#include "chrome/installer/util/firewall_manager_win.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
#include "chrome/installer/util/helper.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/installation_state.h"
#include "chrome/installer/util/installer_state.h"
#include "chrome/installer/util/logging_installer.h"
#include "chrome/installer/util/self_cleaning_temp_dir.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/installer/util/util_constants.h"
#include "chrome/installer/util/work_item.h"
#include "content/public/common/result_codes.h"
#include "rlz/lib/rlz_lib.h"

using base::win::RegKey;

namespace installer {

namespace {

// Avoid leaving behind a Temp dir.  If one exists, ask SelfCleaningTempDir to
// clean it up for us.  This may involve scheduling it for deletion after
// reboot.  Don't report that a reboot is required in this case, however.
// TODO(erikwright): Shouldn't this still lead to
// ScheduleParentAndGrandparentForDeletion?
void DeleteInstallTempDir(const base::FilePath& target_path) {
  base::FilePath temp_path(target_path.DirName().Append(
      installer::kInstallTempDir));
  if (base::DirectoryExists(temp_path)) {
    SelfCleaningTempDir temp_dir;
    if (!temp_dir.Initialize(target_path.DirName(),
                             installer::kInstallTempDir) ||
        !temp_dir.Delete()) {
      LOG(ERROR) << "Failed to delete temp dir " << temp_path.value();
    }
  }
}

// Iterates over the list of distribution types in |dist_types|, and
// adds to |update_list| the work item to update the corresponding "ap"
// registry value specified in |channel_info|.
void AddChannelValueUpdateWorkItems(
    const InstallationState& original_state,
    const InstallerState& installer_state,
    const ChannelInfo& channel_info,
    const std::vector<BrowserDistribution::Type>& dist_types,
    WorkItemList* update_list) {
  const bool system_level = installer_state.system_install();
  const HKEY reg_root = installer_state.root_key();
  for (size_t i = 0; i < dist_types.size(); ++i) {
    BrowserDistribution::Type dist_type = dist_types[i];
    const ProductState* product_state =
        original_state.GetProductState(system_level, dist_type);
    // Only modify other products if they're installed and multi.
    if (product_state != NULL &&
        product_state->is_multi_install() &&
        !product_state->channel().Equals(channel_info)) {
      BrowserDistribution* other_dist =
          BrowserDistribution::GetSpecificDistribution(dist_type);
      update_list->AddSetRegValueWorkItem(reg_root,
                                          other_dist->GetStateKey(),
                                          KEY_WOW64_32KEY,
                                          google_update::kRegApField,
                                          channel_info.value(),
                                          true);
    } else {
      LOG_IF(ERROR,
             product_state != NULL && product_state->is_multi_install())
          << "Channel value for "
          << BrowserDistribution::GetSpecificDistribution(
                 dist_type)->GetDisplayName()
          << " is somehow already set to the desired new value of "
          << channel_info.value();
    }
  }
}

// Makes appropriate changes to the Google Update "ap" value in the registry.
// Specifically, removes the flags associated with this product ("-chrome" or
// "-chromeframe") from the "ap" values for all other installed products and for
// the multi-installer package.
void ProcessGoogleUpdateItems(const InstallationState& original_state,
                              const InstallerState& installer_state,
                              const Product& product) {
  DCHECK(installer_state.is_multi_install());
  const bool system_level = installer_state.system_install();
  BrowserDistribution* distribution = product.distribution();
  const ProductState* product_state =
      original_state.GetProductState(system_level, distribution->GetType());
  DCHECK(product_state != NULL);
  ChannelInfo channel_info;

  // Remove product's flags from the channel value.
  channel_info.set_value(product_state->channel().value());
  const bool modified = product.SetChannelFlags(false, &channel_info);

  // Apply the new channel value to all other products and to the multi package.
  if (modified) {
    scoped_ptr<WorkItemList>
        update_list(WorkItem::CreateNoRollbackWorkItemList());
    std::vector<BrowserDistribution::Type> dist_types;
    for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
      BrowserDistribution::Type other_dist_type =
          static_cast<BrowserDistribution::Type>(i);
      if (distribution->GetType() != other_dist_type)
        dist_types.push_back(other_dist_type);
    }
    AddChannelValueUpdateWorkItems(original_state, installer_state,
                                   channel_info, dist_types,
                                   update_list.get());
    bool success = update_list->Do();
    LOG_IF(ERROR, !success) << "Failed updating channel values.";
  }
}

void ProcessOnOsUpgradeWorkItems(const InstallerState& installer_state,
                                 const Product& product) {
  scoped_ptr<WorkItemList> work_item_list(
      WorkItem::CreateNoRollbackWorkItemList());
  AddOsUpgradeWorkItems(installer_state, base::FilePath(), Version(), product,
                        work_item_list.get());
  if (!work_item_list->Do())
    LOG(ERROR) << "Failed to remove on-os-upgrade command.";
}

void ProcessIELowRightsPolicyWorkItems(const InstallerState& installer_state) {
  scoped_ptr<WorkItemList> work_items(WorkItem::CreateNoRollbackWorkItemList());
  AddDeleteOldIELowRightsPolicyWorkItems(installer_state, work_items.get());
  work_items->Do();
  RefreshElevationPolicy();
}

void ClearRlzProductState() {
  const rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX,
                                         rlz_lib::CHROME_HOME_PAGE,
                                         rlz_lib::CHROME_APP_LIST,
                                         rlz_lib::NO_ACCESS_POINT};

  rlz_lib::ClearProductState(rlz_lib::CHROME, points);

  // If chrome has been reactivated, clear all events for this brand as well.
  base::string16 reactivation_brand_wide;
  if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand_wide)) {
    std::string reactivation_brand(base::UTF16ToASCII(reactivation_brand_wide));
    rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
    rlz_lib::ClearProductState(rlz_lib::CHROME, points);
  }
}

// Decides whether setup.exe and the installer archive should be removed based
// on the original and installer states:
// * non-multi product being uninstalled: remove both
// * any multi product left besides App Host: keep both
// * only App Host left: keep setup.exe
void CheckShouldRemoveSetupAndArchive(const InstallationState& original_state,
                                      const InstallerState& installer_state,
                                      bool* remove_setup,
                                      bool* remove_archive) {
  *remove_setup = true;
  *remove_archive = true;

  // If any multi-install product is left (other than App Host) we must leave
  // the installer and archive. For the App Host, we only leave the installer.
  if (!installer_state.is_multi_install()) {
    VLOG(1) << "Removing all installer files for a non-multi installation.";
  } else {
    // Loop through all known products...
    for (size_t i = 0; i < BrowserDistribution::NUM_TYPES; ++i) {
      BrowserDistribution::Type dist_type =
          static_cast<BrowserDistribution::Type>(i);
      const ProductState* product_state = original_state.GetProductState(
          installer_state.system_install(), dist_type);
      // If the product is installed, in multi mode, and is not part of the
      // active uninstallation...
      if (product_state && product_state->is_multi_install() &&
          !installer_state.FindProduct(dist_type)) {
        // setup.exe will not be removed as there is a remaining multi-install
        // product.
        *remove_setup = false;
        // As a special case, we can still remove the actual archive if the
        // only remaining product is the App Host.
        if (dist_type != BrowserDistribution::CHROME_APP_HOST) {
          VLOG(1) << "Keeping all installer files due to a remaining "
                  << "multi-install product.";
          *remove_archive = false;
          return;
        }
        VLOG(1) << "Keeping setup.exe due to a remaining "
                << "app-host installation.";
      }
    }
    VLOG(1) << "Removing the installer archive.";
    if (remove_setup)
      VLOG(1) << "Removing setup.exe.";
  }
}

// Removes all files from the installer directory, leaving setup.exe iff
// |remove_setup| is false.
// Returns false in case of an error.
bool RemoveInstallerFiles(const base::FilePath& installer_directory,
                          bool remove_setup) {
  base::FileEnumerator file_enumerator(
      installer_directory,
      false,
      base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
  bool success = true;

  base::FilePath setup_exe_base_name(installer::kSetupExe);

  for (base::FilePath to_delete = file_enumerator.Next(); !to_delete.empty();
       to_delete = file_enumerator.Next()) {
    if (!remove_setup && to_delete.BaseName() == setup_exe_base_name)
      continue;

    VLOG(1) << "Deleting installer path " << to_delete.value();
    if (!base::DeleteFile(to_delete, true)) {
      LOG(ERROR) << "Failed to delete path: " << to_delete.value();
      success = false;
    }
  }

  return success;
}

// Kills all Chrome processes, immediately.
void CloseAllChromeProcesses() {
  base::CleanupProcesses(installer::kChromeExe, base::TimeDelta(),
                         content::RESULT_CODE_HUNG, NULL);
  base::CleanupProcesses(installer::kNaClExe, base::TimeDelta(),
                         content::RESULT_CODE_HUNG, NULL);
}

// Attempts to close the Chrome Frame helper process by sending WM_CLOSE
// messages to its window, or just killing it if that doesn't work.
void CloseChromeFrameHelperProcess() {
  HWND window = FindWindow(installer::kChromeFrameHelperWndClass, NULL);
  if (!::IsWindow(window))
    return;

  const DWORD kWaitMs = 3000;

  DWORD pid = 0;
  ::GetWindowThreadProcessId(window, &pid);
  DCHECK_NE(pid, 0U);
  base::win::ScopedHandle process(::OpenProcess(SYNCHRONIZE, FALSE, pid));
  PLOG_IF(INFO, !process) << "Failed to open process: " << pid;

  bool kill = true;
  if (SendMessageTimeout(window, WM_CLOSE, 0, 0, SMTO_BLOCK, kWaitMs, NULL) &&
      process) {
    VLOG(1) << "Waiting for " << installer::kChromeFrameHelperExe;
    DWORD wait = ::WaitForSingleObject(process, kWaitMs);
    if (wait != WAIT_OBJECT_0) {
      LOG(WARNING) << "Wait for " << installer::kChromeFrameHelperExe
                   << " to exit failed or timed out.";
    } else {
      kill = false;
      VLOG(1) << installer::kChromeFrameHelperExe << " exited normally.";
    }
  }

  if (kill) {
    VLOG(1) << installer::kChromeFrameHelperExe << " hung.  Killing.";
    base::CleanupProcesses(installer::kChromeFrameHelperExe, base::TimeDelta(),
                           content::RESULT_CODE_HUNG, NULL);
  }
}

// Updates shortcuts to |old_target_exe| that have non-empty args, making them
// target |new_target_exe| instead. The non-empty args requirement is a
// heuristic to determine whether a shortcut is "user-generated". This routine
// can only be called for user-level installs.
void RetargetUserShortcutsWithArgs(const InstallerState& installer_state,
                                   const Product& product,
                                   const base::FilePath& old_target_exe,
                                   const base::FilePath& new_target_exe) {
  if (installer_state.system_install()) {
    NOTREACHED();
    return;
  }
  BrowserDistribution* dist = product.distribution();
  ShellUtil::ShellChange install_level = ShellUtil::CURRENT_USER;

  // Retarget all shortcuts that point to |old_target_exe| from all
  // ShellUtil::ShortcutLocations.
  VLOG(1) << "Retargeting shortcuts.";
  for (int location = ShellUtil::SHORTCUT_LOCATION_FIRST;
      location < ShellUtil::NUM_SHORTCUT_LOCATIONS; ++location) {
    if (!ShellUtil::RetargetShortcutsWithArgs(
            static_cast<ShellUtil::ShortcutLocation>(location), dist,
            install_level, old_target_exe, new_target_exe)) {
      LOG(WARNING) << "Failed to retarget shortcuts in ShortcutLocation: "
                   << location;
    }
  }
}

// Deletes shortcuts at |install_level| from Start menu, Desktop,
// Quick Launch, taskbar, and secondary tiles on the Start Screen (Win8+).
// Only shortcuts pointing to |target_exe| will be removed.
void DeleteShortcuts(const InstallerState& installer_state,
                     const Product& product,
                     const base::FilePath& target_exe) {
  BrowserDistribution* dist = product.distribution();

  // The per-user shortcut for this user, if present on a system-level install,
  // has already been deleted in chrome_browser_main_win.cc::DoUninstallTasks().
  ShellUtil::ShellChange install_level = installer_state.system_install() ?
      ShellUtil::SYSTEM_LEVEL : ShellUtil::CURRENT_USER;

  // Delete and unpin all shortcuts that point to |target_exe| from all
  // ShellUtil::ShortcutLocations.
  VLOG(1) << "Deleting shortcuts.";
  for (int location = ShellUtil::SHORTCUT_LOCATION_FIRST;
      location < ShellUtil::NUM_SHORTCUT_LOCATIONS; ++location) {
    if (!ShellUtil::RemoveShortcuts(
            static_cast<ShellUtil::ShortcutLocation>(location), dist,
            install_level, target_exe)) {
      LOG(WARNING) << "Failed to delete shortcuts in ShortcutLocation:"
                   << location;
    }
  }
}

bool ScheduleParentAndGrandparentForDeletion(const base::FilePath& path) {
  base::FilePath parent_dir = path.DirName();
  bool ret = ScheduleFileSystemEntityForDeletion(parent_dir);
  if (!ret) {
    LOG(ERROR) << "Failed to schedule parent dir for deletion: "
               << parent_dir.value();
  } else {
    base::FilePath grandparent_dir(parent_dir.DirName());
    ret = ScheduleFileSystemEntityForDeletion(grandparent_dir);
    if (!ret) {
      LOG(ERROR) << "Failed to schedule grandparent dir for deletion: "
                 << grandparent_dir.value();
    }
  }
  return ret;
}

// Deletes the given directory if it is empty. Returns DELETE_SUCCEEDED if the
// directory is deleted, DELETE_NOT_EMPTY if it is not empty, and DELETE_FAILED
// otherwise.
DeleteResult DeleteEmptyDir(const base::FilePath& path) {
  if (!base::IsDirectoryEmpty(path))
    return DELETE_NOT_EMPTY;

  if (base::DeleteFile(path, true))
    return DELETE_SUCCEEDED;

  LOG(ERROR) << "Failed to delete folder: " << path.value();
  return DELETE_FAILED;
}

// Get the user data directory, which is *not* DIR_USER_DATA for Chrome Frame.
// TODO(grt): Remove Chrome Frame uninstall support when usage is low enough.
base::FilePath GetUserDataDir(const Product& product) {
  base::FilePath path;
  bool is_chrome_frame = product.is_chrome_frame();
  int key = is_chrome_frame ? base::DIR_LOCAL_APP_DATA : chrome::DIR_USER_DATA;
  if (!PathService::Get(key, &path))
    return base::FilePath();
  if (is_chrome_frame) {
    path = path.Append(product.distribution()->GetInstallSubDir());
    path = path.Append(chrome::kUserDataDirname);
  }
  return path;
}

// Creates a copy of the local state file and returns a path to the copy.
base::FilePath BackupLocalStateFile(const base::FilePath& user_data_dir) {
  base::FilePath backup;
  base::FilePath state_file(user_data_dir.Append(chrome::kLocalStateFilename));
  if (!base::CreateTemporaryFile(&backup))
    LOG(ERROR) << "Failed to create temporary file for Local State.";
  else
    base::CopyFile(state_file, backup);
  return backup;
}

// Deletes a given user data directory as well as the containing product
// directories if they are empty (e.g., "Google\Chrome").
DeleteResult DeleteUserDataDir(const base::FilePath& user_data_dir,
                               bool schedule_on_failure) {
  if (user_data_dir.empty())
    return DELETE_SUCCEEDED;

  DeleteResult result = DELETE_SUCCEEDED;
  VLOG(1) << "Deleting user profile " << user_data_dir.value();
  if (!base::DeleteFile(user_data_dir, true)) {
    LOG(ERROR) << "Failed to delete user profile dir: "
               << user_data_dir.value();
    if (schedule_on_failure) {
      ScheduleDirectoryForDeletion(user_data_dir);
      result = DELETE_REQUIRES_REBOOT;
    } else {
      result = DELETE_FAILED;
    }
  }

  if (result == DELETE_REQUIRES_REBOOT) {
    ScheduleParentAndGrandparentForDeletion(user_data_dir);
  } else {
    const base::FilePath user_data_dir(user_data_dir.DirName());
    if (!user_data_dir.empty() &&
        DeleteEmptyDir(user_data_dir) == DELETE_SUCCEEDED) {
      const base::FilePath product_dir(user_data_dir.DirName());
      if (!product_dir.empty())
        DeleteEmptyDir(product_dir);
    }
  }

  return result;
}

// Moves setup to a temporary file, outside of the install folder. Also attempts
// to change the current directory to the TMP directory. On Windows, each
// process has a handle to its CWD. If setup.exe's CWD happens to be within the
// install directory, deletion will fail as a result of the open handle.
bool MoveSetupOutOfInstallFolder(const InstallerState& installer_state,
                                 const base::FilePath& setup_exe) {
  // The list of files which setup.exe depends on at runtime. Typically this is
  // solely setup.exe itself, but in component builds this also includes the
  // DLLs installed by setup.exe.
  std::vector<base::FilePath> setup_files;
  setup_files.push_back(setup_exe);
#if defined(COMPONENT_BUILD)
  base::FileEnumerator file_enumerator(
      setup_exe.DirName(), false, base::FileEnumerator::FILES, L"*.dll");
  for (base::FilePath setup_dll = file_enumerator.Next(); !setup_dll.empty();
       setup_dll = file_enumerator.Next()) {
    setup_files.push_back(setup_dll);
  }
#endif  // defined(COMPONENT_BUILD)

  base::FilePath tmp_dir;
  base::FilePath temp_file;
  if (!PathService::Get(base::DIR_TEMP, &tmp_dir)) {
    NOTREACHED();
    return false;
  }

  // Change the current directory to the TMP directory. See method comment above
  // for details.
  VLOG(1) << "Changing current directory to: " << tmp_dir.value();
  if (!base::SetCurrentDirectory(tmp_dir))
    PLOG(ERROR) << "Failed to change the current directory.";

  for (std::vector<base::FilePath>::const_iterator it = setup_files.begin();
       it != setup_files.end(); ++it) {
    const base::FilePath& setup_file = *it;
    if (!base::CreateTemporaryFileInDir(tmp_dir, &temp_file)) {
      LOG(ERROR) << "Failed to create temporary file for "
                 << setup_file.BaseName().value();
      return false;
    }

    VLOG(1) << "Attempting to move " << setup_file.BaseName().value() << " to: "
            << temp_file.value();
    if (!base::Move(setup_file, temp_file)) {
      PLOG(ERROR) << "Failed to move " << setup_file.BaseName().value()
                  << " to " << temp_file.value();
      return false;
    }

    // We cannot delete the file right away, but try to delete it some other
    // way. Either with the help of a different process or the system.
    if (!base::DeleteFileAfterReboot(temp_file)) {
      const uint32 kDeleteAfterMs = 10 * 1000;
      installer::DeleteFileFromTempProcess(temp_file, kDeleteAfterMs);
    }
  }
  return true;
}

DeleteResult DeleteAppHostFilesAndFolders(const InstallerState& installer_state,
                                          const Version& installed_version) {
  const base::FilePath& target_path = installer_state.target_path();
  if (target_path.empty()) {
    LOG(ERROR) << "DeleteAppHostFilesAndFolders: no installation destination "
               << "path.";
    return DELETE_FAILED;  // Nothing else we can do to uninstall, so we return.
  }

  DeleteInstallTempDir(target_path);

  DeleteResult result = DELETE_SUCCEEDED;

  base::FilePath app_host_exe(target_path.Append(installer::kChromeAppHostExe));
  if (!base::DeleteFile(app_host_exe, false)) {
    result = DELETE_FAILED;
    LOG(ERROR) << "Failed to delete path: " << app_host_exe.value();
  }

  return result;
}

DeleteResult DeleteChromeFilesAndFolders(const InstallerState& installer_state,
                                         const base::FilePath& setup_exe) {
  const base::FilePath& target_path = installer_state.target_path();
  if (target_path.empty()) {
    LOG(ERROR) << "DeleteChromeFilesAndFolders: no installation destination "
               << "path.";
    return DELETE_FAILED;  // Nothing else we can do to uninstall, so we return.
  }

  DeleteInstallTempDir(target_path);

  DeleteResult result = DELETE_SUCCEEDED;

  base::FilePath installer_directory;
  if (target_path.IsParent(setup_exe))
    installer_directory = setup_exe.DirName();

  // Enumerate all the files in target_path recursively (breadth-first).
  // We delete a file or folder unless it is a parent/child of the installer
  // directory. For parents of the installer directory, we will later recurse
  // and delete all the children (that are not also parents/children of the
  // installer directory).
  base::FileEnumerator file_enumerator(target_path, true,
      base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
  for (base::FilePath to_delete = file_enumerator.Next(); !to_delete.empty();
       to_delete = file_enumerator.Next()) {
    if (to_delete.BaseName().value() == installer::kChromeAppHostExe)
      continue;
    if (!installer_directory.empty() &&
        (to_delete == installer_directory ||
         installer_directory.IsParent(to_delete) ||
         to_delete.IsParent(installer_directory))) {
      continue;
    }

    VLOG(1) << "Deleting install path " << to_delete.value();
    if (!base::DeleteFile(to_delete, true)) {
      LOG(ERROR) << "Failed to delete path (1st try): " << to_delete.value();
      if (installer_state.FindProduct(BrowserDistribution::CHROME_FRAME)) {
        // We don't try killing Chrome processes for Chrome Frame builds since
        // that is unlikely to help. Instead, schedule files for deletion and
        // return a value that will trigger a reboot prompt.
        base::FileEnumerator::FileInfo find_info = file_enumerator.GetInfo();
        if (find_info.IsDirectory())
          ScheduleDirectoryForDeletion(to_delete);
        else
          ScheduleFileSystemEntityForDeletion(to_delete);
        result = DELETE_REQUIRES_REBOOT;
      } else {
        // Try closing any running Chrome processes and deleting files once
        // again.
        CloseAllChromeProcesses();
        if (!base::DeleteFile(to_delete, true)) {
          LOG(ERROR) << "Failed to delete path (2nd try): "
                     << to_delete.value();
          result = DELETE_FAILED;
          break;
        }
      }
    }
  }

  return result;
}

// This method checks if Chrome is currently running or if the user has
// cancelled the uninstall operation by clicking Cancel on the confirmation
// box that Chrome pops up.
InstallStatus IsChromeActiveOrUserCancelled(
    const InstallerState& installer_state,
    const Product& product) {
  int32 exit_code = content::RESULT_CODE_NORMAL_EXIT;
  CommandLine options(CommandLine::NO_PROGRAM);
  options.AppendSwitch(installer::switches::kUninstall);

  // Here we want to save user from frustration (in case of Chrome crashes)
  // and continue with the uninstallation as long as chrome.exe process exit
  // code is NOT one of the following:
  // - UNINSTALL_CHROME_ALIVE - chrome.exe is currently running
  // - UNINSTALL_USER_CANCEL - User cancelled uninstallation
  // - HUNG - chrome.exe was killed by HuntForZombieProcesses() (until we can
  //          give this method some brains and not kill chrome.exe launched
  //          by us, we will not uninstall if we get this return code).
  VLOG(1) << "Launching Chrome to do uninstall tasks.";
  if (product.LaunchChromeAndWait(installer_state.target_path(), options,
                                  &exit_code)) {
    VLOG(1) << "chrome.exe launched for uninstall confirmation returned: "
            << exit_code;
    if ((exit_code == chrome::RESULT_CODE_UNINSTALL_CHROME_ALIVE) ||
        (exit_code == chrome::RESULT_CODE_UNINSTALL_USER_CANCEL) ||
        (exit_code == content::RESULT_CODE_HUNG))
      return installer::UNINSTALL_CANCELLED;

    if (exit_code == chrome::RESULT_CODE_UNINSTALL_DELETE_PROFILE)
      return installer::UNINSTALL_DELETE_PROFILE;
  } else {
    PLOG(ERROR) << "Failed to launch chrome.exe for uninstall confirmation.";
  }

  return installer::UNINSTALL_CONFIRMED;
}

bool ShouldDeleteProfile(const InstallerState& installer_state,
                         const CommandLine& cmd_line, InstallStatus status,
                         const Product& product) {
  bool should_delete = false;

  // Chrome Frame uninstallations always want to delete the profile (we have no
  // UI to prompt otherwise and the profile stores no useful data anyway)
  // unless they are managed by MSI. MSI uninstalls will explicitly include
  // the --delete-profile flag to distinguish them from MSI upgrades.
  if (product.is_chrome_frame() && !installer_state.is_msi()) {
    should_delete = true;
  } else {
    should_delete =
        status == installer::UNINSTALL_DELETE_PROFILE ||
        cmd_line.HasSwitch(installer::switches::kDeleteProfile);
  }

  return should_delete;
}

// Removes XP-era filetype registration making Chrome the default browser.
// MSDN (see http://msdn.microsoft.com/library/windows/desktop/cc144148.aspx)
// tells us not to do this, but certain applications break following
// uninstallation if we don't.
void RemoveFiletypeRegistration(const InstallerState& installer_state,
                                HKEY root,
                                const base::string16& browser_entry_suffix) {
  base::string16 classes_path(ShellUtil::kRegClasses);
  classes_path.push_back(base::FilePath::kSeparators[0]);

  BrowserDistribution* distribution = BrowserDistribution::GetDistribution();
  const base::string16 prog_id(
      distribution->GetBrowserProgIdPrefix() + browser_entry_suffix);

  // Delete each filetype association if it references this Chrome.  Take care
  // not to delete the association if it references a system-level install of
  // Chrome (only a risk if the suffix is empty).  Don't delete the whole key
  // since other apps may have stored data there.
  std::vector<const wchar_t*> cleared_assocs;
  if (installer_state.system_install() ||
      !browser_entry_suffix.empty() ||
      !base::win::RegKey(HKEY_LOCAL_MACHINE, (classes_path + prog_id).c_str(),
                         KEY_QUERY_VALUE).Valid()) {
    InstallUtil::ValueEquals prog_id_pred(prog_id);
    for (const wchar_t* const* filetype =
         &ShellUtil::kPotentialFileAssociations[0]; *filetype != NULL;
         ++filetype) {
      if (InstallUtil::DeleteRegistryValueIf(
              root, (classes_path + *filetype).c_str(), WorkItem::kWow64Default,
              NULL, prog_id_pred) == InstallUtil::DELETED) {
        cleared_assocs.push_back(*filetype);
      }
    }
  }

  // For all filetype associations in HKLM that have just been removed, attempt
  // to restore some reasonable value.  We have no definitive way of knowing
  // what handlers are the most appropriate, so we use a fixed mapping based on
  // the default values for a fresh install of Windows.
  if (root == HKEY_LOCAL_MACHINE) {
    base::string16 assoc;
    base::win::RegKey key;

    for (size_t i = 0; i < cleared_assocs.size(); ++i) {
      const wchar_t* replacement_prog_id = NULL;
      assoc.assign(cleared_assocs[i]);

      // Inelegant, but simpler than a pure data-driven approach.
      if (assoc == L".htm" || assoc == L".html")
        replacement_prog_id = L"htmlfile";
      else if (assoc == L".xht" || assoc == L".xhtml")
        replacement_prog_id = L"xhtmlfile";

      if (!replacement_prog_id) {
        LOG(WARNING) << "No known replacement ProgID for " << assoc
                     << " files.";
      } else if (key.Open(HKEY_LOCAL_MACHINE,
                          (classes_path + replacement_prog_id).c_str(),
                          KEY_QUERY_VALUE) == ERROR_SUCCESS &&
                 (key.Open(HKEY_LOCAL_MACHINE, (classes_path + assoc).c_str(),
                           KEY_SET_VALUE) != ERROR_SUCCESS ||
                  key.WriteValue(NULL, replacement_prog_id) != ERROR_SUCCESS)) {
        // The replacement ProgID is registered on the computer but the attempt
        // to set it for the filetype failed.
        LOG(ERROR) << "Failed to restore system-level filetype association "
                   << assoc << " = " << replacement_prog_id;
      }
    }
  }
}

// Builds and executes a work item list to remove DelegateExecute verb handler
// work items for |product|.  This will be a noop for products whose
// corresponding BrowserDistribution implementations do not publish a CLSID via
// GetCommandExecuteImplClsid.
bool ProcessDelegateExecuteWorkItems(const InstallerState& installer_state,
                                     const Product& product) {
  scoped_ptr<WorkItemList> item_list(WorkItem::CreateNoRollbackWorkItemList());
  AddDelegateExecuteWorkItems(installer_state, base::FilePath(), Version(),
                              product, item_list.get());
  return item_list->Do();
}

// Removes Active Setup entries from the registry. This cannot be done through
// a work items list as usual because of different paths based on conditionals,
// but otherwise respects the no rollback/best effort uninstall mentality.
// This will only apply for system-level installs of Chrome/Chromium and will be
// a no-op for all other types of installs.
void UninstallActiveSetupEntries(const InstallerState& installer_state,
                                 const Product& product) {
  VLOG(1) << "Uninstalling registry entries for ActiveSetup.";
  BrowserDistribution* distribution = product.distribution();

  if (!product.is_chrome() || !installer_state.system_install()) {
    const char* install_level =
        installer_state.system_install() ? "system" : "user";
    VLOG(1) << "No Active Setup processing to do for " << install_level
            << "-level " << distribution->GetDisplayName();
    return;
  }

  const base::string16 active_setup_path(
      InstallUtil::GetActiveSetupPath(distribution));
  InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, active_setup_path,
                                 WorkItem::kWow64Default);

  // Windows leaves keys behind in HKCU\\Software\\(Wow6432Node\\)?Microsoft\\
  //     Active Setup\\Installed Components\\{guid}
  // for every user that logged in since system-level Chrome was installed.
  // This is a problem because Windows compares the value of the Version subkey
  // in there with the value of the Version subkey in the matching HKLM entries
  // before running Chrome's Active Setup so if Chrome was to be reinstalled
  // with a lesser version (e.g. switching back to a more stable channel), the
  // affected users would not have Chrome's Active Setup called until Chrome
  // eventually updated passed that user's registered Version.
  //
  // It is however very hard to delete those values as the registry hives for
  // other users are not loaded by default under HKEY_USERS (unless a user is
  // logged on or has a process impersonating him).
  //
  // Following our best effort uninstall practices, try to delete the value in
  // all users hives. If a given user's hive is not loaded, try to load it to
  // proceed with the deletion (failure to do so is ignored).

  static const wchar_t kProfileList[] =
      L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\";

  // Windows automatically adds Wow6432Node when creating/deleting the HKLM key,
  // but doesn't seem to do so when manually deleting the user-level keys it
  // created.
  base::string16 alternate_active_setup_path(active_setup_path);
  alternate_active_setup_path.insert(arraysize("Software\\") - 1,
                                     L"Wow6432Node\\");

  // These two privileges are required by RegLoadKey() and RegUnloadKey() below.
  ScopedTokenPrivilege se_restore_name_privilege(SE_RESTORE_NAME);
  ScopedTokenPrivilege se_backup_name_privilege(SE_BACKUP_NAME);
  if (!se_restore_name_privilege.is_enabled() ||
      !se_backup_name_privilege.is_enabled()) {
    // This is not a critical failure as those privileges aren't required to
    // clean hives that are already loaded, but attempts to LoadRegKey() below
    // will fail.
    LOG(WARNING) << "Failed to enable privileges required to load registry "
                    "hives.";
  }

  for (base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE, kProfileList);
       it.Valid(); ++it) {
    const wchar_t* profile_sid = it.Name();

    // First check if this user's registry hive needs to be loaded in
    // HKEY_USERS.
    base::win::RegKey user_reg_root_probe(
        HKEY_USERS, profile_sid, KEY_READ);
    bool loaded_hive = false;
    if (!user_reg_root_probe.Valid()) {
      VLOG(1) << "Attempting to load registry hive for " << profile_sid;

      base::string16 reg_profile_info_path(kProfileList);
      reg_profile_info_path.append(profile_sid);
      base::win::RegKey reg_profile_info_key(
          HKEY_LOCAL_MACHINE, reg_profile_info_path.c_str(), KEY_READ);

      base::string16 profile_path;
      LONG result = reg_profile_info_key.ReadValue(L"ProfileImagePath",
                                                   &profile_path);
      if (result != ERROR_SUCCESS) {
        LOG(ERROR) << "Error reading ProfileImagePath: " << result;
        continue;
      }
      base::FilePath registry_hive_file(profile_path);
      registry_hive_file = registry_hive_file.AppendASCII("NTUSER.DAT");

      result = RegLoadKey(HKEY_USERS, profile_sid,
                          registry_hive_file.value().c_str());
      if (result != ERROR_SUCCESS) {
        LOG(ERROR) << "Error loading registry hive: " << result;
        continue;
      }

      VLOG(1) << "Loaded registry hive for " << profile_sid;
      loaded_hive = true;
    }

    base::win::RegKey user_reg_root(
        HKEY_USERS, profile_sid, KEY_ALL_ACCESS);

    LONG result = user_reg_root.DeleteKey(active_setup_path.c_str());
    if (result != ERROR_SUCCESS) {
      result = user_reg_root.DeleteKey(alternate_active_setup_path.c_str());
      if (result != ERROR_SUCCESS && result != ERROR_FILE_NOT_FOUND) {
        LOG(ERROR) << "Failed to delete key at " << active_setup_path
                   << " and at " << alternate_active_setup_path
                   << ", result: " << result;
      }
    }

    if (loaded_hive) {
      user_reg_root.Close();
      if (RegUnLoadKey(HKEY_USERS, profile_sid) == ERROR_SUCCESS)
        VLOG(1) << "Unloaded registry hive for " << profile_sid;
      else
        LOG(ERROR) << "Error unloading registry hive for " << profile_sid;
    }
  }
}

}  // namespace

DeleteResult DeleteChromeDirectoriesIfEmpty(
    const base::FilePath& application_directory) {
  DeleteResult result(DeleteEmptyDir(application_directory));
  if (result == DELETE_SUCCEEDED) {
    // Now check and delete if the parent directories are empty
    // For example Google\Chrome or Chromium
    const base::FilePath product_directory(application_directory.DirName());
    if (!product_directory.empty()) {
        result = DeleteEmptyDir(product_directory);
        if (result == DELETE_SUCCEEDED) {
          const base::FilePath vendor_directory(product_directory.DirName());
          if (!vendor_directory.empty())
            result = DeleteEmptyDir(vendor_directory);
        }
    }
  }
  if (result == DELETE_NOT_EMPTY)
    result = DELETE_SUCCEEDED;
  return result;
}

bool DeleteChromeRegistrationKeys(const InstallerState& installer_state,
                                  BrowserDistribution* dist,
                                  HKEY root,
                                  const base::string16& browser_entry_suffix,
                                  InstallStatus* exit_code) {
  DCHECK(exit_code);
  if (dist->GetDefaultBrowserControlPolicy() ==
      BrowserDistribution::DEFAULT_BROWSER_UNSUPPORTED) {
    // We should have never set those keys.
    return true;
  }

  base::FilePath chrome_exe(installer_state.target_path().Append(kChromeExe));

  // Delete Software\Classes\ChromeHTML.
  const base::string16 prog_id(
      dist->GetBrowserProgIdPrefix() + browser_entry_suffix);
  base::string16 reg_prog_id(ShellUtil::kRegClasses);
  reg_prog_id.push_back(base::FilePath::kSeparators[0]);
  reg_prog_id.append(prog_id);
  InstallUtil::DeleteRegistryKey(root, reg_prog_id, WorkItem::kWow64Default);

  // Delete Software\Classes\Chrome.
  base::string16 reg_app_id(ShellUtil::kRegClasses);
  reg_app_id.push_back(base::FilePath::kSeparators[0]);
  // Append the requested suffix manually here (as ShellUtil::GetBrowserModelId
  // would otherwise try to figure out the currently installed suffix).
  reg_app_id.append(dist->GetBaseAppId() + browser_entry_suffix);
  InstallUtil::DeleteRegistryKey(root, reg_app_id, WorkItem::kWow64Default);

  // Delete all Start Menu Internet registrations that refer to this Chrome.
  {
    using base::win::RegistryKeyIterator;
    InstallUtil::ProgramCompare open_command_pred(chrome_exe);
    base::string16 client_name;
    base::string16 client_key;
    base::string16 open_key;
    for (RegistryKeyIterator iter(root, ShellUtil::kRegStartMenuInternet);
         iter.Valid(); ++iter) {
      client_name.assign(iter.Name());
      client_key.assign(ShellUtil::kRegStartMenuInternet)
          .append(1, L'\\')
          .append(client_name);
      open_key.assign(client_key).append(ShellUtil::kRegShellOpen);
      if (InstallUtil::DeleteRegistryKeyIf(root, client_key, open_key,
              WorkItem::kWow64Default, NULL, open_command_pred)
                  != InstallUtil::NOT_FOUND) {
        // Delete the default value of SOFTWARE\Clients\StartMenuInternet if it
        // references this Chrome (i.e., if it was made the default browser).
        InstallUtil::DeleteRegistryValueIf(
            root, ShellUtil::kRegStartMenuInternet, WorkItem::kWow64Default,
            NULL, InstallUtil::ValueEquals(client_name));
        // Also delete the value for the default user if we're operating in
        // HKLM.
        if (root == HKEY_LOCAL_MACHINE) {
          InstallUtil::DeleteRegistryValueIf(
              HKEY_USERS,
              base::string16(L".DEFAULT\\").append(
                  ShellUtil::kRegStartMenuInternet).c_str(),
              WorkItem::kWow64Default, NULL,
              InstallUtil::ValueEquals(client_name));
        }
      }
    }
  }

  // Delete Software\RegisteredApplications\Chromium
  InstallUtil::DeleteRegistryValue(
      root, ShellUtil::kRegRegisteredApplications,
      WorkItem::kWow64Default,
      dist->GetBaseAppName() + browser_entry_suffix);

  // Delete the App Paths and Applications keys that let Explorer find Chrome:
  // http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121
  base::string16 app_key(ShellUtil::kRegClasses);
  app_key.push_back(base::FilePath::kSeparators[0]);
  app_key.append(L"Applications");
  app_key.push_back(base::FilePath::kSeparators[0]);
  app_key.append(installer::kChromeExe);
  InstallUtil::DeleteRegistryKey(root, app_key, WorkItem::kWow64Default);

  base::string16 app_path_key(ShellUtil::kAppPathsRegistryKey);
  app_path_key.push_back(base::FilePath::kSeparators[0]);
  app_path_key.append(installer::kChromeExe);
  InstallUtil::DeleteRegistryKey(root, app_path_key, WorkItem::kWow64Default);

  // Cleanup OpenWithList and OpenWithProgids:
  // http://msdn.microsoft.com/en-us/library/bb166549
  base::string16 file_assoc_key;
  base::string16 open_with_list_key;
  base::string16 open_with_progids_key;
  for (int i = 0; ShellUtil::kPotentialFileAssociations[i] != NULL; ++i) {
    file_assoc_key.assign(ShellUtil::kRegClasses);
    file_assoc_key.push_back(base::FilePath::kSeparators[0]);
    file_assoc_key.append(ShellUtil::kPotentialFileAssociations[i]);
    file_assoc_key.push_back(base::FilePath::kSeparators[0]);

    open_with_list_key.assign(file_assoc_key);
    open_with_list_key.append(L"OpenWithList");
    open_with_list_key.push_back(base::FilePath::kSeparators[0]);
    open_with_list_key.append(installer::kChromeExe);
    InstallUtil::DeleteRegistryKey(
        root, open_with_list_key, WorkItem::kWow64Default);

    open_with_progids_key.assign(file_assoc_key);
    open_with_progids_key.append(ShellUtil::kRegOpenWithProgids);
    InstallUtil::DeleteRegistryValue(root, open_with_progids_key,
                                     WorkItem::kWow64Default, prog_id);
  }

  // Cleanup in case Chrome had been made the default browser.

  // Delete the default value of SOFTWARE\Clients\StartMenuInternet if it
  // references this Chrome.  Do this explicitly here for the case where HKCU is
  // being processed; the iteration above will have no hits since registration
  // lives in HKLM.
  InstallUtil::DeleteRegistryValueIf(
      root, ShellUtil::kRegStartMenuInternet, WorkItem::kWow64Default, NULL,
      InstallUtil::ValueEquals(dist->GetBaseAppName() + browser_entry_suffix));

  // Delete each protocol association if it references this Chrome.
  InstallUtil::ProgramCompare open_command_pred(chrome_exe);
  base::string16 parent_key(ShellUtil::kRegClasses);
  parent_key.push_back(base::FilePath::kSeparators[0]);
  const base::string16::size_type base_length = parent_key.size();
  base::string16 child_key;
  for (const wchar_t* const* proto =
           &ShellUtil::kPotentialProtocolAssociations[0];
       *proto != NULL;
       ++proto) {
    parent_key.resize(base_length);
    parent_key.append(*proto);
    child_key.assign(parent_key).append(ShellUtil::kRegShellOpen);
    InstallUtil::DeleteRegistryKeyIf(root, parent_key, child_key,
                                     WorkItem::kWow64Default, NULL,
                                     open_command_pred);
  }

  RemoveFiletypeRegistration(installer_state, root, browser_entry_suffix);

  *exit_code = installer::UNINSTALL_SUCCESSFUL;
  return true;
}

void RemoveChromeLegacyRegistryKeys(BrowserDistribution* dist,
                                    const base::string16& chrome_exe) {
  // We used to register Chrome to handle crx files, but this turned out
  // to be not worth the hassle. Remove these old registry entries if
  // they exist. See: http://codereview.chromium.org/210007

#if defined(GOOGLE_CHROME_BUILD)
const wchar_t kChromeExtProgId[] = L"ChromeExt";
#else
const wchar_t kChromeExtProgId[] = L"ChromiumExt";
#endif

  HKEY roots[] = { HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER };
  for (size_t i = 0; i < arraysize(roots); ++i) {
    base::string16 suffix;
    if (roots[i] == HKEY_LOCAL_MACHINE)
      suffix = ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe);

    // Delete Software\Classes\ChromeExt,
    base::string16 ext_prog_id(ShellUtil::kRegClasses);
    ext_prog_id.push_back(base::FilePath::kSeparators[0]);
    ext_prog_id.append(kChromeExtProgId);
    ext_prog_id.append(suffix);
    InstallUtil::DeleteRegistryKey(roots[i], ext_prog_id,
                                   WorkItem::kWow64Default);

    // Delete Software\Classes\.crx,
    base::string16 ext_association(ShellUtil::kRegClasses);
    ext_association.append(L"\\");
    ext_association.append(L".crx");
    InstallUtil::DeleteRegistryKey(roots[i], ext_association,
                                   WorkItem::kWow64Default);
  }
}

void UninstallFirewallRules(BrowserDistribution* dist,
                            const base::FilePath& chrome_exe) {
  scoped_ptr<FirewallManager> manager =
      FirewallManager::Create(dist, chrome_exe);
  if (manager)
    manager->RemoveFirewallRules();
}

InstallStatus UninstallProduct(const InstallationState& original_state,
                               const InstallerState& installer_state,
                               const base::FilePath& setup_exe,
                               const Product& product,
                               bool remove_all,
                               bool force_uninstall,
                               const CommandLine& cmd_line) {
  InstallStatus status = installer::UNINSTALL_CONFIRMED;
  BrowserDistribution* browser_dist = product.distribution();
  const base::string16 chrome_exe(
      installer_state.target_path().Append(installer::kChromeExe).value());

  bool is_chrome = product.is_chrome();

  VLOG(1) << "UninstallProduct: " << browser_dist->GetDisplayName();

  if (force_uninstall) {
    // Since --force-uninstall command line option is used, we are going to
    // do silent uninstall. Try to close all running Chrome instances.
    // NOTE: We don't do this for Chrome Frame.
    if (is_chrome)
      CloseAllChromeProcesses();
  } else if (is_chrome) {
    // no --force-uninstall so lets show some UI dialog boxes.
    status = IsChromeActiveOrUserCancelled(installer_state, product);
    if (status != installer::UNINSTALL_CONFIRMED &&
        status != installer::UNINSTALL_DELETE_PROFILE)
      return status;

    const base::string16 suffix(
        ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe));

    // Check if we need admin rights to cleanup HKLM (the conditions for
    // requiring a cleanup are the same as the conditions to do the actual
    // cleanup where DeleteChromeRegistrationKeys() is invoked for
    // HKEY_LOCAL_MACHINE below). If we do, try to launch another uninstaller
    // (silent) in elevated mode to do HKLM cleanup.
    // And continue uninstalling in the current process also to do HKCU cleanup.
    if (remove_all &&
        ShellUtil::QuickIsChromeRegisteredInHKLM(
            browser_dist, chrome_exe, suffix) &&
        !::IsUserAnAdmin() &&
        base::win::GetVersion() >= base::win::VERSION_VISTA &&
        !cmd_line.HasSwitch(installer::switches::kRunAsAdmin)) {
      CommandLine new_cmd(CommandLine::NO_PROGRAM);
      new_cmd.AppendArguments(cmd_line, true);
      // Append --run-as-admin flag to let the new instance of setup.exe know
      // that we already tried to launch ourselves as admin.
      new_cmd.AppendSwitch(installer::switches::kRunAsAdmin);
      // Append --remove-chrome-registration to remove registry keys only.
      new_cmd.AppendSwitch(installer::switches::kRemoveChromeRegistration);
      if (!suffix.empty()) {
        new_cmd.AppendSwitchNative(
            installer::switches::kRegisterChromeBrowserSuffix, suffix);
      }
      DWORD exit_code = installer::UNKNOWN_STATUS;
      InstallUtil::ExecuteExeAsAdmin(new_cmd, &exit_code);
    }
  }

  if (is_chrome) {
    // Chrome is not in use so lets uninstall Chrome by deleting various files
    // and registry entries. Here we will just make best effort and keep going
    // in case of errors.
    ClearRlzProductState();
    // Delete the key that delegate_execute might make.
    if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
      InstallUtil::DeleteRegistryKey(HKEY_CURRENT_USER,
                                     chrome::kMetroRegistryPath,
                                     WorkItem::kWow64Default);
    }

    auto_launch_util::DisableAllAutoStartFeatures(
        base::ASCIIToUTF16(chrome::kInitialProfile));

    // If user-level chrome is self-destructing as a result of encountering a
    // system-level chrome, retarget owned non-default shortcuts (app shortcuts,
    // profile shortcuts, etc.) to the system-level chrome.
    if (cmd_line.HasSwitch(installer::switches::kSelfDestruct) &&
        !installer_state.system_install()) {
      const base::FilePath system_chrome_path(
          GetChromeInstallPath(true, browser_dist).
              Append(installer::kChromeExe));
      VLOG(1) << "Retargeting user-generated Chrome shortcuts.";
      if (base::PathExists(system_chrome_path)) {
        RetargetUserShortcutsWithArgs(installer_state, product,
                                      base::FilePath(chrome_exe),
                                      system_chrome_path);
      } else {
        LOG(ERROR) << "Retarget failed: system-level Chrome not found.";
      }
    }

    DeleteShortcuts(installer_state, product, base::FilePath(chrome_exe));
  }

  // Delete the registry keys (Uninstall key and Version key).
  HKEY reg_root = installer_state.root_key();

  // Note that we must retrieve the distribution-specific data before deleting
  // product.GetVersionKey().
  base::string16 distribution_data(browser_dist->GetDistributionData(reg_root));

  // Remove Control Panel uninstall link.
  if (product.ShouldCreateUninstallEntry()) {
    InstallUtil::DeleteRegistryKey(
        reg_root, browser_dist->GetUninstallRegPath(), KEY_WOW64_32KEY);
  }

  // Remove Omaha product key.
  InstallUtil::DeleteRegistryKey(
      reg_root, browser_dist->GetVersionKey(), KEY_WOW64_32KEY);

  // Also try to delete the MSI value in the ClientState key (it might not be
  // there). This is due to a Google Update behaviour where an uninstall and a
  // rapid reinstall might result in stale values from the old ClientState key
  // being picked up on reinstall.
  product.SetMsiMarker(installer_state.system_install(), false);

  InstallStatus ret = installer::UNKNOWN_STATUS;

  if (is_chrome) {
    const base::string16 suffix(
        ShellUtil::GetCurrentInstallationSuffix(browser_dist, chrome_exe));

    // Remove all Chrome registration keys.
    // Registration data is put in HKCU for both system level and user level
    // installs.
    DeleteChromeRegistrationKeys(installer_state, browser_dist,
                                 HKEY_CURRENT_USER, suffix, &ret);

    // If the user's Chrome is registered with a suffix: it is possible that old
    // unsuffixed registrations were left in HKCU (e.g. if this install was
    // previously installed with no suffix in HKCU (old suffix rules if the user
    // is not an admin (or declined UAC at first run)) and later had to be
    // suffixed when fully registered in HKLM (e.g. when later making Chrome
    // default through the UI)).
    // Remove remaining HKCU entries with no suffix if any.
    if (!suffix.empty()) {
      DeleteChromeRegistrationKeys(installer_state, browser_dist,
                                   HKEY_CURRENT_USER, base::string16(), &ret);

      // For similar reasons it is possible in very few installs (from
      // 21.0.1180.0 and fixed shortly after) to be installed with the new-style
      // suffix, but have some old-style suffix registrations left behind.
      base::string16 old_style_suffix;
      if (ShellUtil::GetOldUserSpecificRegistrySuffix(&old_style_suffix) &&
          suffix != old_style_suffix) {
        DeleteChromeRegistrationKeys(installer_state, browser_dist,
                                     HKEY_CURRENT_USER, old_style_suffix, &ret);
      }
    }

    // Chrome is registered in HKLM for all system-level installs and for
    // user-level installs for which Chrome has been made the default browser.
    // Always remove the HKLM registration for system-level installs.  For
    // user-level installs, only remove it if both: 1) this uninstall isn't a
    // self destruct following the installation of a system-level Chrome
    // (because the system-level Chrome owns the HKLM registration now), and 2)
    // this user has made Chrome their default browser (i.e. has shell
    // integration entries registered with |suffix| (note: |suffix| will be the
    // empty string if required as it is obtained by
    // GetCurrentInstallationSuffix() above)).
    // TODO(gab): This can still leave parts of a suffixed install behind. To be
    // able to remove them we would need to be able to remove only suffixed
    // entries (as it is now some of the registry entries (e.g. App Paths) are
    // unsuffixed; thus removing suffixed installs is prohibited in HKLM if
    // !|remove_all| for now).
    if (installer_state.system_install() ||
        (remove_all &&
         ShellUtil::QuickIsChromeRegisteredInHKLM(
             browser_dist, chrome_exe, suffix))) {
      DeleteChromeRegistrationKeys(installer_state, browser_dist,
                                   HKEY_LOCAL_MACHINE, suffix, &ret);
    }

    ProcessDelegateExecuteWorkItems(installer_state, product);

    ProcessOnOsUpgradeWorkItems(installer_state, product);

    UninstallActiveSetupEntries(installer_state, product);

    UninstallFirewallRules(browser_dist, base::FilePath(chrome_exe));

    // Notify the shell that associations have changed since Chrome was likely
    // unregistered.
    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);

    // TODO(huangs): Implement actual migration code and remove the hack below.
    // Remove the "shadow" App Launcher registry keys.
    if (installer_state.is_multi_install()) {
      // If we're not uninstalling the legacy App Launcher, and if it was
      // not installed in the first place, then delete the "shadow" keys.
      chrome_launcher_support::InstallationState level_to_check =
          installer_state.system_install() ?
              chrome_launcher_support::INSTALLED_AT_SYSTEM_LEVEL :
              chrome_launcher_support::INSTALLED_AT_USER_LEVEL;
      bool has_legacy_app_launcher = level_to_check ==
          chrome_launcher_support::GetAppLauncherInstallationState();
      if (!has_legacy_app_launcher) {
        BrowserDistribution* shadow_app_launcher_dist =
            BrowserDistribution::GetSpecificDistribution(
                BrowserDistribution::CHROME_APP_HOST);
        InstallUtil::DeleteRegistryKey(
            reg_root,
            shadow_app_launcher_dist->GetVersionKey(),
            KEY_WOW64_32KEY);
      }
    }
  }

  if (installer_state.is_multi_install())
    ProcessGoogleUpdateItems(original_state, installer_state, product);

  // Get the state of the installed product (if any)
  const ProductState* product_state =
      original_state.GetProductState(installer_state.system_install(),
                                     browser_dist->GetType());

  // Delete shared registry keys as well (these require admin rights) if
  // remove_all option is specified.
  if (remove_all) {
    if (!InstallUtil::IsChromeSxSProcess() && is_chrome) {
      // Delete media player registry key that exists only in HKLM.
      // We don't delete this key in SxS uninstall or Chrome Frame uninstall
      // as we never set the key for those products.
      base::string16 reg_path(installer::kMediaPlayerRegPath);
      reg_path.push_back(base::FilePath::kSeparators[0]);
      reg_path.append(installer::kChromeExe);
      InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path,
                                     WorkItem::kWow64Default);
    }

    // Unregister any dll servers that we may have registered for this
    // product.
    if (product_state != NULL) {
      std::vector<base::FilePath> com_dll_list;
      product.AddComDllList(&com_dll_list);
      base::FilePath dll_folder = installer_state.target_path().AppendASCII(
          product_state->version().GetString());

      scoped_ptr<WorkItemList> unreg_work_item_list(
          WorkItem::CreateWorkItemList());

      AddRegisterComDllWorkItems(dll_folder,
                                 com_dll_list,
                                 installer_state.system_install(),
                                 false,  // Unregister
                                 true,   // May fail
                                 unreg_work_item_list.get());
      unreg_work_item_list->Do();
    }

    if (product.is_chrome_frame())
      ProcessIELowRightsPolicyWorkItems(installer_state);
  }

  // Close any Chrome Frame helper processes that may be running.
  if (product.is_chrome_frame()) {
    VLOG(1) << "Closing the Chrome Frame helper process";
    CloseChromeFrameHelperProcess();
  }

  if (product_state == NULL)
    return installer::UNINSTALL_SUCCESSFUL;

  // Finally delete all the files from Chrome folder after moving setup.exe
  // and the user's Local State to a temp location.
  bool delete_profile = ShouldDeleteProfile(installer_state, cmd_line, status,
                                            product);
  ret = installer::UNINSTALL_SUCCESSFUL;

  // When deleting files, we must make sure that we're either a "single"
  // (aka non-multi) installation or we are the Chrome Binaries.

  base::FilePath user_data_dir(GetUserDataDir(product));
  base::FilePath backup_state_file;
  if (!user_data_dir.empty()) {
    backup_state_file = BackupLocalStateFile(user_data_dir);
  } else {
    LOG(ERROR) << "Could not retrieve the user's profile directory.";
    ret = installer::UNINSTALL_FAILED;
    delete_profile = false;
  }

  if (product.is_chrome_app_host()) {
    DeleteAppHostFilesAndFolders(installer_state, product_state->version());
  } else if (!installer_state.is_multi_install() ||
             product.is_chrome_binaries()) {
    DeleteResult delete_result = DeleteChromeFilesAndFolders(
        installer_state, base::MakeAbsoluteFilePath(setup_exe));
    if (delete_result == DELETE_FAILED) {
      ret = installer::UNINSTALL_FAILED;
    } else if (delete_result == DELETE_REQUIRES_REBOOT) {
      ret = installer::UNINSTALL_REQUIRES_REBOOT;
    }
  }

  if (delete_profile)
    DeleteUserDataDir(user_data_dir, product.is_chrome_frame());

  if (!force_uninstall) {
    VLOG(1) << "Uninstallation complete. Launching post-uninstall operations.";
    browser_dist->DoPostUninstallOperations(product_state->version(),
        backup_state_file, distribution_data);
  }

  // Try and delete the preserved local state once the post-install
  // operations are complete.
  if (!backup_state_file.empty())
    base::DeleteFile(backup_state_file, false);

  return ret;
}

void CleanUpInstallationDirectoryAfterUninstall(
    const InstallationState& original_state,
    const InstallerState& installer_state,
    const base::FilePath& setup_exe,
    InstallStatus* uninstall_status) {
  if (*uninstall_status != UNINSTALL_SUCCESSFUL &&
      *uninstall_status != UNINSTALL_REQUIRES_REBOOT) {
    return;
  }
  const base::FilePath target_path(installer_state.target_path());
  if (target_path.empty()) {
    LOG(ERROR) << "No installation destination path.";
    *uninstall_status = UNINSTALL_FAILED;
    return;
  }
  if (!target_path.IsParent(base::MakeAbsoluteFilePath(setup_exe))) {
    VLOG(1) << "setup.exe is not in target path. Skipping installer cleanup.";
    return;
  }
  base::FilePath install_directory(setup_exe.DirName());

  bool remove_setup = true;
  bool remove_archive = true;
  CheckShouldRemoveSetupAndArchive(original_state, installer_state,
                                   &remove_setup, &remove_archive);
  if (!remove_archive)
    return;

  if (remove_setup) {
    // In order to be able to remove the folder in which we're running, we
    // need to move setup.exe out of the install folder.
    // TODO(tommi): What if the temp folder is on a different volume?
    MoveSetupOutOfInstallFolder(installer_state, setup_exe);
  }

  // Remove files from "...\<product>\Application\<version>\Installer"
  if (!RemoveInstallerFiles(install_directory, remove_setup)) {
    *uninstall_status = UNINSTALL_FAILED;
    return;
  }

  if (!remove_setup)
    return;

  // Try to remove the empty directory hierarchy.

  // Delete "...\<product>\Application\<version>\Installer"
  if (DeleteEmptyDir(install_directory) != DELETE_SUCCEEDED) {
    *uninstall_status = UNINSTALL_FAILED;
    return;
  }

  // Delete "...\<product>\Application\<version>"
  DeleteResult delete_result = DeleteEmptyDir(install_directory.DirName());
  if (delete_result == DELETE_FAILED ||
      (delete_result == DELETE_NOT_EMPTY &&
       *uninstall_status != UNINSTALL_REQUIRES_REBOOT)) {
    *uninstall_status = UNINSTALL_FAILED;
    return;
  }

  if (*uninstall_status == UNINSTALL_REQUIRES_REBOOT) {
    // Delete the Application directory at reboot if empty.
    ScheduleFileSystemEntityForDeletion(target_path);

    // If we need a reboot to continue, schedule the parent directories for
    // deletion unconditionally. If they are not empty, the session manager
    // will not delete them on reboot.
    ScheduleParentAndGrandparentForDeletion(target_path);
  } else if (DeleteChromeDirectoriesIfEmpty(target_path) == DELETE_FAILED) {
    *uninstall_status = UNINSTALL_FAILED;
  }
}

}  // namespace installer
