blob: 4cc7690cf0637d9cd6fcba70de3c5847c5d710b4 [file] [log] [blame]
// Copyright 2021 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 "chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h"
#include <inttypes.h>
#include <memory>
#include <string>
#include <utility>
#include "ash/webui/telemetry_extension_ui/services/probe_service.h"
#include "base/bind.h"
#include "base/values.h"
#include "chrome/browser/chromeos/extensions/telemetry/api/telemetry_api_converters.h"
#include "chrome/common/chromeos/extensions/api/telemetry.h"
#include "extensions/common/permissions/permissions_data.h"
namespace chromeos {
// TelemetryApiFunctionBase ----------------------------------------------------
TelemetryApiFunctionBase::TelemetryApiFunctionBase()
: probe_service_(ash::ProbeService::Factory::Create(
remote_probe_service_.BindNewPipeAndPassReceiver())) {}
TelemetryApiFunctionBase::~TelemetryApiFunctionBase() = default;
// OsTelemetryGetBatteryInfoFunction -------------------------------------------
OsTelemetryGetBatteryInfoFunction::OsTelemetryGetBatteryInfoFunction() =
default;
OsTelemetryGetBatteryInfoFunction::~OsTelemetryGetBatteryInfoFunction() =
default;
void OsTelemetryGetBatteryInfoFunction::RunIfAllowed() {
auto cb = base::BindOnce(&OsTelemetryGetBatteryInfoFunction::OnResult, this);
remote_probe_service_->ProbeTelemetryInfo(
{ash::health::mojom::ProbeCategoryEnum::kBattery}, std::move(cb));
}
void OsTelemetryGetBatteryInfoFunction::OnResult(
ash::health::mojom::TelemetryInfoPtr ptr) {
if (!ptr || !ptr->battery_result || !ptr->battery_result->is_battery_info()) {
Respond(Error("API internal error"));
return;
}
auto& battery_info = ptr->battery_result->get_battery_info();
// Protect accessing the serial number by a permission.
std::unique_ptr<std::string> serial_number;
if (extension()->permissions_data()->HasAPIPermission(
extensions::mojom::APIPermissionID::kChromeOSTelemetrySerialNumber) &&
battery_info->serial_number.has_value()) {
serial_number = std::make_unique<std::string>(
std::move(battery_info->serial_number.value()));
}
api::os_telemetry::BatteryInfo result =
converters::ConvertPtr<api::os_telemetry::BatteryInfo>(
std::move(battery_info));
if (serial_number && !serial_number->empty()) {
result.serial_number = std::move(serial_number);
}
Respond(
ArgumentList(api::os_telemetry::GetBatteryInfo::Results::Create(result)));
}
// OsTelemetryGetCpuInfoFunction -----------------------------------------------
OsTelemetryGetCpuInfoFunction::OsTelemetryGetCpuInfoFunction() = default;
OsTelemetryGetCpuInfoFunction::~OsTelemetryGetCpuInfoFunction() = default;
void OsTelemetryGetCpuInfoFunction::RunIfAllowed() {
auto cb = base::BindOnce(&OsTelemetryGetCpuInfoFunction::OnResult, this);
remote_probe_service_->ProbeTelemetryInfo(
{ash::health::mojom::ProbeCategoryEnum::kCpu}, std::move(cb));
}
void OsTelemetryGetCpuInfoFunction::OnResult(
ash::health::mojom::TelemetryInfoPtr ptr) {
if (!ptr || !ptr->cpu_result || !ptr->cpu_result->is_cpu_info()) {
Respond(Error("API internal error"));
return;
}
const auto& cpu_info = ptr->cpu_result->get_cpu_info();
api::os_telemetry::CpuInfo result;
if (cpu_info->num_total_threads) {
result.num_total_threads =
std::make_unique<int32_t>(cpu_info->num_total_threads->value);
}
result.architecture = converters::Convert(cpu_info->architecture);
result.physical_cpus =
converters::ConvertPtrVector<api::os_telemetry::PhysicalCpuInfo>(
std::move(cpu_info->physical_cpus));
Respond(ArgumentList(api::os_telemetry::GetCpuInfo::Results::Create(result)));
}
// OsTelemetryGetMemoryInfoFunction --------------------------------------------
OsTelemetryGetMemoryInfoFunction::OsTelemetryGetMemoryInfoFunction() = default;
OsTelemetryGetMemoryInfoFunction::~OsTelemetryGetMemoryInfoFunction() = default;
void OsTelemetryGetMemoryInfoFunction::RunIfAllowed() {
auto cb = base::BindOnce(&OsTelemetryGetMemoryInfoFunction::OnResult, this);
remote_probe_service_->ProbeTelemetryInfo(
{ash::health::mojom::ProbeCategoryEnum::kMemory}, std::move(cb));
}
void OsTelemetryGetMemoryInfoFunction::OnResult(
ash::health::mojom::TelemetryInfoPtr ptr) {
if (!ptr || !ptr->memory_result || !ptr->memory_result->is_memory_info()) {
Respond(Error("API internal error"));
return;
}
api::os_telemetry::MemoryInfo result;
const auto& memory_info = ptr->memory_result->get_memory_info();
if (memory_info->total_memory_kib) {
result.total_memory_ki_b =
std::make_unique<int32_t>(memory_info->total_memory_kib->value);
}
if (memory_info->free_memory_kib) {
result.free_memory_ki_b =
std::make_unique<int32_t>(memory_info->free_memory_kib->value);
}
if (memory_info->available_memory_kib) {
result.available_memory_ki_b =
std::make_unique<int32_t>(memory_info->available_memory_kib->value);
}
if (memory_info->page_faults_since_last_boot) {
result.page_faults_since_last_boot = std::make_unique<double_t>(
memory_info->page_faults_since_last_boot->value);
}
Respond(
ArgumentList(api::os_telemetry::GetMemoryInfo::Results::Create(result)));
}
// OsTelemetryGetOemDataFunction -----------------------------------------------
OsTelemetryGetOemDataFunction::OsTelemetryGetOemDataFunction() = default;
OsTelemetryGetOemDataFunction::~OsTelemetryGetOemDataFunction() = default;
void OsTelemetryGetOemDataFunction::RunIfAllowed() {
// Protect accessing the serial number by a permission.
if (!extension()->permissions_data()->HasAPIPermission(
extensions::mojom::APIPermissionID::kChromeOSTelemetrySerialNumber)) {
Respond(
Error("Unauthorized access to chrome.os.telemetry.getOemData. Extension"
" doesn't have the permission."));
return;
}
auto cb = base::BindOnce(&OsTelemetryGetOemDataFunction::OnResult, this);
remote_probe_service_->GetOemData(std::move(cb));
}
void OsTelemetryGetOemDataFunction::OnResult(
ash::health::mojom::OemDataPtr ptr) {
if (!ptr || !ptr->oem_data.has_value()) {
Respond(Error("API internal error"));
return;
}
api::os_telemetry::OemData result;
result.oem_data =
std::make_unique<std::string>(std::move(ptr->oem_data.value()));
Respond(ArgumentList(api::os_telemetry::GetOemData::Results::Create(result)));
}
// OsTelemetryGetOsVersionInfoFunction -----------------------------------------
OsTelemetryGetOsVersionInfoFunction::OsTelemetryGetOsVersionInfoFunction() =
default;
OsTelemetryGetOsVersionInfoFunction::~OsTelemetryGetOsVersionInfoFunction() =
default;
void OsTelemetryGetOsVersionInfoFunction::RunIfAllowed() {
auto cb =
base::BindOnce(&OsTelemetryGetOsVersionInfoFunction::OnResult, this);
remote_probe_service_->ProbeTelemetryInfo(
{ash::health::mojom::ProbeCategoryEnum::kSystem}, std::move(cb));
}
void OsTelemetryGetOsVersionInfoFunction::OnResult(
ash::health::mojom::TelemetryInfoPtr ptr) {
if (!ptr || !ptr->system_result || !ptr->system_result->is_system_info()) {
Respond(Error("API internal error"));
return;
}
auto& system_info = ptr->system_result->get_system_info();
// os_version is an optional value and might not be present.
// TODO(b/234338704): check how to test this.
if (!system_info->os_info || !system_info->os_info->os_version) {
Respond(Error("API internal error"));
return;
}
api::os_telemetry::OsVersionInfo result =
converters::ConvertPtr<api::os_telemetry::OsVersionInfo>(
std::move(system_info->os_info->os_version));
Respond(ArgumentList(
api::os_telemetry::GetOsVersionInfo::Results::Create(result)));
}
// OsTelemetryGetStatefulPartitionInfoFunction ---------------------------------
OsTelemetryGetStatefulPartitionInfoFunction::
OsTelemetryGetStatefulPartitionInfoFunction() = default;
OsTelemetryGetStatefulPartitionInfoFunction::
~OsTelemetryGetStatefulPartitionInfoFunction() = default;
void OsTelemetryGetStatefulPartitionInfoFunction::RunIfAllowed() {
auto cb = base::BindOnce(
&OsTelemetryGetStatefulPartitionInfoFunction::OnResult, this);
remote_probe_service_->ProbeTelemetryInfo(
{ash::health::mojom::ProbeCategoryEnum::kStatefulPartition},
std::move(cb));
}
void OsTelemetryGetStatefulPartitionInfoFunction::OnResult(
ash::health::mojom::TelemetryInfoPtr ptr) {
if (!ptr || !ptr->stateful_partition_result ||
!ptr->stateful_partition_result->is_partition_info()) {
Respond(Error("API internal error"));
return;
}
auto& stateful_part_info =
ptr->stateful_partition_result->get_partition_info();
api::os_telemetry::StatefulPartitionInfo result =
converters::ConvertPtr<api::os_telemetry::StatefulPartitionInfo>(
std::move(stateful_part_info));
Respond(ArgumentList(
api::os_telemetry::GetStatefulPartitionInfo::Results::Create(result)));
}
// OsTelemetryGetVpdInfoFunction -----------------------------------------------
OsTelemetryGetVpdInfoFunction::OsTelemetryGetVpdInfoFunction() = default;
OsTelemetryGetVpdInfoFunction::~OsTelemetryGetVpdInfoFunction() = default;
void OsTelemetryGetVpdInfoFunction::RunIfAllowed() {
auto cb = base::BindOnce(&OsTelemetryGetVpdInfoFunction::OnResult, this);
remote_probe_service_->ProbeTelemetryInfo(
{ash::health::mojom::ProbeCategoryEnum::kCachedVpdData}, std::move(cb));
}
void OsTelemetryGetVpdInfoFunction::OnResult(
ash::health::mojom::TelemetryInfoPtr ptr) {
if (!ptr || !ptr->vpd_result || !ptr->vpd_result->is_vpd_info()) {
Respond(Error("API internal error"));
return;
}
api::os_telemetry::VpdInfo result;
const auto& vpd_info = ptr->vpd_result->get_vpd_info();
if (vpd_info->first_power_date.has_value()) {
result.activate_date =
std::make_unique<std::string>(vpd_info->first_power_date.value());
}
if (vpd_info->model_name.has_value()) {
result.model_name =
std::make_unique<std::string>(vpd_info->model_name.value());
}
if (vpd_info->sku_number.has_value()) {
result.sku_number =
std::make_unique<std::string>(vpd_info->sku_number.value());
}
// Protect accessing the serial number by a permission.
if (extension()->permissions_data()->HasAPIPermission(
extensions::mojom::APIPermissionID::kChromeOSTelemetrySerialNumber) &&
vpd_info->serial_number.has_value()) {
result.serial_number =
std::make_unique<std::string>(vpd_info->serial_number.value());
}
Respond(ArgumentList(api::os_telemetry::GetVpdInfo::Results::Create(result)));
}
} // namespace chromeos