// Copyright 2018 The Chromium OS 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 "dlcservice/dlc_service_dbus_adaptor.h"

#include <algorithm>
#include <utility>
#include <vector>

#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/message_loop/message_loop.h>
#include <brillo/errors/error.h>
#include <brillo/errors/error_codes.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/dlcservice/dbus-constants.h>
#include <update_engine/dbus-constants.h>

#include "dlcservice/boot_slot.h"
#include "dlcservice/utils.h"

namespace dlcservice {

namespace {

// Permissions for DLC module directories.
constexpr mode_t kDlcModuleDirectoryPerms = 0755;

// Creates a directory with permissions required for DLC modules.
bool CreateDirWithDlcPermissions(const base::FilePath& path) {
  base::File::Error file_err;
  if (!base::CreateDirectoryAndGetError(path, &file_err)) {
    LOG(ERROR) << "Failed to create directory '" << path.value()
               << "': " << base::File::ErrorToString(file_err);
    return false;
  }
  if (!base::SetPosixFilePermissions(path, kDlcModuleDirectoryPerms)) {
    LOG(ERROR) << "Failed to set directory permissions for '" << path.value()
               << "'";
    return false;
  }
  return true;
}

// Creates a directory with an empty image file and resizes it to the given
// size.
bool CreateImageFile(const base::FilePath& path, int64_t image_size) {
  if (!CreateDirWithDlcPermissions(path.DirName())) {
    return false;
  }
  constexpr uint32_t file_flags =
      base::File::FLAG_CREATE | base::File::FLAG_READ | base::File::FLAG_WRITE;
  base::File file(path, file_flags);
  if (!file.IsValid()) {
    LOG(ERROR) << "Failed to create image file '" << path.value()
               << "': " << base::File::ErrorToString(file.error_details());
    return false;
  }
  if (!file.SetLength(image_size)) {
    LOG(ERROR) << "Failed to reserve backup file for DLC module image '"
               << path.value() << "'";
    return false;
  }
  return true;
}

// Sets the D-Bus error object and logs the error message.
void LogAndSetError(brillo::ErrorPtr* err, const std::string& msg) {
  if (err)
    *err = brillo::Error::Create(FROM_HERE, "dlcservice", "INTERNAL", msg);
  LOG(ERROR) << msg;
}

}  // namespace

DlcServiceDBusAdaptor::DlcServiceDBusAdaptor(
    std::unique_ptr<org::chromium::ImageLoaderInterfaceProxyInterface>
        image_loader_proxy,
    std::unique_ptr<org::chromium::UpdateEngineInterfaceProxyInterface>
        update_engine_proxy,
    std::unique_ptr<BootSlot> boot_slot,
    const base::FilePath& manifest_dir,
    const base::FilePath& content_dir)
    : org::chromium::DlcServiceInterfaceAdaptor(this),
      image_loader_proxy_(std::move(image_loader_proxy)),
      update_engine_proxy_(std::move(update_engine_proxy)),
      boot_slot_(std::move(boot_slot)),
      manifest_dir_(manifest_dir),
      content_dir_(content_dir),
      weak_ptr_factory_(this) {
  // Get current boot slot.
  std::string boot_disk_name;
  int num_slots = -1;
  int current_boot_slot = -1;
  if (!boot_slot_->GetCurrentSlot(&boot_disk_name, &num_slots,
                                  &current_boot_slot))
    LOG(FATAL) << "Can not get current boot slot.";

  current_boot_slot_name_ = current_boot_slot == 0 ? imageloader::kSlotNameA
                                                   : imageloader::kSlotNameB;

  // Register D-Bus signal callbacks.
  update_engine_proxy_->RegisterStatusUpdateSignalHandler(
      base::Bind(&DlcServiceDBusAdaptor::OnStatusUpdateSignal,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&DlcServiceDBusAdaptor::OnStatusUpdateSignalConnected,
                 weak_ptr_factory_.GetWeakPtr()));

  // Initalize installed DLC modules.
  installed_dlc_modules_ = utils::ScanDirectory(content_dir_);

  // Initialize supported DLC modules.
  supported_dlc_modules_ = utils::ScanDirectory(manifest_dir_);
}

DlcServiceDBusAdaptor::~DlcServiceDBusAdaptor() {}

void DlcServiceDBusAdaptor::LoadDlcModuleImages() {
  // Load all installed DLC modules.
  for (const auto& dlc_module_id : installed_dlc_modules_) {
    std::string package = ScanDlcModulePackage(dlc_module_id);
    auto dlc_module_content_path =
        utils::GetDlcModulePackagePath(content_dir_, dlc_module_id, package);

    // Mount the installed DLC image.
    std::string path;
    image_loader_proxy_->LoadDlcImage(dlc_module_id, package,
                                      current_boot_slot_name_, &path, nullptr);
    if (path.empty()) {
      LOG(ERROR) << "DLC image " << dlc_module_id << "/" << package
                 << " is corrupted.";
    } else {
      LOG(INFO) << "DLC image " << dlc_module_id << "/" << package
                << " is mounted at " << path;
    }
  }
}

bool DlcServiceDBusAdaptor::Install(brillo::ErrorPtr* err,
                                    const std::string& id_in,
                                    const std::string& omaha_url_in) {
  if (supported_dlc_modules_.find(id_in) == supported_dlc_modules_.end()) {
    LogAndSetError(err, "The DLC ID provided is not supported.");
    return false;
  }
  std::string package = ScanDlcModulePackage(id_in);

  // Create the DLC ID directory with correct permissions.
  base::FilePath module_path = utils::GetDlcModulePath(content_dir_, id_in);
  if (base::PathExists(module_path)) {
    LogAndSetError(err, "The DLC module is installed.");
    return false;
  }
  if (!CreateDirWithDlcPermissions(module_path)) {
    LogAndSetError(err, "Failed to create DLC ID directory.");
    return false;
  }

  // Create the DLC package directory with correct permissions.
  base::FilePath module_package_path =
      utils::GetDlcModulePackagePath(content_dir_, id_in, package);
  if (base::PathExists(module_package_path)) {
    LogAndSetError(err, "The DLC module is installed.");
    return false;
  }
  if (!CreateDirWithDlcPermissions(module_package_path)) {
    LogAndSetError(err, "Failed to create DLC Package directory.");
    return false;
  }

  // Creates DLC module storage.
  // TODO(xiaochu): Manifest currently returns a signed integer, which means
  // this will likely fail for modules >= 2 GiB in size.
  // https://crbug.com/904539
  imageloader::Manifest manifest;
  if (!dlcservice::utils::GetDlcManifest(manifest_dir_, id_in, package,
                                         &manifest)) {
    LogAndSetError(err, "Failed to get DLC module manifest.");
    return false;
  }
  int64_t image_size = manifest.preallocated_size();
  if (image_size <= 0) {
    LogAndSetError(err, "Preallocated size in manifest is illegal.");
    return false;
  }

  // Creates image A.
  base::FilePath image_a_path =
      utils::GetDlcModuleImagePath(content_dir_, id_in, package, 0);
  if (!CreateImageFile(image_a_path, image_size)) {
    LogAndSetError(err, "Failed to create slot A DLC image file");
    return false;
  }

  // Creates image B.
  base::FilePath image_b_path =
      utils::GetDlcModuleImagePath(content_dir_, id_in, package, 1);
  if (!CreateImageFile(image_b_path, image_size)) {
    LogAndSetError(err, "Failed to create slot B image file");
    return false;
  }

  if (!CheckForUpdateEngineStatus({update_engine::kUpdateStatusIdle})) {
    LogAndSetError(
        err, "Update Engine is performing operations or a reboot is pending.");
    return false;
  }

  // Invokes update_engine to install the DLC module.
  dlcservice::DlcModuleList dlc_parameters;
  dlc_parameters.set_omaha_url(omaha_url_in);
  dlcservice::DlcModuleInfo* dlc_info = dlc_parameters.add_dlc_module_infos();
  dlc_info->set_dlc_id(id_in);
  if (!update_engine_proxy_->AttemptInstall(dlc_parameters, nullptr)) {
    LogAndSetError(err, "Update Engine failed to schedule install operations.");
    return false;
  }

  dlc_id_being_installed_ = id_in;
  // Note: Do NOT add to installed indication. Let |OnStatusUpdateSignaled()|
  // handle since hat's truly when the DLC(s) are installed.

  return true;
}

bool DlcServiceDBusAdaptor::Uninstall(brillo::ErrorPtr* err,
                                      const std::string& id_in) {
  if (installed_dlc_modules_.find(id_in) == installed_dlc_modules_.end()) {
    LogAndSetError(err, "The DLC ID provided is not installed");
    return false;
  }
  std::string package = ScanDlcModulePackage(id_in);

  const base::FilePath dlc_module_content_path =
      utils::GetDlcModulePackagePath(content_dir_, id_in, package);
  if (!base::PathExists(dlc_module_content_path) ||
      !base::PathExists(
          utils::GetDlcModuleImagePath(content_dir_, id_in, package, 0)) ||
      !base::PathExists(
          utils::GetDlcModuleImagePath(content_dir_, id_in, package, 1))) {
    LogAndSetError(err, "The DLC module is not installed properly.");
    return false;
  }
  // Unmounts the DLC module image.
  bool success = false;
  if (!image_loader_proxy_->UnloadDlcImage(id_in, package, &success, nullptr)) {
    LogAndSetError(err, "Imageloader is not available.");
    return false;
  }
  if (!success) {
    LogAndSetError(err, "Imageloader UnloadDlcImage failed.");
    return false;
  }

  if (!CheckForUpdateEngineStatus(
          {update_engine::kUpdateStatusIdle,
           update_engine::kUpdateStatusUpdatedNeedReboot})) {
    LogAndSetError(err, "Update Engine is performing operations.");
    return false;
  }

  // Deletes the DLC module images.
  const base::FilePath dlc_module_path =
      utils::GetDlcModulePath(content_dir_, id_in);
  if (!base::DeleteFile(dlc_module_path, true)) {
    LogAndSetError(err, "DLC image folder could not be deleted.");
    return false;
  }

  LOG(INFO) << "Uninstalling DLC id:" << id_in;
  installed_dlc_modules_.erase(id_in);
  return true;
}

bool DlcServiceDBusAdaptor::GetInstalled(brillo::ErrorPtr* err,
                                         DlcModuleList* dlc_module_list_out) {
  const auto InsertIntoDlcModuleListOut =
      [dlc_module_list_out](const std::string& dlc_module_id) {
        DlcModuleInfo* dlc_module_info =
            dlc_module_list_out->add_dlc_module_infos();
        dlc_module_info->set_dlc_id(dlc_module_id);
      };
  for_each(begin(installed_dlc_modules_), end(installed_dlc_modules_),
           InsertIntoDlcModuleListOut);
  return true;
}

std::string DlcServiceDBusAdaptor::ScanDlcModulePackage(const std::string& id) {
  return *(utils::ScanDirectory(manifest_dir_.Append(id)).begin());
}

bool DlcServiceDBusAdaptor::CheckForUpdateEngineStatus(
    const std::vector<std::string>& status_list) {
  int64_t last_checked_time = 0;
  double progress = 0;
  std::string current_operation;
  std::string new_version;
  int64_t new_size = 0;
  if (!update_engine_proxy_->GetStatus(&last_checked_time, &progress,
                                       &current_operation, &new_version,
                                       &new_size, nullptr)) {
    LOG(ERROR) << "Update Engine is not available.";
    return false;
  }
  if (!std::any_of(status_list.begin(), status_list.end(),
                   [&current_operation](const std::string& status) {
                     return current_operation == status;
                   })) {
    return false;
  }
  return true;
}

void DlcServiceDBusAdaptor::SendOnInstalledSignal(
    const InstallResult& install_result) {
  org::chromium::DlcServiceInterfaceAdaptor::SendOnInstalledSignal(
      install_result);
}

void DlcServiceDBusAdaptor::OnStatusUpdateSignal(
    int64_t last_checked_time,
    double progress,
    const std::string& current_operation,
    const std::string& new_version,
    int64_t new_size) {
  // This signal is for DLC install only when have DLC modules being installed.
  if (dlc_id_being_installed_.empty())
    return;
  // Install is complete when we receive kUpdateStatusIdle signal.
  if (current_operation != update_engine::kUpdateStatusIdle)
    return;

  // At this point, update_engine finished installation of the requested DLC
  // module (failure or success).
  std::string dlc_id = dlc_id_being_installed_;
  dlc_id_being_installed_.clear();

  InstallResult install_result;
  install_result.set_success(false);
  install_result.set_dlc_id(dlc_id);

  std::string package = ScanDlcModulePackage(dlc_id);

  // Mount the installed DLC module image.
  std::string mount_point;
  if (!image_loader_proxy_->LoadDlcImage(
          dlc_id, package, current_boot_slot_name_, &mount_point, nullptr)) {
    LOG(ERROR) << "Imageloader is not available.";
    install_result.set_error_code(
        static_cast<int>(OnInstalledSignalErrorCode::kImageLoaderReturnsFalse));
    SendOnInstalledSignal(install_result);
    return;
  }
  if (mount_point.empty()) {
    LOG(ERROR) << "Imageloader LoadDlcImage failed.";
    install_result.set_error_code(
        static_cast<int>(OnInstalledSignalErrorCode::kMountFailure));
    SendOnInstalledSignal(install_result);
    return;
  }

  // Install was a success so keep track.
  installed_dlc_modules_.insert(dlc_id);

  install_result.set_success(true);
  install_result.set_error_code(
      static_cast<int>(OnInstalledSignalErrorCode::kNone));
  install_result.set_dlc_root(
      utils::GetDlcRootInModulePath(base::FilePath(mount_point)).value());
  SendOnInstalledSignal(install_result);
}

void DlcServiceDBusAdaptor::OnStatusUpdateSignalConnected(
    const std::string& interface_name,
    const std::string& signal_name,
    bool success) {
  if (!success) {
    LOG(ERROR) << "Failed to connect to update_engine's StatusUpdate signal.";
  }
}

}  // namespace dlcservice
