// Copyright 2019 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 "diagnostics/wilco_dtc_supportd/routine_service.h"

#include <iterator>
#include <string>
#include <utility>
#include <vector>

#include "diagnostics/common/mojo_utils.h"
#include "mojo/cros_healthd.mojom.h"
#include "mojo/cros_healthd_diagnostics.mojom.h"

namespace diagnostics {
namespace mojo_ipc = ::chromeos::cros_healthd::mojom;

namespace {

// When the battery routine's low_mah and high_mah parameters are not set, we
// default to low_mah = 1000mAh and high_mah = 10000mAh.
constexpr int kRoutineBatteryDefaultLowmAh = 1000;
constexpr int kRoutineBatteryDefaultHighmAh = 10000;

// Converts from mojo's DiagnosticRoutineStatusEnum to gRPC's
// DiagnosticRoutineStatus.
bool GetGrpcStatusFromMojoStatus(
    chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum mojo_status,
    grpc_api::DiagnosticRoutineStatus* grpc_status_out) {
  DCHECK(grpc_status_out);
  switch (mojo_status) {
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kReady:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_READY;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kRunning:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_RUNNING;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kWaiting:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_WAITING;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kPassed:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_PASSED;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kFailed:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_FAILED;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kError:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_ERROR;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kCancelled:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_CANCELLED;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::
        kFailedToStart:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_FAILED_TO_START;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::kRemoved:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_REMOVED;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::
        kCancelling:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_CANCELLING;
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum::
        kUnsupported:
      *grpc_status_out = grpc_api::ROUTINE_STATUS_ERROR;
      return true;
  }
  LOG(ERROR) << "Unknown mojo routine status: "
             << static_cast<int>(mojo_status);
  return false;
}

// Converts from mojo's DiagnosticRoutineUserMessageEnum to gRPC's
// DiagnosticRoutineUserMessage.
bool GetUserMessageFromMojoEnum(
    chromeos::cros_healthd::mojom::DiagnosticRoutineUserMessageEnum
        mojo_message,
    grpc_api::DiagnosticRoutineUserMessage* grpc_message_out) {
  DCHECK(grpc_message_out);
  switch (mojo_message) {
    case chromeos::cros_healthd::mojom::DiagnosticRoutineUserMessageEnum::
        kUnplugACPower:
      *grpc_message_out = grpc_api::ROUTINE_USER_MESSAGE_UNPLUG_AC_POWER;
      return true;
    default:
      LOG(ERROR) << "Unknown mojo user message: "
                 << static_cast<int>(mojo_message);
      return false;
  }
}

// Converts from mojo's DiagnosticRoutineEnum to gRPC's DiagnosticRoutine.
bool GetGrpcRoutineEnumFromMojoRoutineEnum(
    chromeos::cros_healthd::mojom::DiagnosticRoutineEnum mojo_enum,
    std::vector<grpc_api::DiagnosticRoutine>* grpc_enum_out) {
  DCHECK(grpc_enum_out);
  switch (mojo_enum) {
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryCapacity:
      grpc_enum_out->push_back(grpc_api::ROUTINE_BATTERY);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kBatteryHealth:
      grpc_enum_out->push_back(grpc_api::ROUTINE_BATTERY_SYSFS);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kUrandom:
      grpc_enum_out->push_back(grpc_api::ROUTINE_URANDOM);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kSmartctlCheck:
      grpc_enum_out->push_back(grpc_api::ROUTINE_SMARTCTL_CHECK);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kCpuCache:
      grpc_enum_out->push_back(grpc_api::ROUTINE_CPU_CACHE);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kCpuStress:
      grpc_enum_out->push_back(grpc_api::ROUTINE_CPU_STRESS);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::
        kFloatingPointAccuracy:
      grpc_enum_out->push_back(grpc_api::ROUTINE_FLOATING_POINT_ACCURACY);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kNvmeWearLevel:
      grpc_enum_out->push_back(grpc_api::ROUTINE_NVME_WEAR_LEVEL);
      return true;
    // There is only one mojo enum for self_test(short & extended share same
    // class), but there're 2 gRPC enum for self_test according to requirement.
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kNvmeSelfTest:
      grpc_enum_out->push_back(grpc_api::ROUTINE_NVME_SHORT_SELF_TEST);
      grpc_enum_out->push_back(grpc_api::ROUTINE_NVME_LONG_SELF_TEST);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kDiskRead:
      grpc_enum_out->push_back(grpc_api::ROUTINE_DISK_LINEAR_READ);
      grpc_enum_out->push_back(grpc_api::ROUTINE_DISK_RANDOM_READ);
      return true;
    case chromeos::cros_healthd::mojom::DiagnosticRoutineEnum::kPrimeSearch:
      grpc_enum_out->push_back(grpc_api::ROUTINE_PRIME_SEARCH);
      return true;
    default:
      LOG(ERROR) << "Unknown mojo routine: " << static_cast<int>(mojo_enum);
      return false;
  }
}

// Converts from mojo's RoutineUpdate to gRPC's GetRoutineUpdateResponse.
void SetGrpcUpdateFromMojoUpdate(
    chromeos::cros_healthd::mojom::RoutineUpdatePtr mojo_update,
    grpc_api::GetRoutineUpdateResponse* grpc_update) {
  DCHECK(grpc_update);
  grpc_update->set_progress_percent(mojo_update->progress_percent);
  const auto& update_union = mojo_update->routine_update_union;
  if (update_union->is_interactive_update()) {
    grpc_api::DiagnosticRoutineUserMessage grpc_message;
    chromeos::cros_healthd::mojom::DiagnosticRoutineUserMessageEnum
        mojo_message = update_union->get_interactive_update()->user_message;
    if (!GetUserMessageFromMojoEnum(mojo_message, &grpc_message)) {
      grpc_update->set_status(grpc_api::ROUTINE_STATUS_ERROR);
    } else {
      grpc_update->set_user_message(grpc_message);
    }
  } else {
    grpc_update->set_status_message(
        update_union->get_noninteractive_update()->status_message);
    grpc_api::DiagnosticRoutineStatus grpc_status;
    auto mojo_status = update_union->get_noninteractive_update()->status;
    if (!GetGrpcStatusFromMojoStatus(mojo_status, &grpc_status)) {
      grpc_update->set_status(grpc_api::ROUTINE_STATUS_ERROR);
    } else {
      grpc_update->set_status(grpc_status);
    }
  }

  if (!mojo_update->output.is_valid()) {
    // This isn't necessarily an error, since some requests may not have
    // specified that they wanted output returned, and some routines may never
    // return any extra input. We'll log the event in the case that it was an
    // error.
    VLOG(1) << "No output in mojo update.";
    return;
  }

  auto shm_mapping = GetReadOnlySharedMemoryMappingFromMojoHandle(
      std::move(mojo_update->output));
  if (!shm_mapping.IsValid()) {
    PLOG(ERROR) << "Failed to read data from mojo handle";
    return;
  }
  grpc_update->set_output(std::string(shm_mapping.GetMemoryAs<const char>(),
                                      shm_mapping.mapped_size()));
}

// Converts from gRPC's GetRoutineUpdateRequest::Command to mojo's
// DiagnosticRoutineCommandEnum.
bool GetMojoCommandFromGrpcCommand(
    grpc_api::GetRoutineUpdateRequest::Command grpc_command,
    chromeos::cros_healthd::mojom::DiagnosticRoutineCommandEnum*
        mojo_command_out) {
  DCHECK(mojo_command_out);
  switch (grpc_command) {
    case grpc_api::GetRoutineUpdateRequest::RESUME:
      *mojo_command_out = chromeos::cros_healthd::mojom::
          DiagnosticRoutineCommandEnum::kContinue;
      return true;
    case grpc_api::GetRoutineUpdateRequest::CANCEL:
      *mojo_command_out =
          chromeos::cros_healthd::mojom::DiagnosticRoutineCommandEnum::kCancel;
      return true;
    case grpc_api::GetRoutineUpdateRequest::GET_STATUS:
      *mojo_command_out = chromeos::cros_healthd::mojom::
          DiagnosticRoutineCommandEnum::kGetStatus;
      return true;
    case grpc_api::GetRoutineUpdateRequest::REMOVE:
      *mojo_command_out =
          chromeos::cros_healthd::mojom::DiagnosticRoutineCommandEnum::kRemove;
      return true;
    default:
      LOG(ERROR) << "Unknown gRPC command: " << static_cast<int>(grpc_command);
      return false;
  }
}

}  // namespace

RoutineService::RoutineService(Delegate* delegate) : delegate_(delegate) {
  DCHECK(delegate_);
}

RoutineService::~RoutineService() {
  RunInFlightCallbacks();
}

void RoutineService::GetAvailableRoutines(
    const GetAvailableRoutinesToServiceCallback& callback) {
  if (!BindCrosHealthdDiagnosticsServiceIfNeeded()) {
    LOG(WARNING) << "GetAvailableRoutines called before mojo was bootstrapped.";
    callback.Run(std::vector<grpc_api::DiagnosticRoutine>{},
                 grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
    return;
  }

  const size_t callback_key = next_get_available_routines_key_;
  next_get_available_routines_key_++;
  DCHECK_EQ(get_available_routines_callbacks_.count(callback_key), 0);
  get_available_routines_callbacks_.insert({callback_key, std::move(callback)});
  service_ptr_->GetAvailableRoutines(
      base::Bind(&RoutineService::ForwardGetAvailableRoutinesResponse,
                 weak_ptr_factory_.GetWeakPtr(), callback_key));
}

void RoutineService::RunRoutine(const grpc_api::RunRoutineRequest& request,
                                const RunRoutineToServiceCallback& callback) {
  if (!BindCrosHealthdDiagnosticsServiceIfNeeded()) {
    LOG(WARNING) << "RunRoutine called before mojo was bootstrapped.";
    callback.Run(0 /* uuid */, grpc_api::ROUTINE_STATUS_FAILED_TO_START,
                 grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
    return;
  }

  const size_t callback_key = next_run_routine_key_;
  next_run_routine_key_++;
  DCHECK_EQ(run_routine_callbacks_.count(callback_key), 0);
  auto it = run_routine_callbacks_.insert({callback_key, std::move(callback)});

  switch (request.routine()) {
    case grpc_api::ROUTINE_BATTERY:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kBatteryParams);
      service_ptr_->RunBatteryCapacityRoutine(
          request.battery_params().low_mah()
              ? request.battery_params().low_mah()
              : kRoutineBatteryDefaultLowmAh,
          request.battery_params().high_mah()
              ? request.battery_params().high_mah()
              : kRoutineBatteryDefaultHighmAh,
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_BATTERY_SYSFS:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kBatterySysfsParams);
      service_ptr_->RunBatteryHealthRoutine(
          request.battery_sysfs_params().maximum_cycle_count(),
          request.battery_sysfs_params().percent_battery_wear_allowed(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_URANDOM:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kUrandomParams);
      service_ptr_->RunUrandomRoutine(
          request.urandom_params().length_seconds(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_SMARTCTL_CHECK:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kSmartctlCheckParams);
      service_ptr_->RunSmartctlCheckRoutine(
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_CPU_CACHE:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kCpuParams);
      service_ptr_->RunCpuCacheRoutine(
          request.cpu_params().length_seconds(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_CPU_STRESS:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kCpuParams);
      service_ptr_->RunCpuStressRoutine(
          request.cpu_params().length_seconds(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_FLOATING_POINT_ACCURACY:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kFloatingPointAccuracyParams);
      service_ptr_->RunFloatingPointAccuracyRoutine(
          request.floating_point_accuracy_params().length_seconds(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_NVME_WEAR_LEVEL:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kNvmeWearLevelParams);
      service_ptr_->RunNvmeWearLevelRoutine(
          request.nvme_wear_level_params().wear_level_threshold(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_NVME_SHORT_SELF_TEST:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kNvmeShortSelfTestParams);
      service_ptr_->RunNvmeSelfTestRoutine(
          chromeos::cros_healthd::mojom::NvmeSelfTestTypeEnum::kShortSelfTest,
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_NVME_LONG_SELF_TEST:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kNvmeLongSelfTestParams);
      service_ptr_->RunNvmeSelfTestRoutine(
          chromeos::cros_healthd::mojom::NvmeSelfTestTypeEnum::kLongSelfTest,
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_DISK_LINEAR_READ:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kDiskLinearReadParams);
      service_ptr_->RunDiskReadRoutine(
          mojo_ipc::DiskReadRoutineTypeEnum::kLinearRead,
          request.disk_linear_read_params().length_seconds(),
          request.disk_linear_read_params().file_size_mb(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_DISK_RANDOM_READ:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kDiskRandomReadParams);
      service_ptr_->RunDiskReadRoutine(
          mojo_ipc::DiskReadRoutineTypeEnum::kRandomRead,
          request.disk_random_read_params().length_seconds(),
          request.disk_random_read_params().file_size_mb(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    case grpc_api::ROUTINE_PRIME_SEARCH:
      DCHECK_EQ(request.parameters_case(),
                grpc_api::RunRoutineRequest::kPrimeSearchParams);
      service_ptr_->RunPrimeSearchRoutine(
          request.prime_search_params().length_seconds(),
          request.prime_search_params().max_num(),
          base::Bind(&RoutineService::ForwardRunRoutineResponse,
                     weak_ptr_factory_.GetWeakPtr(), callback_key));
      break;
    default:
      LOG(ERROR) << "RunRoutineRequest routine not set or unrecognized.";
      it.first->second.Run(0 /* uuid */, grpc_api::ROUTINE_STATUS_INVALID_FIELD,
                           grpc_api::ROUTINE_SERVICE_STATUS_OK);
      run_routine_callbacks_.erase(it.first);
      break;
  }
}

void RoutineService::GetRoutineUpdate(
    int uuid,
    grpc_api::GetRoutineUpdateRequest::Command command,
    bool include_output,
    const GetRoutineUpdateRequestToServiceCallback& callback) {
  if (!BindCrosHealthdDiagnosticsServiceIfNeeded()) {
    LOG(WARNING) << "GetRoutineUpdate called before mojo was bootstrapped.";
    callback.Run(uuid, grpc_api::ROUTINE_STATUS_ERROR, 0 /* progress_percent */,
                 grpc_api::ROUTINE_USER_MESSAGE_UNSET, "" /* output */,
                 "" /* status_message */,
                 grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
    return;
  }

  chromeos::cros_healthd::mojom::DiagnosticRoutineCommandEnum mojo_command;
  if (!GetMojoCommandFromGrpcCommand(command, &mojo_command)) {
    callback.Run(uuid, grpc_api::ROUTINE_STATUS_INVALID_FIELD,
                 0 /* progress_percent */, grpc_api::ROUTINE_USER_MESSAGE_UNSET,
                 "" /* output */, "" /* status_message */,
                 grpc_api::ROUTINE_SERVICE_STATUS_OK);
    return;
  }

  const size_t callback_key = next_get_routine_update_key_;
  next_get_routine_update_key_++;
  DCHECK_EQ(get_routine_update_callbacks_.count(callback_key), 0);
  get_routine_update_callbacks_.insert(
      {callback_key, {uuid, std::move(callback)}});
  service_ptr_->GetRoutineUpdate(
      uuid, mojo_command, include_output,
      base::Bind(&RoutineService::ForwardGetRoutineUpdateResponse,
                 weak_ptr_factory_.GetWeakPtr(), callback_key));
}

void RoutineService::ForwardGetAvailableRoutinesResponse(
    size_t callback_key,
    const std::vector<chromeos::cros_healthd::mojom::DiagnosticRoutineEnum>&
        mojo_routines) {
  auto it = get_available_routines_callbacks_.find(callback_key);
  if (it == get_available_routines_callbacks_.end()) {
    LOG(ERROR) << "Unknown callback_key for received mojo GetAvailableRoutines "
                  "response: "
               << callback_key;
    return;
  }

  std::vector<grpc_api::DiagnosticRoutine> grpc_routines;
  for (auto mojo_routine : mojo_routines) {
    std::vector<grpc_api::DiagnosticRoutine> grpc_mojo_routines;
    if (GetGrpcRoutineEnumFromMojoRoutineEnum(mojo_routine,
                                              &grpc_mojo_routines))
      for (auto grpc_routine : grpc_mojo_routines)
        grpc_routines.push_back(grpc_routine);
  }

  it->second.Run(std::move(grpc_routines), grpc_api::ROUTINE_SERVICE_STATUS_OK);
  get_available_routines_callbacks_.erase(it);
}

void RoutineService::ForwardRunRoutineResponse(
    size_t callback_key,
    chromeos::cros_healthd::mojom::RunRoutineResponsePtr response) {
  auto it = run_routine_callbacks_.find(callback_key);
  if (it == run_routine_callbacks_.end()) {
    LOG(ERROR) << "Unknown callback_key for received mojo GetAvailableRoutines "
                  "response: "
               << callback_key;
    return;
  }

  grpc_api::DiagnosticRoutineStatus grpc_status;
  chromeos::cros_healthd::mojom::DiagnosticRoutineStatusEnum mojo_status =
      response->status;
  if (!GetGrpcStatusFromMojoStatus(mojo_status, &grpc_status)) {
    it->second.Run(0 /* uuid */, grpc_api::ROUTINE_STATUS_ERROR,
                   grpc_api::ROUTINE_SERVICE_STATUS_OK);
  } else {
    it->second.Run(response->id, grpc_status,
                   grpc_api::ROUTINE_SERVICE_STATUS_OK);
  }
  run_routine_callbacks_.erase(it);
}

void RoutineService::ForwardGetRoutineUpdateResponse(
    size_t callback_key,
    chromeos::cros_healthd::mojom::RoutineUpdatePtr response) {
  auto it = get_routine_update_callbacks_.find(callback_key);
  if (it == get_routine_update_callbacks_.end()) {
    LOG(ERROR) << "Unknown callback_key for received mojo GetAvailableRoutines "
                  "response: "
               << callback_key;
    return;
  }

  grpc_api::GetRoutineUpdateResponse grpc_response;
  SetGrpcUpdateFromMojoUpdate(std::move(response), &grpc_response);
  it->second.second.Run(it->second.first /* uuid */, grpc_response.status(),
                        grpc_response.progress_percent(),
                        grpc_response.user_message(), grpc_response.output(),
                        grpc_response.status_message(),
                        grpc_api::ROUTINE_SERVICE_STATUS_OK);
  get_routine_update_callbacks_.erase(it);
}

bool RoutineService::BindCrosHealthdDiagnosticsServiceIfNeeded() {
  if (service_ptr_.is_bound())
    return true;

  auto request = mojo::MakeRequest(&service_ptr_);

  service_ptr_.set_connection_error_handler(base::Bind(
      &RoutineService::OnDisconnect, weak_ptr_factory_.GetWeakPtr()));

  if (!delegate_->GetCrosHealthdDiagnosticsService(std::move(request)))
    return false;

  return true;
}

void RoutineService::OnDisconnect() {
  VLOG(1) << "cros_healthd Mojo connection closed.";
  RunInFlightCallbacks();
  service_ptr_.reset();
}

void RoutineService::RunInFlightCallbacks() {
  for (auto& it : get_available_routines_callbacks_) {
    it.second.Run(std::vector<grpc_api::DiagnosticRoutine>{},
                  grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
  }
  get_available_routines_callbacks_.clear();

  for (auto& it : run_routine_callbacks_) {
    it.second.Run(0 /* uuid */, grpc_api::ROUTINE_STATUS_FAILED_TO_START,
                  grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
  }
  run_routine_callbacks_.clear();

  for (auto& it : get_routine_update_callbacks_) {
    it.second.second.Run(
        it.second.first /* uuid */, grpc_api::ROUTINE_STATUS_ERROR,
        0 /* progress_percent */, grpc_api::ROUTINE_USER_MESSAGE_UNSET,
        "" /* output */, "" /* status_message */,
        grpc_api::ROUTINE_SERVICE_STATUS_UNAVAILABLE);
  }
  get_routine_update_callbacks_.clear();
}

}  // namespace diagnostics
