// 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/component_updater/cros_component_installer_chromeos.h"

#include <map>
#include <utility>

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/component_updater/component_installer_errors.h"
#include "chrome/browser/component_updater/metadata_table_chromeos.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/image_loader_client.h"
#include "components/component_updater/component_updater_paths.h"
#include "components/crx_file/id_util.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/sha2.h"

namespace component_updater {

namespace {

// Root path where all components are stored.
constexpr char kComponentsRootPath[] = "cros-components";

// All downloadable Chrome OS components.
const ComponentConfig kConfigs[] = {
    {"epson-inkjet-printer-escpr", "3.0",
     "1913a5e0a6cad30b6f03e176177e0d7ed62c5d6700a9c66da556d7c3f5d6a47e"},
    {"cros-termina", "750.1",
     "e9d960f84f628e1f42d05de4046bb5b3154b6f1f65c08412c6af57a29aecaffb"},
    {"rtanalytics-light", "10.0",
     "69f09d33c439c2ab55bbbe24b47ab55cb3f6c0bd1f1ef46eefea3216ec925038"},
    {"rtanalytics-full", "10.0",
     "c93c3e1013c52100a20038b405ac854d69fa889f6dc4fa6f188267051e05e444"},
    {"star-cups-driver", "1.1",
     "6d24de30f671da5aee6d463d9e446cafe9ddac672800a9defe86877dcde6c466"},
    {"cros-cellular", "1.0",
     "5714811c04f0a63aac96b39096faa759ace4c04e9b68291e7c9716128f5a2722"},
    {"demo-mode-resources", "1.0",
     "93c093ebac788581389015e9c59c5af111d2fa5174d206eb795042e6376cbd10"},
};

const ComponentConfig* FindConfig(const std::string& name) {
  const ComponentConfig* config = std::find_if(
      std::begin(kConfigs), std::end(kConfigs),
      [&name](const ComponentConfig& config) { return config.name == name; });
  if (config == std::end(kConfigs))
    return nullptr;
  return config;
}

// TODO(xiaochu): add metrics for component usage (https://crbug.com/793052).
void LogCustomUninstall(base::Optional<bool> result) {}

std::string GenerateId(const std::string& sha2hashstr) {
  // kIdSize is the count of a pair of hex in the sha2hash array.
  // In string representation of sha2hash, size is doubled since each hex is
  // represented by a single char.
  return crx_file::id_util::GenerateIdFromHex(
      sha2hashstr.substr(0, crx_file::id_util::kIdSize * 2));
}

void CleanUpOldInstalls(const std::string& name) {
  // Clean up components installed at old path.
  base::FilePath path;
  if (!base::PathService::Get(DIR_COMPONENT_USER, &path))
    return;
  path = path.Append(name);
  if (base::PathExists(path))
    base::DeleteFile(path, true);
}

// Returns all installed components.
std::vector<ComponentConfig> GetInstalled() {
  std::vector<ComponentConfig> configs;
  base::FilePath root;
  if (!base::PathService::Get(DIR_COMPONENT_USER, &root))
    return configs;

  root = root.Append(kComponentsRootPath);
  for (const ComponentConfig& config : kConfigs) {
    base::FilePath component_path = root.Append(config.name);
    if (base::PathExists(component_path))
      configs.push_back(config);
  }
  return configs;
}

// Report Error code.
CrOSComponentManager::Error ReportError(CrOSComponentManager::Error error) {
  UMA_HISTOGRAM_ENUMERATION("ComponentUpdater.ChromeOS.InstallResult", error,
                            CrOSComponentManager::Error::ERROR_MAX);
  return error;
}

}  // namespace

CrOSComponentInstallerPolicy::CrOSComponentInstallerPolicy(
    const ComponentConfig& config,
    CrOSComponentInstaller* cros_component_installer)
    : cros_component_installer_(cros_component_installer),
      name_(config.name),
      env_version_(config.env_version) {
  if (strlen(config.sha2hash) != crypto::kSHA256Length * 2)
    return;

  bool converted = base::HexStringToBytes(config.sha2hash, &sha2_hash_);
  DCHECK(converted);
  DCHECK_EQ(crypto::kSHA256Length, sha2_hash_.size());
}

CrOSComponentInstallerPolicy::~CrOSComponentInstallerPolicy() = default;

bool CrOSComponentInstallerPolicy::SupportsGroupPolicyEnabledComponentUpdates()
    const {
  return true;
}

bool CrOSComponentInstallerPolicy::RequiresNetworkEncryption() const {
  return true;
}

update_client::CrxInstaller::Result
CrOSComponentInstallerPolicy::OnCustomInstall(
    const base::DictionaryValue& manifest,
    const base::FilePath& install_dir) {
  // TODO(xiaochu): remove after M66 ships to stable. https://crbug.com/792203
  CleanUpOldInstalls(name_);

  cros_component_installer_->EmitInstalledSignal(GetName());

  return update_client::CrxInstaller::Result(update_client::InstallError::NONE);
}

void CrOSComponentInstallerPolicy::OnCustomUninstall() {
  cros_component_installer_->UnregisterCompatiblePath(name_);

  chromeos::DBusThreadManager::Get()->GetImageLoaderClient()->UnmountComponent(
      name_, base::BindOnce(&LogCustomUninstall));
}

void CrOSComponentInstallerPolicy::ComponentReady(
    const base::Version& version,
    const base::FilePath& path,
    std::unique_ptr<base::DictionaryValue> manifest) {
  std::string min_env_version;
  if (!manifest || !manifest->GetString("min_env_version", &min_env_version))
    return;

  if (!IsCompatible(env_version_, min_env_version))
    return;

  cros_component_installer_->RegisterCompatiblePath(GetName(), path);
}

bool CrOSComponentInstallerPolicy::VerifyInstallation(
    const base::DictionaryValue& manifest,
    const base::FilePath& install_dir) const {
  return true;
}

base::FilePath CrOSComponentInstallerPolicy::GetRelativeInstallDir() const {
  base::FilePath path = base::FilePath(kComponentsRootPath);
  return path.Append(name_);
}

void CrOSComponentInstallerPolicy::GetHash(std::vector<uint8_t>* hash) const {
  *hash = sha2_hash_;
}

std::string CrOSComponentInstallerPolicy::GetName() const {
  return name_;
}

update_client::InstallerAttributes
CrOSComponentInstallerPolicy::GetInstallerAttributes() const {
  update_client::InstallerAttributes attrs;
  attrs["_env_version"] = env_version_;
  return attrs;
}

std::vector<std::string> CrOSComponentInstallerPolicy::GetMimeTypes() const {
  std::vector<std::string> mime_types;
  return mime_types;
}

bool CrOSComponentInstallerPolicy::IsCompatible(
    const std::string& env_version_str,
    const std::string& min_env_version_str) {
  base::Version env_version(env_version_str);
  base::Version min_env_version(min_env_version_str);
  return env_version.IsValid() && min_env_version.IsValid() &&
         env_version.components()[0] == min_env_version.components()[0] &&
         env_version >= min_env_version;
}

CrOSComponentInstaller::CrOSComponentInstaller(
    std::unique_ptr<MetadataTable> metadata_table,
    ComponentUpdateService* component_updater)
    : metadata_table_(std::move(metadata_table)),
      component_updater_(component_updater) {}

CrOSComponentInstaller::~CrOSComponentInstaller() {}

void CrOSComponentInstaller::SetDelegate(Delegate* delegate) {
  delegate_ = delegate;
}

void CrOSComponentInstaller::Load(const std::string& name,
                                  MountPolicy mount_policy,
                                  UpdatePolicy update_policy,
                                  LoadCallback load_callback) {
  if (!IsCompatible(name) || update_policy == UpdatePolicy::kForce) {
    // A compatible component is not installed, or forced update is requested.
    // Start registration and installation/update process.
    Install(name, update_policy, mount_policy, std::move(load_callback));
  } else if (mount_policy == MountPolicy::kMount) {
    // A compatible component is installed, load it.
    LoadInternal(name, std::move(load_callback));
  } else {
    // A compatible component is installed, do not load it.
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(load_callback),
                                  ReportError(Error::NONE), base::FilePath()));
  }
}

bool CrOSComponentInstaller::Unload(const std::string& name) {
  const ComponentConfig* config = FindConfig(name);
  if (!config) {
    // Component |name| does not exist.
    return false;
  }
  const std::string id = GenerateId(config->sha2hash);
  metadata_table_->DeleteComponentForCurrentUser(name);
  return metadata_table_->HasComponentForAnyUser(name) ||
         component_updater_->UnregisterComponent(id);
}

void CrOSComponentInstaller::RegisterInstalled() {
  base::PostTaskWithTraitsAndReplyWithResult(
      FROM_HERE, {base::MayBlock()}, base::BindOnce(GetInstalled),
      base::BindOnce(&CrOSComponentInstaller::RegisterN,
                     base::Unretained(this)));
}

void CrOSComponentInstaller::RegisterCompatiblePath(
    const std::string& name,
    const base::FilePath& path) {
  compatible_components_[name] = path;
}

void CrOSComponentInstaller::UnregisterCompatiblePath(const std::string& name) {
  compatible_components_.erase(name);
}

base::FilePath CrOSComponentInstaller::GetCompatiblePath(
    const std::string& name) const {
  const auto it = compatible_components_.find(name);
  return it == compatible_components_.end() ? base::FilePath() : it->second;
}

void CrOSComponentInstaller::EmitInstalledSignal(const std::string& component) {
  if (delegate_)
    delegate_->EmitInstalledSignal(component);
}

bool CrOSComponentInstaller::IsRegistered(const std::string& name) const {
  base::FilePath root;
  if (!base::PathService::Get(DIR_COMPONENT_USER, &root))
    return false;

  return base::PathExists(root.Append(kComponentsRootPath).Append(name));
}

void CrOSComponentInstaller::Register(const ComponentConfig& config,
                                      base::OnceClosure register_callback) {
  auto installer = base::MakeRefCounted<ComponentInstaller>(
      std::make_unique<CrOSComponentInstallerPolicy>(config, this));
  installer->Register(component_updater_, std::move(register_callback));
}

void CrOSComponentInstaller::Install(const std::string& name,
                                     UpdatePolicy update_policy,
                                     MountPolicy mount_policy,
                                     LoadCallback load_callback) {
  const ComponentConfig* config = FindConfig(name);
  if (!config) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(load_callback),
                                  ReportError(Error::UNKNOWN_COMPONENT),
                                  base::FilePath()));
    return;
  }

  Register(*config,
           base::BindOnce(
               &CrOSComponentInstaller::StartInstall, base::Unretained(this),
               name, GenerateId(config->sha2hash), update_policy,
               base::BindOnce(&CrOSComponentInstaller::FinishInstall,
                              base::Unretained(this), name, mount_policy,
                              update_policy, std::move(load_callback))));
}

void CrOSComponentInstaller::StartInstall(
    const std::string& name,
    const std::string& id,
    UpdatePolicy update_policy,
    update_client::Callback install_callback) {
  // Check whether an installed component was found during registration, and
  // determine whether OnDemandUpdater should be started accordingly.
  const bool is_compatible = IsCompatible(name);
  if (update_policy == UpdatePolicy::kSkip ||
      (is_compatible && update_policy != UpdatePolicy::kForce)) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(install_callback),
                                  update_client::Error::NONE));
    return;
  }

  const component_updater::OnDemandUpdater::Priority priority =
      is_compatible ? component_updater::OnDemandUpdater::Priority::BACKGROUND
                    : component_updater::OnDemandUpdater::Priority::FOREGROUND;
  component_updater_->GetOnDemandUpdater().OnDemandUpdate(
      id, priority, std::move(install_callback));
}

void CrOSComponentInstaller::FinishInstall(const std::string& name,
                                           MountPolicy mount_policy,
                                           UpdatePolicy update_policy,
                                           LoadCallback load_callback,
                                           update_client::Error error) {
  if (error != update_client::Error::NONE) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(load_callback),
                       ReportError(Error::INSTALL_FAILURE), base::FilePath()));
  } else if (!IsCompatible(name)) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(load_callback),
                       ReportError(update_policy == UpdatePolicy::kSkip
                                       ? Error::NOT_FOUND
                                       : Error::COMPATIBILITY_CHECK_FAILED),
                       base::FilePath()));
  } else if (mount_policy == MountPolicy::kMount) {
    LoadInternal(name, std::move(load_callback));
  } else {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(load_callback),
                                  ReportError(Error::NONE), base::FilePath()));
  }
}

void CrOSComponentInstaller::LoadInternal(const std::string& name,
                                          LoadCallback load_callback) {
  const base::FilePath path = GetCompatiblePath(name);
  DCHECK(!path.empty());
  chromeos::DBusThreadManager::Get()
      ->GetImageLoaderClient()
      ->LoadComponentAtPath(
          name, path,
          base::BindOnce(&CrOSComponentInstaller::FinishLoad,
                         base::Unretained(this), std::move(load_callback),
                         base::TimeTicks::Now(), name));
}

void CrOSComponentInstaller::FinishLoad(LoadCallback load_callback,
                                        const base::TimeTicks start_time,
                                        const std::string& name,
                                        base::Optional<base::FilePath> result) {
  // Report component image mount time.
  UMA_HISTOGRAM_LONG_TIMES("ComponentUpdater.ChromeOS.MountTime",
                           base::TimeTicks::Now() - start_time);
  if (!result.has_value()) {
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(load_callback),
                       ReportError(Error::MOUNT_FAILURE), base::FilePath()));
  } else {
    metadata_table_->AddComponentForCurrentUser(name);
    base::ThreadTaskRunnerHandle::Get()->PostTask(
        FROM_HERE, base::BindOnce(std::move(load_callback),
                                  ReportError(Error::NONE), result.value()));
  }
}

void CrOSComponentInstaller::RegisterN(
    const std::vector<ComponentConfig>& configs) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  for (const auto& config : configs) {
    Register(config, base::OnceClosure());
  }
}

bool CrOSComponentInstaller::IsCompatible(const std::string& name) const {
  return compatible_components_.count(name) > 0;
}

}  // namespace component_updater
