blob: 17c628ad8622605b8a473c89c408de8a1da0ac85 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_ENTERPRISE_COMPANION_ENTERPRISE_COMPANION_STATUS_H_
#define CHROME_ENTERPRISE_COMPANION_ENTERPRISE_COMPANION_STATUS_H_
#include <cstdint>
#include <ostream>
#include <string>
#include <utility>
#include <variant>
#include "base/functional/overloaded.h"
#include "chrome/enterprise_companion/mojom/enterprise_companion.mojom.h"
#include "chrome/enterprise_companion/proto/enterprise_companion_event.pb.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/cloud_policy_validator.h"
namespace enterprise_companion {
// Errors defined by the enterprise companion app. Ordinals are transmitted
// across IPC and network boundaries. Entries must not be removed or reordered.
enum class ApplicationError {
// An action failed due to the client not being registered.
kRegistrationPreconditionFailed,
// DMStorage reports that it is not capable of persisting policies.
kPolicyPersistenceImpossible,
// DMStorage failed to persist the policies.
kPolicyPersistenceFailed,
// The global singleton lock could not be acquired.
kCannotAcquireLock,
// An IPC connection could not be established.
kMojoConnectionFailed,
// Installation failed.
kInstallationFailed,
// The IPC caller is not allowed to perform the requested action.
kIpcCallerNotAllowed,
};
// Represents an error which was deserialized from an external source (e.g.
// across an IPC or network boundary). The error may not be known to this
// version of the application.
struct PersistedError {
PersistedError(int space, int code, const std::string& description);
PersistedError(const PersistedError&);
PersistedError(PersistedError&&);
~PersistedError();
PersistedError& operator=(const PersistedError&);
PersistedError& operator=(PersistedError&&);
// The error space, as defined by `EnterpriseCompanionStatus`.
int space;
// The error code, as defined by `EnterpriseCompanionStatus`.
int code;
// A human readable description of the error.
std::string description;
auto operator<=>(const PersistedError& other) const = default;
};
// Canonical view of statuses used across the application.
class EnterpriseCompanionStatus {
public:
using Ok = std::monostate;
using PosixErrno = int;
// The indices of the underlying variant are used by this implementation and
// are transmitted across RPC boundaries. Existing entries should not be
// reordered.
using StatusVariant = std::variant<Ok,
policy::DeviceManagementStatus,
policy::CloudPolicyValidatorBase::Status,
ApplicationError,
PersistedError,
PosixErrno>;
EnterpriseCompanionStatus() = delete;
EnterpriseCompanionStatus(const EnterpriseCompanionStatus&);
~EnterpriseCompanionStatus();
// Constructs an `Ok` status.
static EnterpriseCompanionStatus Success() {
return EnterpriseCompanionStatus(Ok());
}
bool ok() const { return std::holds_alternative<Ok>(status_variant_); }
// Indicates the status space for the code. As an implementation detail, the
// space is the index of the code's type within `StatusVariant`.
int space() const {
if (const PersistedError* deserialized_error =
std::get_if<PersistedError>(&status_variant_)) {
return deserialized_error->space;
} else {
return status_variant_.index();
}
}
int code() const {
return std::visit(
base::Overloaded{[](std::monostate) { return 0; },
[](const PersistedError& error) { return error.code; },
[](auto&& x) { return static_cast<int>(x); }},
status_variant_);
}
std::string description() const;
mojom::StatusPtr ToMojomStatus() const {
return mojom::Status::New(space(), code(), description());
}
proto::Status ToProtoStatus() const {
proto::Status status;
status.set_space(space());
status.set_code(code());
return status;
}
static EnterpriseCompanionStatus FromMojomStatus(mojom::StatusPtr status) {
return status->code == 0 || status->space == 0
? Success()
: EnterpriseCompanionStatus(StatusVariant(PersistedError(
status->space, status->code, status->description)));
}
bool operator==(const EnterpriseCompanionStatus& other) const {
return space() == other.space() && code() == other.code();
}
// policy::DeviceManagementStatus:
static EnterpriseCompanionStatus FromDeviceManagementStatus(
policy::DeviceManagementStatus status) {
return status == policy::DM_STATUS_SUCCESS ? Success() : From<1>(status);
}
bool EqualsDeviceManagementStatus(
policy::DeviceManagementStatus other) const {
return operator==(From<1>(other));
}
// policy::CloudPolicyValidatorBase::Status:
static EnterpriseCompanionStatus FromCloudPolicyValidationResult(
policy::CloudPolicyValidatorBase::Status status) {
return status == policy::CloudPolicyValidatorBase::VALIDATION_OK
? Success()
: From<2>(status);
}
bool EqualsCloudPolicyValidationResult(
policy::CloudPolicyValidatorBase::Status other) const {
return operator==(From<2>(other));
}
// ApplicationError:
explicit EnterpriseCompanionStatus(ApplicationError error);
bool EqualsApplicationError(ApplicationError other) const {
return operator==(From<3>(other));
}
// PosixErrno:
static EnterpriseCompanionStatus FromPosixErrno(PosixErrno error) {
return From<5>(error);
}
bool EqualsPosixErrno(PosixErrno other) const {
return operator==(From<5>(other));
}
private:
StatusVariant status_variant_;
explicit EnterpriseCompanionStatus(StatusVariant status_variant);
template <size_t I, typename T>
static EnterpriseCompanionStatus From(T&& status) {
return EnterpriseCompanionStatus(
StatusVariant(std::in_place_index_t<I>(), std::forward<T>(status)));
}
};
// A general-purpose callback type for operations that produce an
// EnterpriseCompanionStatus.
using StatusCallback =
base::OnceCallback<void(const EnterpriseCompanionStatus&)>;
} // namespace enterprise_companion
#endif // CHROME_ENTERPRISE_COMPANION_ENTERPRISE_COMPANION_STATUS_H_