// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/extensions/telemetry/api/routines/diagnostic_routine_converters.h"
#include <cstdint>
#include <optional>
#include <vector>
#include "base/notreached.h"
#include "base/uuid.h"
#include "chrome/common/chromeos/extensions/api/diagnostics.h"
#include "chromeos/crosapi/mojom/telemetry_diagnostic_routine_service.mojom.h"
namespace chromeos::converters::routines {
namespace {
namespace cx_diag = api::os_diagnostics;
namespace crosapi = ::crosapi::mojom;
std::optional<cx_diag::RoutineFinishedDetailUnion> ConvertRoutineDetailUnionPtr(
crosapi::TelemetryDiagnosticRoutineDetailPtr input) {
if (input.is_null()) {
return std::nullopt;
}
cx_diag::RoutineFinishedDetailUnion detail;
switch (input->which()) {
case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kUnrecognizedArgument:
LOG(WARNING) << "Got unknown routine detail";
return std::nullopt;
case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kMemory:
detail.memory = ConvertPtr(std::move(input->get_memory()));
return detail;
case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kVolumeButton:
// This member type in the union is kept only for backward compatibility.
// There is no such a field in the web IDL definition.
return std::nullopt;
case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kFan:
detail.fan = ConvertPtr(std::move(input->get_fan()));
return detail;
case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kNetworkBandwidth:
detail.network_bandwidth =
ConvertPtr(std::move(input->get_network_bandwidth()));
return detail;
case crosapi::TelemetryDiagnosticRoutineDetail::Tag::kCameraFrameAnalysis:
detail.camera_frame_analysis =
ConvertPtr(std::move(input->get_camera_frame_analysis()));
return detail;
}
}
std::optional<cx_diag::RoutineRunningInfoUnion>
ConvertRoutineRunningInfoUnionPtr(
crosapi::TelemetryDiagnosticRoutineRunningInfoPtr input) {
if (input.is_null()) {
return std::nullopt;
}
cx_diag::RoutineRunningInfoUnion info;
switch (input->which()) {
case crosapi::TelemetryDiagnosticRoutineRunningInfo::Tag::
kUnrecognizedArgument:
LOG(WARNING) << "Got unknown routine running info";
return std::nullopt;
case crosapi::TelemetryDiagnosticRoutineRunningInfo::Tag::kNetworkBandwidth:
info.network_bandwidth =
ConvertPtr(std::move(input->get_network_bandwidth()));
return info;
}
}
} // namespace
namespace unchecked {
cx_diag::RoutineInitializedInfo UncheckedConvertPtr(
crosapi::TelemetryDiagnosticRoutineStateInitializedPtr input,
base::Uuid uuid) {
cx_diag::RoutineInitializedInfo result;
result.uuid = uuid.AsLowercaseString();
return result;
}
cx_diag::RoutineRunningInfo UncheckedConvertPtr(
crosapi::TelemetryDiagnosticRoutineStateRunningPtr input,
base::Uuid uuid,
uint32_t percentage) {
cx_diag::RoutineRunningInfo result;
result.uuid = uuid.AsLowercaseString();
result.percentage = percentage;
result.info = ConvertRoutineRunningInfoUnionPtr(std::move(input->info));
return result;
}
cx_diag::NetworkBandwidthRoutineRunningInfo UncheckedConvertPtr(
crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfoPtr input) {
cx_diag::NetworkBandwidthRoutineRunningInfo info;
info.type = Convert(input->type);
info.speed_kbps = input->speed_kbps;
return info;
}
cx_diag::RoutineInquiryUnion UncheckedConvertPtr(
crosapi::TelemetryDiagnosticRoutineInquiryPtr input) {
cx_diag::RoutineInquiryUnion inquiry;
switch (input->which()) {
case crosapi::TelemetryDiagnosticRoutineInquiry::Tag::kUnrecognizedInquiry:
// This indicates version skew on Mojo interfaces, which is unexpected.
// Return an empty union as a safeguard.
break;
case crosapi::TelemetryDiagnosticRoutineInquiry::Tag::kCheckLedLitUpState:
inquiry.check_led_lit_up_state = cx_diag::CheckLedLitUpStateInquiry();
break;
case crosapi::TelemetryDiagnosticRoutineInquiry::Tag::
kCheckKeyboardBacklightState:
inquiry.check_keyboard_backlight_state =
cx_diag::CheckKeyboardBacklightStateInquiry();
break;
}
return inquiry;
}
cx_diag::RoutineInteractionUnion UncheckedConvertPtr(
crosapi::TelemetryDiagnosticRoutineInteractionPtr input) {
cx_diag::RoutineInteractionUnion interaction;
switch (input->which()) {
case crosapi::TelemetryDiagnosticRoutineInteraction::Tag::
kUnrecognizedInteraction:
// This indicates version skew on Mojo interfaces, which is unexpected.
// Return an empty union as a safeguard.
break;
case crosapi::TelemetryDiagnosticRoutineInteraction::Tag::kInquiry:
interaction.inquiry = ConvertPtr(std::move(input->get_inquiry()));
break;
}
return interaction;
}
cx_diag::RoutineWaitingInfo UncheckedConvertPtr(
crosapi::TelemetryDiagnosticRoutineStateWaitingPtr input,
base::Uuid uuid,
uint32_t percentage) {
cx_diag::RoutineWaitingInfo result;
result.uuid = uuid.AsLowercaseString();
result.reason = Convert(input->reason);
if (input->interaction) {
result.interaction = ConvertPtr(std::move(input->interaction));
}
result.message = input->message;
result.percentage = percentage;
return result;
}
cx_diag::MemtesterResult UncheckedConvertPtr(
crosapi::TelemetryDiagnosticMemtesterResultPtr input) {
cx_diag::MemtesterResult result;
result.passed_items = ConvertVector(input->passed_items);
result.failed_items = ConvertVector(input->failed_items);
return result;
}
cx_diag::LegacyMemoryRoutineFinishedInfo UncheckedConvertPtr(
crosapi::TelemetryDiagnosticMemoryRoutineDetailPtr input,
base::Uuid uuid,
bool has_passed) {
cx_diag::LegacyMemoryRoutineFinishedInfo result;
result.uuid = uuid.AsLowercaseString();
result.has_passed = has_passed;
// Construct the non-legacy detail to ensure the content is the same between
// the legacy and the non-legacy ones.
cx_diag::MemoryRoutineFinishedDetail detail =
UncheckedConvertPtr(std::move(input));
result.bytes_tested = std::move(detail.bytes_tested);
if (detail.result) {
result.result = cx_diag::LegacyMemtesterResult();
result.result->passed_items = std::move(detail.result->passed_items);
result.result->failed_items = std::move(detail.result->failed_items);
}
return result;
}
cx_diag::LegacyVolumeButtonRoutineFinishedInfo UncheckedConvertPtr(
crosapi::TelemetryDiagnosticVolumeButtonRoutineDetailPtr input,
base::Uuid uuid,
bool has_passed) {
cx_diag::LegacyVolumeButtonRoutineFinishedInfo result;
result.uuid = uuid.AsLowercaseString();
result.has_passed = has_passed;
return result;
}
cx_diag::LegacyFanRoutineFinishedInfo UncheckedConvertPtr(
crosapi::TelemetryDiagnosticFanRoutineDetailPtr input,
base::Uuid uuid,
bool has_passed) {
cx_diag::LegacyFanRoutineFinishedInfo result;
result.uuid = uuid.AsLowercaseString();
result.has_passed = has_passed;
// Construct the non-legacy detail to ensure the content is the same between
// the legacy and the non-legacy ones.
cx_diag::FanRoutineFinishedDetail detail =
UncheckedConvertPtr(std::move(input));
result.passed_fan_ids = std::move(detail.passed_fan_ids);
result.failed_fan_ids = std::move(detail.failed_fan_ids);
result.fan_count_status = std::move(detail.fan_count_status);
return result;
}
cx_diag::MemoryRoutineFinishedDetail UncheckedConvertPtr(
crosapi::TelemetryDiagnosticMemoryRoutineDetailPtr input) {
cx_diag::MemoryRoutineFinishedDetail result;
result.bytes_tested = input->bytes_tested;
result.result = ConvertPtr(std::move(input->result));
return result;
}
cx_diag::FanRoutineFinishedDetail UncheckedConvertPtr(
crosapi::TelemetryDiagnosticFanRoutineDetailPtr input) {
cx_diag::FanRoutineFinishedDetail result;
std::vector<int> passed_fan_ids = {};
for (const auto& passed_fan_id : input->passed_fan_ids) {
passed_fan_ids.push_back(passed_fan_id);
}
result.passed_fan_ids = passed_fan_ids;
std::vector<int> failed_fan_ids = {};
for (const auto& failed_fan_id : input->failed_fan_ids) {
failed_fan_ids.push_back(failed_fan_id);
}
result.failed_fan_ids = failed_fan_ids;
result.fan_count_status = Convert(input->fan_count_status);
return result;
}
cx_diag::NetworkBandwidthRoutineFinishedDetail UncheckedConvertPtr(
crosapi::TelemetryDiagnosticNetworkBandwidthRoutineDetailPtr input) {
cx_diag::NetworkBandwidthRoutineFinishedDetail result;
result.download_speed_kbps = input->download_speed_kbps;
result.upload_speed_kbps = input->upload_speed_kbps;
return result;
}
cx_diag::CameraFrameAnalysisRoutineFinishedDetail UncheckedConvertPtr(
crosapi::TelemetryDiagnosticCameraFrameAnalysisRoutineDetailPtr input) {
cx_diag::CameraFrameAnalysisRoutineFinishedDetail result;
result.issue = Convert(input->issue);
result.privacy_shutter_open_test = Convert(input->privacy_shutter_open_test);
result.lens_not_dirty_test = Convert(input->lens_not_dirty_test);
return result;
}
cx_diag::RoutineFinishedInfo UncheckedConvertPtr(
crosapi::TelemetryDiagnosticRoutineStateFinishedPtr input,
base::Uuid uuid,
bool has_passed) {
cx_diag::RoutineFinishedInfo result;
result.uuid = uuid.AsLowercaseString();
result.has_passed = has_passed;
result.detail = ConvertRoutineDetailUnionPtr(std::move(input->detail));
return result;
}
} // namespace unchecked
cx_diag::ExceptionReason Convert(
crosapi::TelemetryExtensionException::Reason input) {
switch (input) {
case crosapi::TelemetryExtensionException::Reason::kUnmappedEnumField:
return cx_diag::ExceptionReason::kUnknown;
case crosapi::TelemetryExtensionException::Reason::
kMojoDisconnectWithoutReason:
return cx_diag::ExceptionReason::kUnknown;
case crosapi::TelemetryExtensionException::Reason::kUnexpected:
return cx_diag::ExceptionReason::kUnexpected;
case crosapi::TelemetryExtensionException::Reason::kUnsupported:
return cx_diag::ExceptionReason::kUnsupported;
case crosapi::TelemetryExtensionException::Reason::kCameraFrontendNotOpened:
return cx_diag::ExceptionReason::kCameraFrontendNotOpened;
}
NOTREACHED_IN_MIGRATION();
}
cx_diag::RoutineWaitingReason Convert(
crosapi::TelemetryDiagnosticRoutineStateWaiting::Reason input) {
switch (input) {
case crosapi::TelemetryDiagnosticRoutineStateWaiting::Reason::
kUnmappedEnumField:
return cx_diag::RoutineWaitingReason::kNone;
case crosapi::TelemetryDiagnosticRoutineStateWaiting::Reason::
kWaitingToBeScheduled:
return cx_diag::RoutineWaitingReason::kWaitingToBeScheduled;
case crosapi::TelemetryDiagnosticRoutineStateWaiting::Reason::
kWaitingForInteraction:
return cx_diag::RoutineWaitingReason::kWaitingForInteraction;
}
NOTREACHED();
}
cx_diag::MemtesterTestItemEnum Convert(
crosapi::TelemetryDiagnosticMemtesterTestItemEnum input) {
switch (input) {
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kUnmappedEnumField:
return cx_diag::MemtesterTestItemEnum::kUnknown;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kUnknown:
return cx_diag::MemtesterTestItemEnum::kUnknown;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kStuckAddress:
return cx_diag::MemtesterTestItemEnum::kStuckAddress;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kCompareAND:
return cx_diag::MemtesterTestItemEnum::kCompareAnd;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kCompareDIV:
return cx_diag::MemtesterTestItemEnum::kCompareDiv;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kCompareMUL:
return cx_diag::MemtesterTestItemEnum::kCompareMul;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kCompareOR:
return cx_diag::MemtesterTestItemEnum::kCompareOr;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kCompareSUB:
return cx_diag::MemtesterTestItemEnum::kCompareSub;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kCompareXOR:
return cx_diag::MemtesterTestItemEnum::kCompareXor;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::
kSequentialIncrement:
return cx_diag::MemtesterTestItemEnum::kSequentialIncrement;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kBitFlip:
return cx_diag::MemtesterTestItemEnum::kBitFlip;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kBitSpread:
return cx_diag::MemtesterTestItemEnum::kBitSpread;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kBlockSequential:
return cx_diag::MemtesterTestItemEnum::kBlockSequential;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kCheckerboard:
return cx_diag::MemtesterTestItemEnum::kCheckerboard;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kRandomValue:
return cx_diag::MemtesterTestItemEnum::kRandomValue;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kSolidBits:
return cx_diag::MemtesterTestItemEnum::kSolidBits;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kWalkingOnes:
return cx_diag::MemtesterTestItemEnum::kWalkingOnes;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kWalkingZeroes:
return cx_diag::MemtesterTestItemEnum::kWalkingZeroes;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kEightBitWrites:
return cx_diag::MemtesterTestItemEnum::kEightBitWrites;
case crosapi::TelemetryDiagnosticMemtesterTestItemEnum::kSixteenBitWrites:
return cx_diag::MemtesterTestItemEnum::kSixteenBitWrites;
}
NOTREACHED();
}
cx_diag::HardwarePresenceStatus Convert(
crosapi::TelemetryDiagnosticHardwarePresenceStatus input) {
switch (input) {
case crosapi::TelemetryDiagnosticHardwarePresenceStatus::kUnmappedEnumField:
return cx_diag::HardwarePresenceStatus::kNone;
case crosapi::TelemetryDiagnosticHardwarePresenceStatus::kMatched:
return cx_diag::HardwarePresenceStatus::kMatched;
case crosapi::TelemetryDiagnosticHardwarePresenceStatus::kNotMatched:
return cx_diag::HardwarePresenceStatus::kNotMatched;
case crosapi::TelemetryDiagnosticHardwarePresenceStatus::kNotConfigured:
return cx_diag::HardwarePresenceStatus::kNotConfigured;
}
NOTREACHED();
}
cx_diag::NetworkBandwidthRoutineRunningType Convert(
crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type
input) {
switch (input) {
case crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type::
kUnmappedEnumField:
return cx_diag::NetworkBandwidthRoutineRunningType::kNone;
case crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type::
kDownload:
return cx_diag::NetworkBandwidthRoutineRunningType::kDownload;
case crosapi::TelemetryDiagnosticNetworkBandwidthRoutineRunningInfo::Type::
kUpload:
return cx_diag::NetworkBandwidthRoutineRunningType::kUpload;
}
NOTREACHED();
}
cx_diag::CameraFrameAnalysisIssue Convert(
crosapi::TelemetryDiagnosticCameraFrameAnalysisRoutineDetail::Issue input) {
switch (input) {
case crosapi::TelemetryDiagnosticCameraFrameAnalysisRoutineDetail::Issue::
kUnmappedEnumField:
return cx_diag::CameraFrameAnalysisIssue::kNone;
case crosapi::TelemetryDiagnosticCameraFrameAnalysisRoutineDetail::Issue::
kNone:
return cx_diag::CameraFrameAnalysisIssue::kNoIssue;
case crosapi::TelemetryDiagnosticCameraFrameAnalysisRoutineDetail::Issue::
kCameraServiceNotAvailable:
return cx_diag::CameraFrameAnalysisIssue::kCameraServiceNotAvailable;
case crosapi::TelemetryDiagnosticCameraFrameAnalysisRoutineDetail::Issue::
kBlockedByPrivacyShutter:
return cx_diag::CameraFrameAnalysisIssue::kBlockedByPrivacyShutter;
case crosapi::TelemetryDiagnosticCameraFrameAnalysisRoutineDetail::Issue::
kLensAreDirty:
return cx_diag::CameraFrameAnalysisIssue::kLensAreDirty;
}
NOTREACHED();
}
cx_diag::CameraSubtestResult Convert(
crosapi::TelemetryDiagnosticCameraSubtestResult input) {
switch (input) {
case crosapi::TelemetryDiagnosticCameraSubtestResult::kUnmappedEnumField:
return cx_diag::CameraSubtestResult::kNone;
case crosapi::TelemetryDiagnosticCameraSubtestResult::kNotRun:
return cx_diag::CameraSubtestResult::kNotRun;
case crosapi::TelemetryDiagnosticCameraSubtestResult::kPassed:
return cx_diag::CameraSubtestResult::kPassed;
case crosapi::TelemetryDiagnosticCameraSubtestResult::kFailed:
return cx_diag::CameraSubtestResult::kFailed;
}
NOTREACHED();
}
} // namespace chromeos::converters::routines