// 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 <memory>
#include <utility>
#include <vector>

#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.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"

using base::Callback;
using base::File;
using base::FilePath;
using base::ScopedTempDir;
using std::pair;
using std::string;
using std::unique_ptr;
using std::vector;
using update_engine::Operation;
using update_engine::StatusResult;

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 FilePath& path) {
  File::Error file_err;
  if (!base::CreateDirectoryAndGetError(path, &file_err)) {
    LOG(ERROR) << "Failed to create directory '" << path.value()
               << "': " << 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 FilePath& path, int64_t image_size) {
  if (!CreateDirWithDlcPermissions(path.DirName())) {
    return false;
  }
  constexpr uint32_t file_flags =
      File::FLAG_CREATE | File::FLAG_READ | File::FLAG_WRITE;
  File file(path, file_flags);
  if (!file.IsValid()) {
    LOG(ERROR) << "Failed to create image file '" << path.value()
               << "': " << 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 with error code and error message after which
// logs the error message will also be logged.
void LogAndSetError(brillo::ErrorPtr* err,
                    const string& code,
                    const string& msg) {
  if (err)
    *err = brillo::Error::Create(FROM_HERE, brillo::errors::dbus::kDomain, code,
                                 msg);
  LOG(ERROR) << msg;
}

}  // namespace

DlcServiceDBusAdaptor::DlcServiceDBusAdaptor(
    unique_ptr<org::chromium::ImageLoaderInterfaceProxyInterface>
        image_loader_proxy,
    unique_ptr<org::chromium::UpdateEngineInterfaceProxyInterface>
        update_engine_proxy,
    unique_ptr<BootSlot> boot_slot,
    const FilePath& manifest_dir,
    const 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.
  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_->RegisterStatusUpdateAdvancedSignalHandler(
      base::Bind(&DlcServiceDBusAdaptor::OnStatusUpdateAdvancedSignal,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&DlcServiceDBusAdaptor::OnStatusUpdateAdvancedSignalConnected,
                 weak_ptr_factory_.GetWeakPtr()));

  // Initalize installed DLC modules.
  for (auto installed_dlc_id : utils::ScanDirectory(content_dir_))
    installed_dlc_modules_[installed_dlc_id];

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

DlcServiceDBusAdaptor::~DlcServiceDBusAdaptor() {}

void DlcServiceDBusAdaptor::LoadDlcModuleImages() {
  // Load all installed DLC modules.
  for (auto installed_dlc_module_itr = installed_dlc_modules_.begin();
       installed_dlc_module_itr != installed_dlc_modules_.end();
       /* Don't increment here */) {
    const string& installed_dlc_module_id = installed_dlc_module_itr->first;
    string& installed_dlc_module_root = installed_dlc_module_itr->second;

    if (base::PathExists(FilePath(installed_dlc_module_root))) {
      ++installed_dlc_module_itr;
      continue;
    }

    string mount_point;
    if (!MountDlc(nullptr, installed_dlc_module_id, &mount_point)) {
      LOG(ERROR) << "Failed to mount DLC module during load: "
                 << installed_dlc_module_id;
      if (!DeleteDlc(nullptr, installed_dlc_module_id)) {
        LOG(ERROR) << "Failed to delete an unmountable DLC module: "
                   << installed_dlc_module_id;
      }
      installed_dlc_modules_.erase(installed_dlc_module_itr++);
    } else {
      installed_dlc_module_root =
          utils::GetDlcRootInModulePath(FilePath(mount_point)).value();
      ++installed_dlc_module_itr;
    }
  }
}

bool DlcServiceDBusAdaptor::Install(brillo::ErrorPtr* err,
                                    const DlcModuleList& dlc_module_list_in) {
  if (dlc_module_list_in.dlc_module_infos().empty()) {
    LogAndSetError(err, kErrorInvalidDlc,
                   "Must provide at least one DLC to install");
    return false;
  }

  // Pick up DLC(s) from |DlcModuleList| passed in which have no roots.
  DlcRootMap unique_dlcs = utils::ToDlcRootMap(
      dlc_module_list_in,
      [](DlcModuleInfo dlc) { return dlc.dlc_root().empty(); });

  // Check that no duplicate DLC(s) were passed in.
  if (unique_dlcs.size() != dlc_module_list_in.dlc_module_infos_size()) {
    // Note: nice to have for log which was duplicate, but not necessary ATM.
    LogAndSetError(err, kErrorInvalidDlc,
                   "Must not pass in duplicate DLC(s) to install");
    return false;
  }

  LoadDlcModuleImages();

  // Go through already installed DLC(s) and set the roots if found.
  for (const auto& unique_dlc : unique_dlcs) {
    const string& id = unique_dlc.first;
    if (installed_dlc_modules_.find(id) != installed_dlc_modules_.end())
      unique_dlcs[id] = installed_dlc_modules_[id];
  }

  // This is the entire unique DLC(s) asked to be installed.
  DlcModuleList unique_dlc_module_list =
      utils::ToDlcModuleList(unique_dlcs, [](DlcId, DlcRoot) { return true; });
  // This is the unique DLC(s) that actually need to be installed.
  DlcModuleList unique_dlc_module_list_to_install = utils::ToDlcModuleList(
      unique_dlcs, [](DlcId, DlcRoot root) { return root.empty(); });
  // Copy over the Omaha URL.
  unique_dlc_module_list_to_install.set_omaha_url(
      dlc_module_list_in.omaha_url());

  // Check if there is nothing to install.
  if (unique_dlc_module_list_to_install.dlc_module_infos_size() == 0) {
    InstallStatus install_status = utils::CreateInstallStatus(
        Status::COMPLETED, kErrorNone, unique_dlc_module_list, 1.);
    SendOnInstallStatusSignal(install_status);
    return true;
  }
  Operation update_engine_operation;
  if (!GetUpdateEngineStatus(&update_engine_operation)) {
    LogAndSetError(err, kErrorInternal,
                   "Failed to get the status of Update Engine.");
    return false;
  }
  switch (update_engine_operation) {
    case update_engine::UPDATED_NEED_REBOOT:
      LogAndSetError(err, kErrorNeedReboot,
                     "Update Engine applied update, device needs a reboot.");
      return false;
    case update_engine::IDLE:
      break;
    default:
      LogAndSetError(err, kErrorBusy,
                     "Update Engine is performing operations.");
      return false;
  }

  // Note: this holds the list of directories that were created and need to be
  // freed in case an error happens.
  vector<unique_ptr<ScopedTempDir>> scoped_paths;

  for (const DlcModuleInfo& dlc_module :
       unique_dlc_module_list_to_install.dlc_module_infos()) {
    FilePath path;
    const string& id = dlc_module.dlc_id();
    auto scoped_path = std::make_unique<ScopedTempDir>();

    if (!CreateDlc(err, id, &path))
      return false;

    if (!scoped_path->Set(path)) {
      LOG(ERROR) << "Failed when scoping path during install: " << path.value();
      return false;
    }

    scoped_paths.emplace_back(std::move(scoped_path));
  }

  // Invokes update_engine to install the DLC module.
  if (!update_engine_proxy_->AttemptInstall(unique_dlc_module_list_to_install,
                                            nullptr)) {
    // TODO(kimjae): need update engine to propagate correct error message by
    // passing in |ErrorPtr| and being set within update engine, current default
    // is to indicate that update engine is updating because there is no way an
    // install should have taken place if not through dlcservice. (could also be
    // the case that an update applied between the time of the last status check
    // above, but just return |kErrorBusy| because the next time around if an
    // update has been applied and is in a reboot needed state, it will indicate
    // correctly then).
    LogAndSetError(err, kErrorBusy,
                   "Update Engine failed to schedule install operations.");
    return false;
  }

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

  // Safely take ownership of scoped paths for them not to be freed.
  for (const auto& scoped_path : scoped_paths)
    scoped_path->Take();

  return true;
}

bool DlcServiceDBusAdaptor::Uninstall(brillo::ErrorPtr* err,
                                      const string& id_in) {
  LoadDlcModuleImages();
  if (installed_dlc_modules_.find(id_in) == installed_dlc_modules_.end()) {
    LOG(INFO) << "Uninstalling DLC id that's not installed: " << id_in;
    return true;
  }

  Operation update_engine_operation;
  if (!GetUpdateEngineStatus(&update_engine_operation)) {
    LogAndSetError(err, kErrorInternal,
                   "Failed to get the status of Update Engine");
    return false;
  }
  switch (update_engine_operation) {
    case update_engine::IDLE:
    case update_engine::UPDATED_NEED_REBOOT:
      break;
    default:
      LogAndSetError(err, kErrorBusy, "Install or update is in progress.");
      return false;
  }

  if (!UnmountDlc(err, id_in))
    return false;

  if (!DeleteDlc(err, id_in))
    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) {
  LoadDlcModuleImages();
  *dlc_module_list_out = utils::ToDlcModuleList(
      installed_dlc_modules_, [](DlcId, DlcRoot) { return true; });
  return true;
}

bool DlcServiceDBusAdaptor::HandleStatusResult(
    const StatusResult& status_result) {
  if (!status_result.is_install()) {
    LOG(INFO) << "Signal from update_engine, not for install.";
    return false;
  }

  if (status_result.current_operation() == Operation::REPORTING_ERROR_EVENT) {
    InstallStatus install_status =
        utils::CreateInstallStatus(Status::FAILED, kErrorInternal, {}, 0.);
    SendOnInstallStatusSignal(install_status);
    dlc_modules_being_installed_.clear_dlc_module_infos();
    return false;
  }

  if (status_result.current_operation() != Operation::IDLE) {
    LOG(INFO) << "Signal from update_engine, but install not complete.";
    InstallStatus install_status = utils::CreateInstallStatus(
        Status::RUNNING, kErrorNone, {}, status_result.progress());
    SendOnInstallStatusSignal(install_status);
    return false;
  }

  LOG(INFO)
      << "Signal from update_engine, proceeding to complete installation.";
  return true;
}

bool DlcServiceDBusAdaptor::CreateDlc(brillo::ErrorPtr* err,
                                      const string& id,
                                      FilePath* path) {
  path->clear();
  if (supported_dlc_modules_.find(id) == supported_dlc_modules_.end()) {
    LogAndSetError(err, kErrorInvalidDlc,
                   "The DLC ID provided is not supported.");
    return false;
  }

  const string& package = ScanDlcModulePackage(id);
  FilePath module_path = utils::GetDlcModulePath(content_dir_, id);
  FilePath module_package_path =
      utils::GetDlcModulePackagePath(content_dir_, id, package);

  if (base::PathExists(module_path)) {
    LogAndSetError(err, kErrorInternal,
                   "The DLC module is installed or duplicate.");
    return false;
  }
  // Create the DLC ID directory with correct permissions.
  if (!CreateDirWithDlcPermissions(module_path)) {
    LogAndSetError(err, kErrorInternal, "Failed to create DLC ID directory");
    return false;
  }
  // Create the DLC package directory with correct permissions.
  if (!CreateDirWithDlcPermissions(module_package_path)) {
    LogAndSetError(err, kErrorInternal,
                   "Failed to create DLC ID package directory");
    return false;
  }

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

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

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

  *path = module_path;
  return true;
}

bool DlcServiceDBusAdaptor::DeleteDlc(brillo::ErrorPtr* err,
                                      const std::string& id) {
  FilePath dlc_module_path = utils::GetDlcModulePath(content_dir_, id);
  if (!DeleteFile(dlc_module_path, true)) {
    LogAndSetError(err, kErrorInternal,
                   "DLC image folder could not be deleted.");
    return false;
  }
  return true;
}

bool DlcServiceDBusAdaptor::MountDlc(brillo::ErrorPtr* err,
                                     const string& id,
                                     string* mount_point) {
  if (!image_loader_proxy_->LoadDlcImage(id, ScanDlcModulePackage(id),
                                         current_boot_slot_name_, mount_point,
                                         nullptr)) {
    LogAndSetError(err, kErrorInternal, "Imageloader is not available.");
    return false;
  }
  if (mount_point->empty()) {
    LogAndSetError(err, kErrorInternal, "Imageloader LoadDlcImage() failed.");
    return false;
  }
  return true;
}

bool DlcServiceDBusAdaptor::UnmountDlc(brillo::ErrorPtr* err,
                                       const string& id) {
  bool success = false;
  if (!image_loader_proxy_->UnloadDlcImage(id, ScanDlcModulePackage(id),
                                           &success, nullptr)) {
    LogAndSetError(err, kErrorInternal, "Imageloader is not available.");
    return false;
  }
  if (!success) {
    LogAndSetError(err, kErrorInternal, "Imageloader UnloadDlcImage failed.");
    return false;
  }
  return true;
}

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

bool DlcServiceDBusAdaptor::GetUpdateEngineStatus(Operation* operation) {
  StatusResult status_result;
  if (!update_engine_proxy_->GetStatusAdvanced(&status_result, nullptr)) {
    return false;
  }
  *operation = status_result.current_operation();
  return true;
}

void DlcServiceDBusAdaptor::SendOnInstallStatusSignal(
    const InstallStatus& install_status) {
  org::chromium::DlcServiceInterfaceAdaptor::SendOnInstallStatusSignal(
      install_status);
}

void DlcServiceDBusAdaptor::OnStatusUpdateAdvancedSignal(
    const StatusResult& status_result) {
  if (!HandleStatusResult(status_result))
    return;

  // At this point, update_engine finished installation of the requested DLC(s).
  DlcModuleList dlc_module_list, dlc_module_list_post_mount;
  dlc_module_list.CopyFrom(dlc_modules_being_installed_);
  dlc_module_list_post_mount.CopyFrom(dlc_modules_being_installed_);
  dlc_modules_being_installed_.clear_dlc_module_infos();

  // Keep track of the cleanups for DLC images.
  utils::ScopedCleanups<Callback<void()>> scoped_cleanups;
  for (const DlcModuleInfo& dlc_module : dlc_module_list.dlc_module_infos()) {
    // Don't cleanup for already mounted.
    if (!dlc_module.dlc_root().empty())
      continue;
    const string& dlc_id = dlc_module.dlc_id();
    auto cleanup = base::Bind(
        [](Callback<bool()> unmounter, Callback<bool()> deleter) {
          unmounter.Run();
          deleter.Run();
        },
        base::Bind(&DlcServiceDBusAdaptor::UnmountDlc, base::Unretained(this),
                   nullptr, dlc_id),
        base::Bind(&DlcServiceDBusAdaptor::DeleteDlc, base::Unretained(this),
                   nullptr, dlc_id));
    scoped_cleanups.Insert(cleanup);
  }

  // Mount the installed DLC module images not already mounted.
  for (auto& dlc_module :
       *dlc_module_list_post_mount.mutable_dlc_module_infos()) {
    // Don't remount already mounted.
    if (!dlc_module.dlc_root().empty())
      continue;
    const string& dlc_module_id = dlc_module.dlc_id();
    string mount_point;
    if (!MountDlc(nullptr, dlc_module_id, &mount_point)) {
      InstallStatus install_status = utils::CreateInstallStatus(
          Status::FAILED, kErrorInternal, dlc_module_list, 0.);
      SendOnInstallStatusSignal(install_status);
      return;
    }
    dlc_module.set_dlc_root(
        utils::GetDlcRootInModulePath(FilePath(mount_point)).value());
  }

  // Don't unmount+delete the images+directories as all successfully installed.
  scoped_cleanups.Cancel();

  // Install was a success so keep track.
  for (const DlcModuleInfo& installed_dlc_module :
       dlc_module_list_post_mount.dlc_module_infos())
    installed_dlc_modules_.emplace(installed_dlc_module.dlc_id(),
                                   installed_dlc_module.dlc_root());

  InstallStatus install_status = utils::CreateInstallStatus(
      Status::COMPLETED, kErrorNone, dlc_module_list_post_mount, 1.);
  SendOnInstallStatusSignal(install_status);
}

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

}  // namespace dlcservice
