// Copyright 2018 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 "chromeos/dbus/concierge_client.h"

#include <string>
#include <utility>

#include "base/bind.h"
#include "base/location.h"
#include "base/threading/thread_task_runner_handle.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "third_party/cros_system_api/dbus/vm_concierge/dbus-constants.h"

namespace concierge = vm_tools::concierge;

namespace {

// TODO(nverne): revert to TIMEOUT_USE_DEFAULT when StartVm no longer requires
// unnecessary long running crypto calculations _and_ b/143499148 is fixed.
// TODO(yusukes): Fix b/143499148.
constexpr int kConciergeDBusTimeoutMs = 160 * 1000;

}  // namespace

namespace chromeos {

class ConciergeClientImpl : public ConciergeClient {
 public:
  ConciergeClientImpl() {}

  ~ConciergeClientImpl() override = default;

  void AddObserver(Observer* observer) override {
    observer_list_.AddObserver(observer);
  }

  void RemoveObserver(Observer* observer) override {
    observer_list_.RemoveObserver(observer);
  }

  void AddVmObserver(VmObserver* observer) override {
    vm_observer_list_.AddObserver(observer);
  }

  void RemoveVmObserver(VmObserver* observer) override {
    vm_observer_list_.RemoveObserver(observer);
  }

  void AddContainerObserver(ContainerObserver* observer) override {
    container_observer_list_.AddObserver(observer);
  }

  void RemoveContainerObserver(ContainerObserver* observer) override {
    container_observer_list_.RemoveObserver(observer);
  }

  void AddDiskImageObserver(DiskImageObserver* observer) override {
    disk_image_observer_list_.AddObserver(observer);
  }

  void RemoveDiskImageObserver(DiskImageObserver* observer) override {
    disk_image_observer_list_.RemoveObserver(observer);
  }

  bool IsVmStartedSignalConnected() override {
    return is_vm_started_signal_connected_;
  }

  bool IsVmStoppedSignalConnected() override {
    return is_vm_stopped_signal_connected_;
  }

  bool IsContainerStartupFailedSignalConnected() override {
    return is_container_startup_failed_signal_connected_;
  }

  bool IsDiskImageProgressSignalConnected() override {
    return is_disk_import_progress_signal_connected_;
  }

  void CreateDiskImage(const concierge::CreateDiskImageRequest& request,
                       DBusMethodCallback<concierge::CreateDiskImageResponse>
                           callback) override {
    CallMethod(concierge::kCreateDiskImageMethod, request, std::move(callback));
  }

  void DestroyDiskImage(const concierge::DestroyDiskImageRequest& request,
                        DBusMethodCallback<concierge::DestroyDiskImageResponse>
                            callback) override {
    CallMethod(concierge::kDestroyDiskImageMethod, request,
               std::move(callback));
  }

  void ImportDiskImage(base::ScopedFD fd,
                       const concierge::ImportDiskImageRequest& request,
                       DBusMethodCallback<concierge::ImportDiskImageResponse>
                           callback) override {
    dbus::MethodCall method_call(concierge::kVmConciergeInterface,
                                 concierge::kImportDiskImageMethod);
    dbus::MessageWriter writer(&method_call);

    if (!writer.AppendProtoAsArrayOfBytes(request)) {
      LOG(ERROR) << "Failed to encode ImportDiskImageRequest protobuf";
      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
      return;
    }

    writer.AppendFileDescriptor(fd.get());

    concierge_proxy_->CallMethod(
        &method_call, kConciergeDBusTimeoutMs,
        base::BindOnce(&ConciergeClientImpl::OnDBusProtoResponse<
                           concierge::ImportDiskImageResponse>,
                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  }

  void CancelDiskImageOperation(
      const concierge::CancelDiskImageRequest& request,
      DBusMethodCallback<concierge::CancelDiskImageResponse> callback)
      override {
    CallMethod(concierge::kCancelDiskImageMethod, request, std::move(callback));
  }

  void DiskImageStatus(const concierge::DiskImageStatusRequest& request,
                       DBusMethodCallback<concierge::DiskImageStatusResponse>
                           callback) override {
    CallMethod(concierge::kDiskImageStatusMethod, request, std::move(callback));
  }

  void ListVmDisks(
      const concierge::ListVmDisksRequest& request,
      DBusMethodCallback<concierge::ListVmDisksResponse> callback) override {
    CallMethod(concierge::kListVmDisksMethod, request, std::move(callback));
  }

  void StartTerminaVm(
      const concierge::StartVmRequest& request,
      DBusMethodCallback<concierge::StartVmResponse> callback) override {
    CallMethod(concierge::kStartVmMethod, request, std::move(callback));
  }

  void StopVm(const concierge::StopVmRequest& request,
              DBusMethodCallback<concierge::StopVmResponse> callback) override {
    CallMethod(concierge::kStopVmMethod, request, std::move(callback));
  }

  void GetVmInfo(
      const concierge::GetVmInfoRequest& request,
      DBusMethodCallback<concierge::GetVmInfoResponse> callback) override {
    CallMethod(concierge::kGetVmInfoMethod, request, std::move(callback));
  }

  void GetVmEnterpriseReportingInfo(
      const concierge::GetVmEnterpriseReportingInfoRequest& request,
      DBusMethodCallback<concierge::GetVmEnterpriseReportingInfoResponse>
          callback) override {
    CallMethod(concierge::kGetVmEnterpriseReportingInfoMethod, request,
               std::move(callback));
  }

  void SetVmCpuRestriction(
      const concierge::SetVmCpuRestrictionRequest& request,
      DBusMethodCallback<concierge::SetVmCpuRestrictionResponse> callback)
      override {
    CallMethod(concierge::kSetVmCpuRestrictionMethod, request,
               std::move(callback));
  }

  void WaitForServiceToBeAvailable(
      dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback)
      override {
    concierge_proxy_->WaitForServiceToBeAvailable(std::move(callback));
  }

  void GetContainerSshKeys(
      const concierge::ContainerSshKeysRequest& request,
      DBusMethodCallback<concierge::ContainerSshKeysResponse> callback)
      override {
    CallMethod(concierge::kGetContainerSshKeysMethod, request,
               std::move(callback));
  }

  void AttachUsbDevice(base::ScopedFD fd,
                       const concierge::AttachUsbDeviceRequest& request,
                       DBusMethodCallback<concierge::AttachUsbDeviceResponse>
                           callback) override {
    dbus::MethodCall method_call(concierge::kVmConciergeInterface,
                                 concierge::kAttachUsbDeviceMethod);
    dbus::MessageWriter writer(&method_call);

    if (!writer.AppendProtoAsArrayOfBytes(request)) {
      LOG(ERROR) << "Failed to encode AttachUsbDeviceRequest protobuf";
      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
      return;
    }

    writer.AppendFileDescriptor(fd.get());

    concierge_proxy_->CallMethod(
        &method_call, kConciergeDBusTimeoutMs,
        base::BindOnce(&ConciergeClientImpl::OnDBusProtoResponse<
                           concierge::AttachUsbDeviceResponse>,
                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  }

  void DetachUsbDevice(const concierge::DetachUsbDeviceRequest& request,
                       DBusMethodCallback<concierge::DetachUsbDeviceResponse>
                           callback) override {
    CallMethod(concierge::kDetachUsbDeviceMethod, request, std::move(callback));
  }

  void StartArcVm(
      const concierge::StartArcVmRequest& request,
      DBusMethodCallback<concierge::StartVmResponse> callback) override {
    CallMethod(concierge::kStartArcVmMethod, request, std::move(callback));
  }

 protected:
  void Init(dbus::Bus* bus) override {
    concierge_proxy_ = bus->GetObjectProxy(
        concierge::kVmConciergeServiceName,
        dbus::ObjectPath(concierge::kVmConciergeServicePath));
    if (!concierge_proxy_) {
      LOG(ERROR) << "Unable to get dbus proxy for "
                 << concierge::kVmConciergeServiceName;
    }
    concierge_proxy_->SetNameOwnerChangedCallback(
        base::BindRepeating(&ConciergeClientImpl::NameOwnerChangedReceived,
                            weak_ptr_factory_.GetWeakPtr()));
    concierge_proxy_->ConnectToSignal(
        concierge::kVmConciergeInterface, concierge::kVmStartedSignal,
        base::BindRepeating(&ConciergeClientImpl::OnVmStartedSignal,
                            weak_ptr_factory_.GetWeakPtr()),
        base::BindOnce(&ConciergeClientImpl::OnSignalConnected,
                       weak_ptr_factory_.GetWeakPtr()));
    concierge_proxy_->ConnectToSignal(
        concierge::kVmConciergeInterface, concierge::kVmStoppedSignal,
        base::BindRepeating(&ConciergeClientImpl::OnVmStoppedSignal,
                            weak_ptr_factory_.GetWeakPtr()),
        base::BindOnce(&ConciergeClientImpl::OnSignalConnected,
                       weak_ptr_factory_.GetWeakPtr()));
    concierge_proxy_->ConnectToSignal(
        concierge::kVmConciergeInterface,
        concierge::kContainerStartupFailedSignal,
        base::BindRepeating(
            &ConciergeClientImpl::OnContainerStartupFailedSignal,
            weak_ptr_factory_.GetWeakPtr()),
        base::BindOnce(&ConciergeClientImpl::OnSignalConnected,
                       weak_ptr_factory_.GetWeakPtr()));
    concierge_proxy_->ConnectToSignal(
        concierge::kVmConciergeInterface, concierge::kDiskImageProgressSignal,
        base::BindRepeating(&ConciergeClientImpl::OnDiskImageProgress,
                            weak_ptr_factory_.GetWeakPtr()),
        base::BindOnce(&ConciergeClientImpl::OnSignalConnected,
                       weak_ptr_factory_.GetWeakPtr()));
  }

 private:
  template <typename RequestProto, typename ResponseProto>
  void CallMethod(const std::string& method_name,
                  const RequestProto& request,
                  DBusMethodCallback<ResponseProto> callback) {
    dbus::MethodCall method_call(concierge::kVmConciergeInterface, method_name);
    dbus::MessageWriter writer(&method_call);

    if (!writer.AppendProtoAsArrayOfBytes(request)) {
      LOG(ERROR) << "Failed to encode protobuf for " << method_name;
      base::ThreadTaskRunnerHandle::Get()->PostTask(
          FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
      return;
    }

    concierge_proxy_->CallMethod(
        &method_call, kConciergeDBusTimeoutMs,
        base::BindOnce(&ConciergeClientImpl::OnDBusProtoResponse<ResponseProto>,
                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  }

  template <typename ResponseProto>
  void OnDBusProtoResponse(DBusMethodCallback<ResponseProto> callback,
                           dbus::Response* dbus_response) {
    if (!dbus_response) {
      std::move(callback).Run(base::nullopt);
      return;
    }
    ResponseProto reponse_proto;
    dbus::MessageReader reader(dbus_response);
    if (!reader.PopArrayOfBytesAsProto(&reponse_proto)) {
      LOG(ERROR) << "Failed to parse proto from DBus Response.";
      std::move(callback).Run(base::nullopt);
      return;
    }
    std::move(callback).Run(std::move(reponse_proto));
  }

  void NameOwnerChangedReceived(const std::string& old_owner,
                                const std::string& new_owner) {
    const bool restarted = !new_owner.empty();
    for (auto& observer : observer_list_) {
      if (restarted)
        observer.ConciergeServiceRestarted();
      else
        observer.ConciergeServiceStopped();
    }
  }

  void OnVmStartedSignal(dbus::Signal* signal) {
    DCHECK_EQ(signal->GetInterface(), concierge::kVmConciergeInterface);
    DCHECK_EQ(signal->GetMember(), concierge::kVmStartedSignal);

    concierge::VmStartedSignal vm_started_signal;
    dbus::MessageReader reader(signal);
    if (!reader.PopArrayOfBytesAsProto(&vm_started_signal)) {
      LOG(ERROR) << "Failed to parse proto from DBus Signal";
      return;
    }

    for (auto& observer : vm_observer_list_)
      observer.OnVmStarted(vm_started_signal);
  }

  void OnVmStoppedSignal(dbus::Signal* signal) {
    DCHECK_EQ(signal->GetInterface(), concierge::kVmConciergeInterface);
    DCHECK_EQ(signal->GetMember(), concierge::kVmStoppedSignal);

    concierge::VmStoppedSignal vm_stopped_signal;
    dbus::MessageReader reader(signal);
    if (!reader.PopArrayOfBytesAsProto(&vm_stopped_signal)) {
      LOG(ERROR) << "Failed to parse proto from DBus Signal";
      return;
    }

    for (auto& observer : vm_observer_list_)
      observer.OnVmStopped(vm_stopped_signal);
  }

  void OnContainerStartupFailedSignal(dbus::Signal* signal) {
    DCHECK_EQ(signal->GetInterface(), concierge::kVmConciergeInterface);
    DCHECK_EQ(signal->GetMember(), concierge::kContainerStartupFailedSignal);

    concierge::ContainerStartedSignal container_startup_failed_signal;
    dbus::MessageReader reader(signal);
    if (!reader.PopArrayOfBytesAsProto(&container_startup_failed_signal)) {
      LOG(ERROR) << "Failed to parse proto from DBus Signal";
      return;
    }

    for (auto& observer : container_observer_list_) {
      observer.OnContainerStartupFailed(container_startup_failed_signal);
    }
  }

  void OnDiskImageProgress(dbus::Signal* signal) {
    DCHECK_EQ(signal->GetInterface(), concierge::kVmConciergeInterface);
    DCHECK_EQ(signal->GetMember(), concierge::kDiskImageProgressSignal);

    concierge::DiskImageStatusResponse disk_image_status_response_signal;
    dbus::MessageReader reader(signal);
    if (!reader.PopArrayOfBytesAsProto(&disk_image_status_response_signal)) {
      LOG(ERROR) << "Failed to parse proto from DBus Signal";
      return;
    }

    for (auto& observer : disk_image_observer_list_) {
      observer.OnDiskImageProgress(disk_image_status_response_signal);
    }
  }

  void OnSignalConnected(const std::string& interface_name,
                         const std::string& signal_name,
                         bool is_connected) {
    DCHECK_EQ(interface_name, concierge::kVmConciergeInterface);
    if (!is_connected)
      LOG(ERROR) << "Failed to connect to signal: " << signal_name;

    if (signal_name == concierge::kVmStartedSignal) {
      is_vm_started_signal_connected_ = is_connected;
    } else if (signal_name == concierge::kVmStoppedSignal) {
      is_vm_stopped_signal_connected_ = is_connected;
    } else if (signal_name == concierge::kContainerStartupFailedSignal) {
      is_container_startup_failed_signal_connected_ = is_connected;
    } else if (signal_name == concierge::kDiskImageProgressSignal) {
      is_disk_import_progress_signal_connected_ = is_connected;
    } else {
      NOTREACHED();
    }
  }

  dbus::ObjectProxy* concierge_proxy_ = nullptr;

  base::ObserverList<Observer> observer_list_;
  base::ObserverList<VmObserver>::Unchecked vm_observer_list_;
  base::ObserverList<ContainerObserver>::Unchecked container_observer_list_;
  base::ObserverList<DiskImageObserver>::Unchecked disk_image_observer_list_;

  bool is_vm_started_signal_connected_ = false;
  bool is_vm_stopped_signal_connected_ = false;
  bool is_container_startup_failed_signal_connected_ = false;
  bool is_disk_import_progress_signal_connected_ = false;

  // Note: This should remain the last member so it'll be destroyed and
  // invalidate its weak pointers before any other members are destroyed.
  base::WeakPtrFactory<ConciergeClientImpl> weak_ptr_factory_{this};

  DISALLOW_COPY_AND_ASSIGN(ConciergeClientImpl);
};

ConciergeClient::ConciergeClient() = default;

ConciergeClient::~ConciergeClient() = default;

std::unique_ptr<ConciergeClient> ConciergeClient::Create() {
  return std::make_unique<ConciergeClientImpl>();
}

}  // namespace chromeos
