Commit ce0e5055 authored by Andrei-Laurențiu Olteanu's avatar Andrei-Laurențiu Olteanu Committed by Commit Bot

[Telemetry SWX] Add GetRoutineUpdate

Add mojom interface for GetRoutineUpdate.

Add converters for RoutineUpdate structures in privileged context.

Add implementation of GetRoutineUpdate from trusted to untrusted.

Bug: b:162051831

Change-Id: I822406a3a09d612f256b3fd4dc6ff35805165f13
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2329750Reviewed-by: default avatarGiovanni Ortuño Urquidi <ortuno@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarMahmoud Gawad <mgawad@google.com>
Reviewed-by: default avatarOleh Lamzin <lamzin@google.com>
Commit-Queue: Laurențiu Olteanu <lolteanu@google.com>
Cr-Commit-Position: refs/heads/master@{#799527}
parent 2c50ce04
......@@ -40,6 +40,7 @@ source_set("telemetry_extension_ui") {
source_set("unit_tests") {
testonly = true
sources = [
"diagnostics_service_converters_unittest.cc",
"probe_service_converters_unittest.cc",
"probe_service_unittest.cc",
]
......
......@@ -48,4 +48,21 @@ void DiagnosticsService::GetAvailableRoutines(
std::move(callback)));
}
void DiagnosticsService::GetRoutineUpdate(
int32_t id,
health::mojom::DiagnosticRoutineCommandEnum command,
bool include_output,
GetRoutineUpdateCallback callback) {
GetService()->GetRoutineUpdate(
id, diagnostics_service_converters::Convert(command), include_output,
base::BindOnce(
[](health::mojom::DiagnosticsService::GetRoutineUpdateCallback
callback,
cros_healthd::mojom::RoutineUpdatePtr ptr) {
std::move(callback).Run(
diagnostics_service_converters::ConvertPtr(std::move(ptr)));
},
std::move(callback)));
}
} // namespace chromeos
......@@ -27,6 +27,10 @@ class DiagnosticsService : public health::mojom::DiagnosticsService {
private:
void GetAvailableRoutines(GetAvailableRoutinesCallback callback) override;
void GetRoutineUpdate(int32_t id,
health::mojom::DiagnosticRoutineCommandEnum command,
bool include_output,
GetRoutineUpdateCallback callback) override;
// Ensures that |service_| created and connected to the
// CrosHealthdProbeService.
......
......@@ -12,7 +12,85 @@
namespace chromeos {
namespace diagnostics_service_converters {
namespace {
namespace unchecked {
health::mojom::RoutineUpdatePtr UncheckedConvertPtr(
cros_healthd::mojom::RoutineUpdatePtr input) {
return health::mojom::RoutineUpdate::New(
input->progress_percent, Convert(std::move(input->output)),
ConvertPtr(std::move(input->routine_update_union)));
}
health::mojom::RoutineUpdateUnionPtr UncheckedConvertPtr(
cros_healthd::mojom::RoutineUpdateUnionPtr input) {
switch (input->which()) {
case cros_healthd::mojom::RoutineUpdateUnion::Tag::INTERACTIVE_UPDATE:
return health::mojom::RoutineUpdateUnion::NewInteractiveUpdate(
ConvertPtr(std::move(input->get_interactive_update())));
case cros_healthd::mojom::RoutineUpdateUnion::Tag::NONINTERACTIVE_UPDATE:
return health::mojom::RoutineUpdateUnion::NewNoninteractiveUpdate(
ConvertPtr(std::move(input->get_noninteractive_update())));
}
}
health::mojom::InteractiveRoutineUpdatePtr UncheckedConvertPtr(
cros_healthd::mojom::InteractiveRoutineUpdatePtr input) {
return health::mojom::InteractiveRoutineUpdate::New(
Convert(input->user_message));
}
health::mojom::NonInteractiveRoutineUpdatePtr UncheckedConvertPtr(
cros_healthd::mojom::NonInteractiveRoutineUpdatePtr input) {
return health::mojom::NonInteractiveRoutineUpdate::New(
Convert(input->status), std::move(input->status_message));
}
} // namespace unchecked
health::mojom::DiagnosticRoutineStatusEnum Convert(
cros_healthd::mojom::DiagnosticRoutineStatusEnum input) {
switch (input) {
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kReady:
return health::mojom::DiagnosticRoutineStatusEnum::kReady;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kRunning:
return health::mojom::DiagnosticRoutineStatusEnum::kRunning;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kWaiting:
return health::mojom::DiagnosticRoutineStatusEnum::kWaiting;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kPassed:
return health::mojom::DiagnosticRoutineStatusEnum::kPassed;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kFailed:
return health::mojom::DiagnosticRoutineStatusEnum::kFailed;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kError:
return health::mojom::DiagnosticRoutineStatusEnum::kError;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kCancelled:
return health::mojom::DiagnosticRoutineStatusEnum::kCancelled;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kFailedToStart:
return health::mojom::DiagnosticRoutineStatusEnum::kFailedToStart;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kRemoved:
return health::mojom::DiagnosticRoutineStatusEnum::kRemoved;
case cros_healthd::mojom::DiagnosticRoutineStatusEnum::kCancelling:
return health::mojom::DiagnosticRoutineStatusEnum::kCancelling;
}
NOTREACHED();
return static_cast<health::mojom::DiagnosticRoutineStatusEnum>(
static_cast<int>(health::mojom::DiagnosticRoutineStatusEnum::kMaxValue) +
1);
}
health::mojom::DiagnosticRoutineUserMessageEnum Convert(
cros_healthd::mojom::DiagnosticRoutineUserMessageEnum input) {
switch (input) {
case cros_healthd::mojom::DiagnosticRoutineUserMessageEnum::kUnplugACPower:
return health::mojom::DiagnosticRoutineUserMessageEnum::kUnplugACPower;
case cros_healthd::mojom::DiagnosticRoutineUserMessageEnum::kPlugInACPower:
return health::mojom::DiagnosticRoutineUserMessageEnum::kPlugInACPower;
}
NOTREACHED();
return static_cast<health::mojom::DiagnosticRoutineUserMessageEnum>(
static_cast<int>(
health::mojom::DiagnosticRoutineUserMessageEnum::kMaxValue) +
1);
}
base::Optional<health::mojom::DiagnosticRoutineEnum> Convert(
cros_healthd::mojom::DiagnosticRoutineEnum input) {
......@@ -48,7 +126,29 @@ base::Optional<health::mojom::DiagnosticRoutineEnum> Convert(
return base::nullopt;
}
} // namespace
std::string Convert(mojo::ScopedHandle handle) {
// TODO (b:162051831): Read from handle and put contents in a string
return std::string();
}
cros_healthd::mojom::DiagnosticRoutineCommandEnum Convert(
health::mojom::DiagnosticRoutineCommandEnum input) {
switch (input) {
case health::mojom::DiagnosticRoutineCommandEnum::kContinue:
return cros_healthd::mojom::DiagnosticRoutineCommandEnum::kContinue;
case health::mojom::DiagnosticRoutineCommandEnum::kCancel:
return cros_healthd::mojom::DiagnosticRoutineCommandEnum::kCancel;
case health::mojom::DiagnosticRoutineCommandEnum::kGetStatus:
return cros_healthd::mojom::DiagnosticRoutineCommandEnum::kGetStatus;
case health::mojom::DiagnosticRoutineCommandEnum::kRemove:
return cros_healthd::mojom::DiagnosticRoutineCommandEnum::kRemove;
}
NOTREACHED();
return static_cast<cros_healthd::mojom::DiagnosticRoutineCommandEnum>(
static_cast<int>(
cros_healthd::mojom::DiagnosticRoutineCommandEnum::kMaxValue) +
1);
}
std::vector<health::mojom::DiagnosticRoutineEnum> Convert(
const std::vector<cros_healthd::mojom::DiagnosticRoutineEnum>& input) {
......
......@@ -9,10 +9,13 @@
#error Diagnostics service should only be included in unofficial builds.
#endif
#include <string>
#include <utility>
#include <vector>
#include "chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom-forward.h"
#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom-forward.h"
#include "mojo/public/cpp/system/handle.h"
namespace chromeos {
namespace diagnostics_service_converters {
......@@ -20,9 +23,42 @@ namespace diagnostics_service_converters {
// This file contains helper functions used by DiagnosticsService to convert its
// types to/from cros_healthd DiagnosticsService types.
namespace unchecked {
health::mojom::RoutineUpdatePtr UncheckedConvertPtr(
cros_healthd::mojom::RoutineUpdatePtr input);
health::mojom::RoutineUpdateUnionPtr UncheckedConvertPtr(
cros_healthd::mojom::RoutineUpdateUnionPtr input);
health::mojom::InteractiveRoutineUpdatePtr UncheckedConvertPtr(
cros_healthd::mojom::InteractiveRoutineUpdatePtr input);
health::mojom::NonInteractiveRoutineUpdatePtr UncheckedConvertPtr(
cros_healthd::mojom::NonInteractiveRoutineUpdatePtr input);
} // namespace unchecked
std::vector<health::mojom::DiagnosticRoutineEnum> Convert(
const std::vector<cros_healthd::mojom::DiagnosticRoutineEnum>& input);
health::mojom::DiagnosticRoutineUserMessageEnum Convert(
cros_healthd::mojom::DiagnosticRoutineUserMessageEnum input);
health::mojom::DiagnosticRoutineStatusEnum Convert(
cros_healthd::mojom::DiagnosticRoutineStatusEnum input);
cros_healthd::mojom::DiagnosticRoutineCommandEnum Convert(
health::mojom::DiagnosticRoutineCommandEnum input);
std::string Convert(mojo::ScopedHandle handle);
template <class InputT>
auto ConvertPtr(InputT input) {
return (!input.is_null()) ? unchecked::UncheckedConvertPtr(std::move(input))
: nullptr;
}
} // namespace diagnostics_service_converters
} // namespace chromeos
......
// Copyright 2020 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/components/telemetry_extension_ui/diagnostics_service_converters.h"
#include "chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom.h"
#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_diagnostics.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace diagnostics_service_converters {
TEST(DiagnosticsServiceConvertersTest, ConvertDiagnosticRoutineStatusEnum) {
namespace cros_healthd = ::chromeos::cros_healthd::mojom;
namespace health = ::chromeos::health::mojom;
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kReady),
health::DiagnosticRoutineStatusEnum::kReady);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kRunning),
health::DiagnosticRoutineStatusEnum::kRunning);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kWaiting),
health::DiagnosticRoutineStatusEnum::kWaiting);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kPassed),
health::DiagnosticRoutineStatusEnum::kPassed);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kFailed),
health::DiagnosticRoutineStatusEnum::kFailed);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kError),
health::DiagnosticRoutineStatusEnum::kError);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kCancelled),
health::DiagnosticRoutineStatusEnum::kCancelled);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kFailedToStart),
health::DiagnosticRoutineStatusEnum::kFailedToStart);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kRemoved),
health::DiagnosticRoutineStatusEnum::kRemoved);
EXPECT_EQ(Convert(cros_healthd::DiagnosticRoutineStatusEnum::kCancelling),
health::DiagnosticRoutineStatusEnum::kCancelling);
}
TEST(DiagnosticsServiceConvertersTest,
ConvertDiagnosticRoutineUserMessageEnum) {
namespace cros_healthd = ::chromeos::cros_healthd::mojom;
namespace health = ::chromeos::health::mojom;
EXPECT_EQ(
Convert(cros_healthd::DiagnosticRoutineUserMessageEnum::kUnplugACPower),
health::DiagnosticRoutineUserMessageEnum::kUnplugACPower);
EXPECT_EQ(
Convert(cros_healthd::DiagnosticRoutineUserMessageEnum::kPlugInACPower),
health::DiagnosticRoutineUserMessageEnum::kPlugInACPower);
}
TEST(DiagnosticsServiceConvertersTest, ConvertDiagnosticRoutineCommandEnum) {
namespace cros_healthd = ::chromeos::cros_healthd::mojom;
namespace health = ::chromeos::health::mojom;
EXPECT_EQ(Convert(health::DiagnosticRoutineCommandEnum::kContinue),
cros_healthd::DiagnosticRoutineCommandEnum::kContinue);
EXPECT_EQ(Convert(health::DiagnosticRoutineCommandEnum::kCancel),
cros_healthd::DiagnosticRoutineCommandEnum::kCancel);
EXPECT_EQ(Convert(health::DiagnosticRoutineCommandEnum::kGetStatus),
cros_healthd::DiagnosticRoutineCommandEnum::kGetStatus);
EXPECT_EQ(Convert(health::DiagnosticRoutineCommandEnum::kRemove),
cros_healthd::DiagnosticRoutineCommandEnum::kRemove);
}
} // namespace diagnostics_service_converters
} // namespace chromeos
......@@ -22,6 +22,24 @@ interface DiagnosticsService {
// Returns an array of all diagnostic routines that the platform supports.
GetAvailableRoutines()
=> (array<DiagnosticRoutineEnum> available_routines);
// Sends commands to an existing routine. Also returns status information for
// the routine.
//
// The request:
// * |id| - specifies which routine the command will be sent to. This must be
// the same id that was returned from the RunSomeRoutine function
// call used to create the routine.
// * |command| - command to send the routine.
// * |include_output| - whether or not the response should include any output
// accumulated from the routine.
//
// The response:
// * |routine_update| - status information for the specified routine. See
// cros_healthd_diagnostics.mojom for the structure.
GetRoutineUpdate(int32 id, DiagnosticRoutineCommandEnum command,
bool include_output)
=> (RoutineUpdate routine_update);
};
// Enumeration of each of the diagnostics routines the platform may support.
......@@ -41,3 +59,77 @@ enum DiagnosticRoutineEnum {
kPrimeSearch = 11,
kBatteryDischarge = 12,
};
// Enumeration of each of the possible statuses for a diagnostics routine.
[Extensible]
enum DiagnosticRoutineStatusEnum {
kReady = 0, // Routine is ready to start.
kRunning = 1, // Routine is currently running.
kWaiting = 2, // Routine needs user input to continue.
kPassed = 3, // Routine completed and passed.
kFailed = 4, // Routine completed and failed.
kError = 5, // An error prevented the routine from completing.
kCancelled = 6, // Routine was cancelled before completion. A cancelled
// routine's information can still be accessed with a
// GetRoutineUpdateRequest.
kFailedToStart = 7, // Routine could not be created.
kRemoved = 8, // Routine has been removed and is no longer valid.
kCancelling = 9, // Routine is in the process of being cancelled.
};
// Enumeration of each of the messages a diagnostics routine can pass back.
// These messages prompt interaction from the user of the routine.
[Extensible]
enum DiagnosticRoutineUserMessageEnum {
kUnplugACPower = 0, // The user needs to unplug the AC power cord.
kPlugInACPower = 1, // The user needs to plug in the AC power cord.
};
// Enumeration of the possible commands to send a diagnostics routine.
[Extensible]
enum DiagnosticRoutineCommandEnum {
kContinue = 0, // Resume a routine that is waiting.
kCancel = 1, // Cancelled routines must still be removed before the routine
// is destroyed.
kGetStatus = 2, // Used to get status but not otherwise control a routine.
kRemove = 3, // All routines which started successfully must be removed,
// otherwise they will persist on the system. This makes sure
// the routine is terminated before removing it.
};
// Status fields specific to interactive routines.
struct InteractiveRoutineUpdate {
// Request for user action. This message should be localized and displayed to
// the user.
DiagnosticRoutineUserMessageEnum user_message;
};
// Status fields specific to noninteractive routines.
struct NonInteractiveRoutineUpdate {
// Current status of the routine.
DiagnosticRoutineStatusEnum status;
// More detailed status - for example, if |status| was kError,
// |status_message| would describe the error encountered, like "failed to
// read file."
string status_message;
};
// Responses will be either interactive or noninteractive.
union RoutineUpdateUnion {
InteractiveRoutineUpdate interactive_update;
NonInteractiveRoutineUpdate noninteractive_update;
};
// Response type for GetRoutineUpdate.
struct RoutineUpdate {
// Percent complete, must be between 0 and 100, inclusive.
uint32 progress_percent;
// Any accumulated output, like logs, from the routine. This field is only
// valid when GetRoutineUpdate (see cros_healthd.mojom) is called with
// include_output = true.
string? output;
// Information specific to the type of response - interactive or
// noninteractive.
RoutineUpdateUnion routine_update_union;
};
......@@ -19,6 +19,7 @@ const dpsl_internal = {};
*/
dpsl_internal.Message = {
DIAGNOSTICS_AVAILABLE_ROUTINES: 'DiagnosticsService.GetAvailableRoutines',
DIAGNOSTICS_ROUTINE_UPDATE: 'DiagnosticsService.GetRoutineUpdate',
PROBE_TELEMETRY_INFO: 'ProbeService.ProbeTelemetryInfo',
};
......@@ -36,6 +37,23 @@ dpsl_internal.DiagnosticsGetAvailableRoutinesRequest;
*/
dpsl_internal.DiagnosticsGetAvailableRoutinesResponse;
/**
* Request message sent by the unprivileged context to the privileged
* context to request a routine update.
* @typedef {{
* routineId: !number,
* command: !string,
* includeOutput: !boolean}}
*/
dpsl_internal.DiagnosticsGetRoutineUpdateRequest;
/**
* Response message sent by the privileged context containing diagnostic
* routine update information.
* @typedef { !Object | !Error }
*/
dpsl_internal.DiagnosticsGetRoutineUpdateResponse;
/**
* Request message sent by the unprivileged context to request the privileged
* context to probe telemetry information
......
......@@ -42,7 +42,7 @@ class DiagnosticsProxy {
* @type { !Map<!chromeos.health.mojom.DiagnosticRoutineEnum, !string> }
* @const
*/
this.routineToEnum_ = new Map([
this.enumToRoutineName_ = new Map([
[routineEnum.kBatteryCapacity, 'battery-capacity'],
[routineEnum.kBatteryHealth, 'battery-health'],
[routineEnum.kUrandom, 'urandom'],
......@@ -58,8 +58,69 @@ class DiagnosticsProxy {
[routineEnum.kBatteryDischarge, 'battery-discharge'],
]);
if (this.routineToEnum_.size != routineEnum.MAX_VALUE + 1) {
throw RangeError('routineToEnum_ does not contain all items from enum!');
if (this.enumToRoutineName_.size !== routineEnum.MAX_VALUE + 1) {
throw RangeError(
'enumToRoutineName_ does not contain all items from enum!');
}
const commandEnum = chromeos.health.mojom.DiagnosticRoutineCommandEnum;
/**
* @type { !Map<!string,
* !chromeos.health.mojom.DiagnosticRoutineCommandEnum> }
* @const
*/
this.commandToEnum_ = new Map([
['continue', commandEnum.kContinue],
['cancel', commandEnum.kCancel],
['get-status', commandEnum.kGetStatus],
['remove', commandEnum.kRemove],
]);
if (this.commandToEnum_.size !== commandEnum.MAX_VALUE + 1) {
throw RangeError('commandToEnum_ does not contain all items from enum!');
}
const statusEnum = chromeos.health.mojom.DiagnosticRoutineStatusEnum;
/**
* @type { !Map<!chromeos.health.mojom.DiagnosticRoutineStatusEnum, !string>
* }
* @const
*/
this.enumToStatus_ = new Map([
[statusEnum.kReady, 'ready'],
[statusEnum.kRunning, 'running'],
[statusEnum.kWaiting, 'waiting'],
[statusEnum.kPassed, 'passed'],
[statusEnum.kFailed, 'failed'],
[statusEnum.kError, 'error'],
[statusEnum.kCancelled, 'cancelled'],
[statusEnum.kFailedToStart, 'failed-to-start'],
[statusEnum.kRemoved, 'removed'],
[statusEnum.kCancelling, 'cancelling'],
]);
if (this.enumToStatus_.size !== statusEnum.MAX_VALUE + 1) {
throw RangeError('enumToStatus_ does not contain all items from enum!');
}
const userMessageEnum =
chromeos.health.mojom.DiagnosticRoutineUserMessageEnum;
/**
* @type { !Map<!chromeos.health.mojom.DiagnosticRoutineUserMessageEnum,
* !string> }
* @const
*/
this.enumToUserMessage_ = new Map([
[userMessageEnum.kUnplugACPower, 'unplug-ac-power'],
[userMessageEnum.kPlugInACPower, 'plug-in-ac-power'],
]);
if (this.enumToUserMessage_.size !== userMessageEnum.MAX_VALUE + 1) {
throw RangeError(
'enumToUserMessage_ does not contain all items from enum!');
}
}
......@@ -69,10 +130,10 @@ class DiagnosticsProxy {
*/
convertRoutines(routines) {
return routines.map((routine) => {
if (!this.routineToEnum_.has(routine)) {
if (!this.enumToRoutineName_.has(routine)) {
throw TypeError(`Diagnostic routine '${routine}' is unknown.`);
}
return this.routineToEnum_.get(routine);
return this.enumToRoutineName_.get(routine);
});
}
......@@ -85,6 +146,113 @@ class DiagnosticsProxy {
await getOrCreateDiagnosticsService().getAvailableRoutines();
return this.convertRoutines(availableRoutines.availableRoutines);
};
/**
* @param { !number } id
* @return { !number }
*/
convertRoutineId(id) {
if (id < -2147483648 || id > 2147483647) {
throw RangeError(`Diagnostic routine id '${id}' is out of int32 range.`);
}
return id;
}
/**
* @param { !string } command
* @return { !chromeos.health.mojom.DiagnosticRoutineCommandEnum }
*/
convertCommandToEnum(command) {
if (!this.commandToEnum_.has(command)) {
throw TypeError(`Diagnostic command '${command}' is unknown.`);
}
return this.commandToEnum_.get(command);
}
/**
* @param { !chromeos.health.mojom.DiagnosticRoutineStatusEnum } status
* @return { !string | null }
*/
convertStatus(status) {
if (!this.enumToStatus_.has(status)) {
return null;
}
return this.enumToStatus_.get(status);
}
/**
* @param { !chromeos.health.mojom.DiagnosticRoutineUserMessageEnum }
* userMessage
* @return { !string | null }
*/
convertUserMessage(userMessage) {
if (!this.enumToUserMessage_.has(userMessage)) {
return null;
}
return this.enumToUserMessage_.get(userMessage);
}
/**
* @param { !chromeos.health.mojom.RoutineUpdate } routineUpdate
* @return { !Object }
*/
convertRoutineUpdate(routineUpdate) {
let result = {
progressPercent: routineUpdate.progressPercent,
output: routineUpdate.output,
routineUpdateUnion: {}
};
const updateUnion = routineUpdate.routineUpdateUnion;
if (typeof updateUnion.noninteractiveUpdate !== 'undefined' &&
updateUnion.noninteractiveUpdate !== null) {
let status = this.convertStatus(updateUnion.noninteractiveUpdate.status);
result.routineUpdateUnion = {
noninteractiveUpdate: {
status: status,
statusMessage: updateUnion.noninteractiveUpdate.statusMessage
}
};
}
if (typeof updateUnion.interactiveUpdate !== 'undefined' &&
updateUnion.interactiveUpdate !== null) {
let message =
this.convertUserMessage(updateUnion.interactiveUpdate.userMessage);
result.routineUpdateUnion = {interactiveUpdate: {userMessage: message}};
}
return result;
}
/**
* Runs a command on a routine.
* @param { !Object } message
* @return { !Promise<dpsl_internal.DiagnosticsGetRoutineUpdateResponse> }
*/
async handleGetRoutineUpdate(message) {
const request =
/** @type {dpsl_internal.DiagnosticsGetRoutineUpdateRequest} */ (
message);
let routine, command;
try {
routine = this.convertRoutineId(request.routineId);
command = this.convertCommandToEnum(request.command);
} catch (/** @type {!Error} */ error) {
return error;
}
const response = await getOrCreateDiagnosticsService().getRoutineUpdate(
routine, command, request.includeOutput);
return this.convertRoutineUpdate(response.routineUpdate);
};
};
const diagnosticsProxy = new DiagnosticsProxy();
......@@ -208,6 +376,10 @@ untrustedMessagePipe.registerHandler(
dpsl_internal.Message.DIAGNOSTICS_AVAILABLE_ROUTINES,
() => diagnosticsProxy.handleGetAvailableRoutines());
untrustedMessagePipe.registerHandler(
dpsl_internal.Message.DIAGNOSTICS_ROUTINE_UPDATE,
(message) => diagnosticsProxy.handleGetRoutineUpdate(message));
untrustedMessagePipe.registerHandler(
dpsl_internal.Message.PROBE_TELEMETRY_INFO,
(message) => telemetryProxy.handleProbeTelemetryInfo(message));
......@@ -50,6 +50,30 @@ chromeos.test_support = {};
dpsl_internal.Message.DIAGNOSTICS_AVAILABLE_ROUTINES));
return response;
}
/**
* Requests a command to be run on a diagnostic routine.
* @param { !number } routineId
* @param { !string } command
* @param { !boolean } includeOutput
* @return { !Promise<!Object> }
* @public
*/
async sendCommandToRoutine(routineId, command, includeOutput) {
const message =
/** @type {dpsl_internal.DiagnosticsGetRoutineUpdateRequest} */ ({
routineId: routineId,
command: command,
includeOutput: includeOutput,
});
const response =
/** @type {!Object} */ (await messagePipe.sendMessage(
dpsl_internal.Message.DIAGNOSTICS_ROUTINE_UPDATE, message));
if (response instanceof Error) {
throw response;
}
return response;
}
};
/**
......
......@@ -61,6 +61,50 @@ void TelemetryExtensionUiBrowserTest::SetUpCommandLine(
SandboxedWebUiAppTestBase::SetUpCommandLine(command_line);
}
void TelemetryExtensionUiBrowserTest::
ConfigureDiagnosticsForInteractiveUpdate() {
namespace cros_healthd = ::chromeos::cros_healthd::mojom;
auto input = cros_healthd::RoutineUpdate::New();
auto routineUpdateUnion = cros_healthd::RoutineUpdateUnion::New();
auto interactiveRoutineUpdate = cros_healthd::InteractiveRoutineUpdate::New();
interactiveRoutineUpdate->user_message =
cros_healthd::DiagnosticRoutineUserMessageEnum::kUnplugACPower;
routineUpdateUnion->set_interactive_update(
std::move(interactiveRoutineUpdate));
input->progress_percent = 0;
input->routine_update_union = std::move(routineUpdateUnion);
chromeos::cros_healthd::FakeCrosHealthdClient::Get()
->SetGetRoutineUpdateResponseForTesting(input);
}
void TelemetryExtensionUiBrowserTest::
ConfigureDiagnosticsForNonInteractiveUpdate() {
namespace cros_healthd = ::chromeos::cros_healthd::mojom;
auto input = cros_healthd::RoutineUpdate::New();
auto routineUpdateUnion = cros_healthd::RoutineUpdateUnion::New();
auto nonInteractiveRoutineUpdate =
cros_healthd::NonInteractiveRoutineUpdate::New();
nonInteractiveRoutineUpdate->status =
cros_healthd::DiagnosticRoutineStatusEnum::kReady;
nonInteractiveRoutineUpdate->status_message = "Routine ran by Google.";
routineUpdateUnion->set_noninteractive_update(
std::move(nonInteractiveRoutineUpdate));
input->progress_percent = 3147483771;
input->routine_update_union = std::move(routineUpdateUnion);
chromeos::cros_healthd::FakeCrosHealthdClient::Get()
->SetGetRoutineUpdateResponseForTesting(input);
}
void TelemetryExtensionUiBrowserTest::SetUpOnMainThread() {
{
namespace cros_diagnostics = ::chromeos::cros_healthd::mojom;
......
......@@ -18,6 +18,9 @@ class TelemetryExtensionUiBrowserTest : public SandboxedWebUiAppTestBase {
TelemetryExtensionUiBrowserTest& operator=(
const TelemetryExtensionUiBrowserTest&) = delete;
void ConfigureDiagnosticsForInteractiveUpdate();
void ConfigureDiagnosticsForNonInteractiveUpdate();
// SandboxedWebUiAppTestBase overrides:
void SetUpCommandLine(base::CommandLine* command_line) override;
void SetUpOnMainThread() override;
......
......@@ -67,6 +67,55 @@ TEST_F('TelemetryExtensionUIBrowserTest', 'HasChromeUntrustedIframe', () => {
testDone();
});
TEST_F('TelemetryExtensionUIBrowserTest', 'ConvertDiagnosticsEnums', () => {
// Unit tests for convertRoutineId
assertEquals(diagnosticsProxy.convertRoutineId(234089591), 234089591);
// Unit tests for convertCommandToEnum
const commandEnum = chromeos.health.mojom.DiagnosticRoutineCommandEnum;
assertEquals(
diagnosticsProxy.convertCommandToEnum('continue'), commandEnum.kContinue);
assertEquals(
diagnosticsProxy.convertCommandToEnum('cancel'), commandEnum.kCancel);
assertEquals(
diagnosticsProxy.convertCommandToEnum('get-status'),
commandEnum.kGetStatus);
assertEquals(
diagnosticsProxy.convertCommandToEnum('remove'), commandEnum.kRemove);
// Unit tests for convertStatus
const statusEnum = chromeos.health.mojom.DiagnosticRoutineStatusEnum;
assertEquals(diagnosticsProxy.convertStatus(statusEnum.kReady), 'ready');
assertEquals(diagnosticsProxy.convertStatus(statusEnum.kRunning), 'running');
assertEquals(diagnosticsProxy.convertStatus(statusEnum.kWaiting), 'waiting');
assertEquals(diagnosticsProxy.convertStatus(statusEnum.kPassed), 'passed');
assertEquals(diagnosticsProxy.convertStatus(statusEnum.kFailed), 'failed');
assertEquals(diagnosticsProxy.convertStatus(statusEnum.kError), 'error');
assertEquals(
diagnosticsProxy.convertStatus(statusEnum.kCancelled), 'cancelled');
assertEquals(
diagnosticsProxy.convertStatus(statusEnum.kFailedToStart),
'failed-to-start');
assertEquals(diagnosticsProxy.convertStatus(statusEnum.kRemoved), 'removed');
assertEquals(
diagnosticsProxy.convertStatus(statusEnum.kCancelling), 'cancelling');
// Unit tests for convertUserMessage
const userMessageEnum =
chromeos.health.mojom.DiagnosticRoutineUserMessageEnum;
assertEquals(
diagnosticsProxy.convertUserMessage(userMessageEnum.kUnplugACPower),
'unplug-ac-power');
assertEquals(
diagnosticsProxy.convertUserMessage(userMessageEnum.kPlugInACPower),
'plug-in-ac-power');
testDone();
});
// Tests that Telemetry.convert method correctly converts Mojo types into WebIDL
// types.
TEST_F(
......@@ -128,6 +177,14 @@ TEST_F(
testDone();
});
TEST_F(
'TelemetryExtensionUIBrowserTest',
'UntrustedDiagnosticsRequestRoutineUpdateUnknownArguments', async () => {
await runTestInUntrusted(
'UntrustedDiagnosticsRequestRoutineUpdateUnknownArguments');
testDone();
});
TEST_F(
'TelemetryExtensionUIBrowserTest',
'UntrustedRequestTelemetryInfoUnknownCategory', async () => {
......@@ -142,6 +199,38 @@ TEST_F(
testDone();
});
var DiagnosticsInteractiveRoutineUpdate =
class extends TelemetryExtensionUIBrowserTest {
/** @override */
testGenPreamble() {
GEN('ConfigureDiagnosticsForInteractiveUpdate();');
}
}
TEST_F(
'DiagnosticsInteractiveRoutineUpdate',
'UntrustedDiagnosticsRequestInteractiveRoutineUpdate', async () => {
await runTestInUntrusted(
'UntrustedDiagnosticsRequestInteractiveRoutineUpdate');
testDone();
});
var DiagnosticsNonInteractiveRoutineUpdate =
class extends TelemetryExtensionUIBrowserTest {
/** @override */
testGenPreamble() {
GEN('ConfigureDiagnosticsForNonInteractiveUpdate();');
}
}
TEST_F(
'DiagnosticsNonInteractiveRoutineUpdate',
'UntrustedDiagnosticsRequestNonInteractiveRoutineUpdate', async () => {
await runTestInUntrusted(
'UntrustedDiagnosticsRequestNonInteractiveRoutineUpdate');
testDone();
});
/**
* @implements {chromeos.health.mojom.ProbeServiceInterface}
*/
......
......@@ -88,6 +88,48 @@ UNTRUSTED_TEST('UntrustedRequestAvailableRoutines', async () => {
]);
});
// Tests that sendCommandToRoutine throws the correct errors
// when unknown routines or commands are passed as input.
UNTRUSTED_TEST(
'UntrustedDiagnosticsRequestRoutineUpdateUnknownArguments', async () => {
let caughtError;
try {
await chromeos.diagnostics.sendCommandToRoutine(
9007199254740991, 'remove', true);
} catch (error) {
caughtError = error;
}
assertEquals(caughtError.name, 'RangeError');
assertEquals(
caughtError.message,
`Diagnostic routine id '9007199254740991' is out of int32 range.`);
try {
await chromeos.diagnostics.sendCommandToRoutine(
-9007199254740991, 'remove', true);
} catch (error) {
caughtError = error;
}
assertEquals(caughtError.name, 'RangeError');
assertEquals(
caughtError.message,
`Diagnostic routine id '-9007199254740991' is out of int32 range.`);
try {
await chromeos.diagnostics.sendCommandToRoutine(
123456789, 'this-command-must-not-exist', true);
} catch (error) {
caughtError = error;
}
assertEquals(caughtError.name, 'TypeError');
assertEquals(
caughtError.message,
`Diagnostic command \'this-command-must-not-exist\' is unknown.`);
});
// Tests that TelemetryInfo can be successfully requested from
// from chrome-untrusted://.
UNTRUSTED_TEST('UntrustedRequestTelemetryInfo', async () => {
......@@ -118,6 +160,36 @@ UNTRUSTED_TEST('UntrustedRequestTelemetryInfo', async () => {
});
});
// Tests that sendCommandToRoutine returns the correct Object
// for an interactive routine.
UNTRUSTED_TEST(
'UntrustedDiagnosticsRequestInteractiveRoutineUpdate', async () => {
const response = await chromeos.diagnostics.sendCommandToRoutine(
987654321, 'remove', true);
assertDeepEquals(response, {
progressPercent: 0,
output: '',
routineUpdateUnion:
{interactiveUpdate: {userMessage: 'unplug-ac-power'}}
});
});
// Tests that sendCommandToRoutine returns the correct Object
// for a non-interactive routine.
UNTRUSTED_TEST(
'UntrustedDiagnosticsRequestNonInteractiveRoutineUpdate', async () => {
const response = await chromeos.diagnostics.sendCommandToRoutine(
135797531, 'remove', true);
assertDeepEquals(response, {
progressPercent: 3147483771,
output: '',
routineUpdateUnion: {
noninteractiveUpdate:
{status: 'ready', statusMessage: 'Routine ran by Google.'}
}
});
});
// Tests that TelemetryInfo can be successfully requested from
// from chrome-untrusted://.
UNTRUSTED_TEST('UntrustedRequestTelemetryInfoWithInterceptor', async () => {
......
......@@ -26,6 +26,7 @@ function GUEST_TEST(testCase, Function) {}
const testing = {
Test: class {
get browsePreload() {}
get testGenPreamble() {}
get extraLibraries() {}
get isAsync() {}
get featureList() {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment