// Copyright 2017 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.

#include "chrome/browser/conflicts/installed_applications_win.h"

#include <algorithm>

#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/win/registry.h"
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "chrome/browser/conflicts/msi_util_win.h"

namespace {

// Returns true if |candidate| is registered as a system component.
bool IsSystemComponent(const base::win::RegKey& candidate) {
  DWORD system_component = 0;
  return candidate.ReadValueDW(L"SystemComponent", &system_component) ==
             ERROR_SUCCESS &&
         system_component == 1;
}

// Fetches a string |value| out of |key|. Return false if a non-empty value
// could not be retrieved.
bool GetValue(const base::win::RegKey& key,
              const wchar_t* value,
              base::string16* result) {
  return key.ReadValue(value, result) == ERROR_SUCCESS && !result->empty();
}

// Try to get the |install_path| from |candidate| using the InstallLocation
// value. Return true on success.
bool GetInstallPathUsingInstallLocation(const base::win::RegKey& candidate,
                                        base::FilePath* install_path) {
  base::string16 install_location;
  if (GetValue(candidate, L"InstallLocation", &install_location)) {
    *install_path = base::FilePath(std::move(install_location));
    return true;
  }
  return false;
}

// Returns true if the |component_path| points to a registry key. Registry key
// paths are characterized by a number instead of a drive letter.
// See the documentation for ::MsiGetComponentPath():
// https://msdn.microsoft.com/library/windows/desktop/aa370112.aspx
bool IsRegistryComponentPath(const base::string16& component_path) {
  base::string16 drive_letter =
      component_path.substr(0, component_path.find(':'));

  for (const wchar_t* registry_drive_letter :
       {L"00", L"01", L"02", L"03", L"20", L"21", L"22", L"23"}) {
    if (drive_letter == registry_drive_letter)
      return true;
  }

  return false;
}

// Returns all the files installed by the product identified by |product_guid|.
// Returns true on success.
bool GetInstalledFilesUsingMsiGuid(
    const base::string16& product_guid,
    const MsiUtil& msi_util,
    const base::string16& user_sid,
    std::vector<base::FilePath>* installed_files) {
  // An invalid product guid may have been passed to this function. In this
  // case, GetMsiComponentPaths() will return false so it is not necessary to
  // specifically filter those out.
  std::vector<base::string16> component_paths;
  if (!msi_util.GetMsiComponentPaths(product_guid, user_sid, &component_paths))
    return false;

  for (auto& component_path : component_paths) {
    // Exclude registry component paths.
    if (IsRegistryComponentPath(component_path))
      continue;

    installed_files->push_back(base::FilePath(std::move(component_path)));
  }

  return true;
}

// Helper function to sort |container| using CompareLessIgnoreCase.
void SortByFilePaths(
    std::vector<std::pair<base::FilePath, size_t>>* container) {
  std::sort(container->begin(), container->end(),
            [](const auto& lhs, const auto& rhs) {
              return base::FilePath::CompareLessIgnoreCase(lhs.first.value(),
                                                           rhs.first.value());
            });
}

}  // namespace

InstalledApplications::InstalledApplications()
    : InstalledApplications(std::make_unique<MsiUtil>()) {}

InstalledApplications::~InstalledApplications() = default;

bool InstalledApplications::GetInstalledApplications(
    const base::FilePath& file,
    std::vector<ApplicationInfo>* applications) const {
  // First, check if an exact file match exists in the installed files list.
  if (GetApplicationsFromInstalledFiles(file, applications))
    return true;

  // Then try to find a parent directory in the install directories list.
  return GetApplicationsFromInstallDirectories(file, applications);
}

InstalledApplications::InstalledApplications(
    std::unique_ptr<MsiUtil> msi_util) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);

  SCOPED_UMA_HISTOGRAM_TIMER(
      "ThirdPartyModules.InstalledApplications.GetDataTime");

  // Iterate over all the variants of the uninstall registry key.
  static constexpr wchar_t kUninstallKeyPath[] =
      L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";

  std::vector<std::pair<HKEY, REGSAM>> registry_key_combinations;
  if (base::win::OSInfo::GetArchitecture() ==
      base::win::OSInfo::X86_ARCHITECTURE) {
    // On 32-bit Windows, there is only one view of the registry.
    registry_key_combinations.emplace_back(HKEY_CURRENT_USER, 0);
    registry_key_combinations.emplace_back(HKEY_LOCAL_MACHINE, 0);
  } else {
    // On 64-bit Windows, there also exists a 32-bit view (Wow6432Node). Except
    // that the "HKCU\SOFTWARE\" subtree is shared between the 32-bits and
    // 64 bits views. Accessing both would create duplicate entries.
    // See https://msdn.microsoft.com/library/windows/desktop/aa384253.aspx
    registry_key_combinations.emplace_back(HKEY_CURRENT_USER, 0);
    registry_key_combinations.emplace_back(HKEY_LOCAL_MACHINE, KEY_WOW64_32KEY);
    registry_key_combinations.emplace_back(HKEY_LOCAL_MACHINE, KEY_WOW64_64KEY);
  }

  // Retrieve the current user's Security Identifier. If it fails, |user_sid|
  // will stay empty.
  base::string16 user_sid;
  bool got_user_sid_string = base::win::GetUserSidString(&user_sid);
  UMA_HISTOGRAM_BOOLEAN(
      "ThirdPartyModules.InstalledApplications.GotUserSidString",
      got_user_sid_string);

  for (const auto& combination : registry_key_combinations) {
    for (base::win::RegistryKeyIterator i(combination.first, kUninstallKeyPath,
                                          combination.second);
         i.Valid(); ++i) {
      CheckRegistryKeyForInstalledApplication(
          combination.first, kUninstallKeyPath, combination.second, i.Name(),
          *msi_util, user_sid);
    }
  }

  // The vectors are sorted so that binary searching can be used. No additional
  // entries will be added anyways.
  SortByFilePaths(&installed_files_);
  SortByFilePaths(&install_directories_);
}

void InstalledApplications::CheckRegistryKeyForInstalledApplication(
    HKEY hkey,
    const base::string16& key_path,
    REGSAM wow64access,
    const base::string16& key_name,
    const MsiUtil& msi_util,
    const base::string16& user_sid) {
  base::string16 candidate_key_path =
      base::StringPrintf(L"%ls\\%ls", key_path.c_str(), key_name.c_str());
  base::win::RegKey candidate(hkey, candidate_key_path.c_str(),
                              KEY_QUERY_VALUE | wow64access);

  if (!candidate.Valid())
    return;

  // System components are not displayed in the Add or remove applications list.
  if (IsSystemComponent(candidate))
    return;

  // If there is no UninstallString, the Uninstall button is grayed out.
  base::string16 uninstall_string;
  if (!GetValue(candidate, L"UninstallString", &uninstall_string))
    return;

  // Ignore Microsoft applications.
  base::string16 publisher;
  if (GetValue(candidate, L"Publisher", &publisher) &&
      base::StartsWith(publisher, L"Microsoft", base::CompareCase::SENSITIVE)) {
    return;
  }

  // Because this class is used to display a warning to the user, not having
  // a display name renders the warning somewhat useless. Ignore those
  // candidates.
  base::string16 display_name;
  if (!GetValue(candidate, L"DisplayName", &display_name))
    return;

  base::FilePath install_path;
  if (GetInstallPathUsingInstallLocation(candidate, &install_path)) {
    applications_.push_back({std::move(display_name), hkey,
                             std::move(candidate_key_path), wow64access});

    const size_t application_index = applications_.size() - 1;
    install_directories_.emplace_back(std::move(install_path),
                                      application_index);
    return;
  }

  std::vector<base::FilePath> installed_files;
  if (GetInstalledFilesUsingMsiGuid(key_name, msi_util, user_sid,
                                    &installed_files)) {
    applications_.push_back({std::move(display_name), hkey,
                             std::move(candidate_key_path), wow64access});

    const size_t application_index = applications_.size() - 1;
    for (auto& installed_file : installed_files) {
      installed_files_.emplace_back(std::move(installed_file),
                                    application_index);
    }
  }
}

bool InstalledApplications::GetApplicationsFromInstalledFiles(
    const base::FilePath& file,
    std::vector<ApplicationInfo>* applications) const {
  // This functor is used to find all exact items by their key in a collection
  // of key/value pairs.
  struct FilePathLess {
    bool operator()(const std::pair<base::FilePath, size_t> element,
                    const base::FilePath& file) {
      return base::FilePath::CompareLessIgnoreCase(element.first.value(),
                                                   file.value());
    }
    bool operator()(const base::FilePath& file,
                    const std::pair<base::FilePath, size_t> element) {
      return base::FilePath::CompareLessIgnoreCase(file.value(),
                                                   element.first.value());
    }
  };

  auto equal_range = std::equal_range(
      installed_files_.begin(), installed_files_.end(), file, FilePathLess());

  auto nb_matches = std::distance(equal_range.first, equal_range.second);
  if (nb_matches == 0)
    return false;

  applications->reserve(applications->size() + nb_matches);
  for (auto iter = equal_range.first; iter != equal_range.second; ++iter)
    applications->push_back(applications_[iter->second]);

  return true;
}

bool InstalledApplications::GetApplicationsFromInstallDirectories(
    const base::FilePath& file,
    std::vector<ApplicationInfo>* applications) const {
  // This functor is used to find all matching items by their key in a
  // collection of key/value pairs. This also takes advantage of the fact that
  // only the first element of the pair is a directory.
  struct FilePathParentLess {
    bool operator()(const std::pair<base::FilePath, size_t> directory,
                    const base::FilePath& file) {
      if (directory.first.IsParent(file))
        return false;
      return base::FilePath::CompareLessIgnoreCase(directory.first.value(),
                                                   file.value());
    }
    bool operator()(const base::FilePath& file,
                    const std::pair<base::FilePath, size_t> directory) {
      if (directory.first.IsParent(file))
        return false;
      return base::FilePath::CompareLessIgnoreCase(file.value(),
                                                   directory.first.value());
    }
  };

  auto equal_range =
      std::equal_range(install_directories_.begin(), install_directories_.end(),
                       file, FilePathParentLess());

  // Skip cases where there are multiple matches because there is no way to know
  // which application is the real owner of the |file| with the information this
  // class possess.
  if (std::distance(equal_range.first, equal_range.second) != 1)
    return false;

  applications->push_back(applications_[equal_range.first->second]);
  return true;
}

bool operator<(const InstalledApplications::ApplicationInfo& lhs,
               const InstalledApplications::ApplicationInfo& rhs) {
  return std::tie(lhs.name, lhs.registry_root, lhs.registry_key_path,
                  lhs.registry_wow64_access) <
         std::tie(rhs.name, rhs.registry_root, rhs.registry_key_path,
                  rhs.registry_wow64_access);
}
