blob: db8a2d4738611ceb722940beda2e5d5757a18895 [file] [log] [blame]
// 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.
#ifndef DIAGNOSTICS_WILCO_DTC_SUPPORTD_ROUTINE_SERVICE_H_
#define DIAGNOSTICS_WILCO_DTC_SUPPORTD_ROUTINE_SERVICE_H_
#include <cstddef>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <base/callback.h>
#include <base/macros.h>
#include "mojo/cros_healthd.mojom.h"
#include "wilco_dtc_supportd.pb.h" // NOLINT(build/include)
namespace diagnostics {
// The routine service is responsible for creating and managing diagnostic
// routines.
class RoutineService final {
public:
using GetAvailableRoutinesToServiceCallback = base::Callback<void(
const std::vector<grpc_api::DiagnosticRoutine>& routines,
grpc_api::RoutineServiceStatus service_status)>;
using RunRoutineToServiceCallback =
base::Callback<void(int uuid,
grpc_api::DiagnosticRoutineStatus status,
grpc_api::RoutineServiceStatus service_status)>;
using GetRoutineUpdateRequestToServiceCallback =
base::Callback<void(int uuid,
grpc_api::DiagnosticRoutineStatus status,
int progress_percent,
grpc_api::DiagnosticRoutineUserMessage user_message,
const std::string& output,
const std::string& status_message,
grpc_api::RoutineServiceStatus service_status)>;
class Delegate {
public:
virtual ~Delegate() = default;
// Binds |service| to an implementation of CrosHealthdDiagnosticsService. In
// production, the implementation is provided by cros_healthd. Returns false
// if wilco_dtc_supportd's mojo service has not been started by Chrome at
// the time this is called.
virtual bool GetCrosHealthdDiagnosticsService(
chromeos::cros_healthd::mojom::CrosHealthdDiagnosticsServiceRequest
service) = 0;
};
// |delegate| - Unowned pointer; must outlive this instance.
explicit RoutineService(Delegate* delegate);
RoutineService(const RoutineService&) = delete;
RoutineService& operator=(const RoutineService&) = delete;
~RoutineService();
void GetAvailableRoutines(
const GetAvailableRoutinesToServiceCallback& callback);
void RunRoutine(const grpc_api::RunRoutineRequest& request,
const RunRoutineToServiceCallback& callback);
void GetRoutineUpdate(
int uuid,
grpc_api::GetRoutineUpdateRequest::Command command,
bool include_output,
const GetRoutineUpdateRequestToServiceCallback& callback);
private:
// Forwards and wraps the result of a GetAvailableRoutines call into a gRPC
// response.
void ForwardGetAvailableRoutinesResponse(
size_t callback_key,
const std::vector<chromeos::cros_healthd::mojom::DiagnosticRoutineEnum>&
mojo_routines);
// Forwards and wraps the result of a RunRoutine call into a gRPC response.
void ForwardRunRoutineResponse(
size_t callback_key,
chromeos::cros_healthd::mojom::RunRoutineResponsePtr response);
// Forwards and wraps the result of a GetRoutineUpdate call into a gRPC
// response.
void ForwardGetRoutineUpdateResponse(
size_t callback_key,
chromeos::cros_healthd::mojom::RoutineUpdatePtr response);
// Binds |service_ptr_| to an implementation of CrosHealthdDiagnosticsService,
// if it is not already bound. Returns false if wilco_dtc_supportd's mojo
// service is not yet running and the binding cannot be attempted.
bool BindCrosHealthdDiagnosticsServiceIfNeeded();
// Disconnect handler called if the mojo connection to cros_healthd is lost.
void OnDisconnect();
// Runs all in flight callbacks.
void RunInFlightCallbacks();
// Unowned. Should outlive this instance.
Delegate* delegate_ = nullptr;
// Mojo interface to the CrosHealthdDiagnosticsService endpoint.
//
// In production this interface is implemented by the cros_healthd process.
chromeos::cros_healthd::mojom::CrosHealthdDiagnosticsServicePtr service_ptr_;
// The following three maps each hold in flight callbacks to |service_ptr_|.
// In case the remote mojo endpoint closes while there are any in flight
// callbacks, the disconnect handler will call those callbacks with error
// responses. This allows wilco_dtc_supportd to remain responsive if
// cros_healthd dies.
std::unordered_map<size_t, GetAvailableRoutinesToServiceCallback>
get_available_routines_callbacks_;
std::unordered_map<size_t, RunRoutineToServiceCallback>
run_routine_callbacks_;
// This map needs to also store the uuids, so the callbacks can be run from
// inside the disconnect handler, which otherwise doesn't have access to the
// uuid.
std::unordered_map<size_t,
std::pair<int, GetRoutineUpdateRequestToServiceCallback>>
get_routine_update_callbacks_;
// Generators for the keys used in the in flight callback maps. Note that our
// generation is very simple - just increment the appropriate generator when
// a call is dispatched to cros_healthd. Since the maps are only tracking
// callbacks which are in flight, we don't anticipate having very many stored
// at a time, and there should never be collisions if size_t wraps back
// around to zero. If a collision were to happen, wilco_dtc_supportd would
// just restart.
size_t next_get_available_routines_key_ = 0;
size_t next_run_routine_key_ = 0;
size_t next_get_routine_update_key_ = 0;
// Must be the last class member.
base::WeakPtrFactory<RoutineService> weak_ptr_factory_{this};
};
} // namespace diagnostics
#endif // DIAGNOSTICS_WILCO_DTC_SUPPORTD_ROUTINE_SERVICE_H_