Skip to content

Commit

Permalink
[Telemetry] Introduce getAudioInfo
Browse files Browse the repository at this point in the history
This change adds a `os.telemetry.getAudioInfo` method to the
Telemetry Extension API.

Bug: b/263219165
Test: unit_tests --gtest_filter="*Convert*"
Test: browser_tests --gtest_filter="*Telemetry*"
Test: Follow http://go/lacros-test-linux to run tests locally
Test: ./testing/xvfb.py build/lacros/test_runner.py \
        test out/lacros/unit_tests --gtest_filter="*TelemetryExtension*" \
        --ash-chrome-path ./out/lacros/ash_clang_x64/test_ash_chrome
Test: ./testing/xvfb.py build/lacros/test_runner.py \
        test out/lacros/lacros_chrome_browsertests \
        --gtest_filter="*TelemetryExtension*"
        --ash-chrome-path ./out/lacros/ash_clang_x64/test_ash_chrome

Change-Id: I5afa75980d6655bf39262c93e58555637c2c4dbf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4116574
Commit-Queue: Bastian Kersting <bkersting@google.com>
Reviewed-by: Oleh Lamzin <lamzin@google.com>
Reviewed-by: Toni Barzic <tbarzic@chromium.org>
Auto-Submit: Bastian Kersting <bkersting@google.com>
Reviewed-by: David Bertoni <dbertoni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1096871}
  • Loading branch information
1c3t3a authored and Chromium LUCI CQ committed Jan 25, 2023
1 parent db63e4a commit 48acd26
Show file tree
Hide file tree
Showing 14 changed files with 504 additions and 1 deletion.
Expand Up @@ -6,6 +6,7 @@
#include <string>

#include "base/strings/string_util.h"
#include "base/test/scoped_feature_list.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/chromeos/extensions/telemetry/api/api_guard_delegate.h"
#include "chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h"
Expand All @@ -15,6 +16,7 @@
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/content_mock_cert_verifier.h"
#include "extensions/common/extension_features.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h"
#include "net/dns/mock_host_resolver.h"
Expand Down Expand Up @@ -44,6 +46,14 @@ std::string GetServiceWorkerForError(const std::string& error) {
std::string service_worker = R"(
const tests = [
// Telemetry APIs.
async function getAudioInfo() {
await chrome.test.assertPromiseRejects(
chrome.os.telemetry.getAudioInfo(),
'Error: Unauthorized access to ' +
'chrome.os.telemetry.getAudioInfo.' + ' %s'
);
chrome.test.succeed();
},
async function getBatteryInfo() {
await chrome.test.assertPromiseRejects(
chrome.os.telemetry.getBatteryInfo(),
Expand Down Expand Up @@ -423,7 +433,18 @@ std::string GetServiceWorkerForError(const std::string& error) {

} // namespace

using TelemetryExtensionApiGuardBrowserTest = BaseTelemetryExtensionBrowserTest;
class TelemetryExtensionApiGuardBrowserTest
: public BaseTelemetryExtensionBrowserTest {
public:
TelemetryExtensionApiGuardBrowserTest() {
// Include unreleased APIs.
feature_list_.InitAndEnableFeature(
extensions_features::kTelemetryExtensionPendingApprovalApi);
}

private:
base::test::ScopedFeatureList feature_list_;
};

IN_PROC_BROWSER_TEST_F(TelemetryExtensionApiGuardBrowserTest,
CanAccessApiReturnsError) {
Expand Down
23 changes: 23 additions & 0 deletions chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.cc
Expand Up @@ -45,6 +45,29 @@ bool TelemetryApiFunctionBase::IsCrosApiAvailable() {
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)

// OsTelemetryGetAudioInfoFunction ---------------------------------------------

void OsTelemetryGetAudioInfoFunction::RunIfAllowed() {
auto cb = base::BindOnce(&OsTelemetryGetAudioInfoFunction::OnResult, this);

GetRemoteService()->ProbeTelemetryInfo(
{crosapi::mojom::ProbeCategoryEnum::kAudio}, std::move(cb));
}

void OsTelemetryGetAudioInfoFunction::OnResult(
crosapi::mojom::ProbeTelemetryInfoPtr ptr) {
if (!ptr || !ptr->audio_result || !ptr->audio_result->is_audio_info()) {
Respond(Error("API internal error"));
return;
}
auto& audio_info = ptr->audio_result->get_audio_info();

auto result =
converters::ConvertPtr<telemetry::AudioInfo>(std::move(audio_info));

Respond(ArgumentList(telemetry::GetAudioInfo::Results::Create(result)));
}

// OsTelemetryGetBatteryInfoFunction -------------------------------------------

void OsTelemetryGetBatteryInfoFunction::RunIfAllowed() {
Expand Down
12 changes: 12 additions & 0 deletions chrome/browser/chromeos/extensions/telemetry/api/telemetry_api.h
Expand Up @@ -37,6 +37,18 @@ class TelemetryApiFunctionBase : public BaseTelemetryExtensionApiGuardFunction {
std::unique_ptr<RemoteProbeServiceStrategy> remote_probe_service_strategy_;
};

class OsTelemetryGetAudioInfoFunction : public TelemetryApiFunctionBase {
DECLARE_EXTENSION_FUNCTION("os.telemetry.getAudioInfo",
OS_TELEMETRY_GETAUDIOINFO)
void OnResult(crosapi::mojom::ProbeTelemetryInfoPtr ptr);

private:
~OsTelemetryGetAudioInfoFunction() override = default;

// BaseTelemetryExtensionApiGuardFunction:
void RunIfAllowed() override;
};

class OsTelemetryGetBatteryInfoFunction : public TelemetryApiFunctionBase {
DECLARE_EXTENSION_FUNCTION("os.telemetry.getBatteryInfo",
OS_TELEMETRY_GETBATTERYINFO)
Expand Down
Expand Up @@ -5,7 +5,9 @@
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/test/scoped_feature_list.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/chromeos/extensions/telemetry/api/base_telemetry_extension_browser_test.h"
#include "chrome/browser/chromeos/extensions/telemetry/api/fake_probe_service.h"
Expand All @@ -14,6 +16,7 @@
#include "chromeos/services/network_config/public/mojom/network_types.mojom.h"
#include "chromeos/services/network_health/public/mojom/network_health_types.mojom.h"
#include "content/public/test/browser_test.h"
#include "extensions/common/extension_features.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
Expand Down Expand Up @@ -201,6 +204,161 @@ IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)

IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
GetAudioInfo_NoFeatureFlagEnabledError) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// If Probe interface is not available on this version of ash-chrome, this
// test suite will no-op.
if (!IsServiceAvailable()) {
return;
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)

// If the permission is not enabled, the method isn't defined
// on `chrome.os.telemetry`.
CreateExtensionAndRunServiceWorker(R"(
chrome.test.runTests([
function getAudioInfo() {
chrome.test.assertThrows(() => { chrome.os.telemetry.getAudioInfo(); },
[], "chrome.os.telemetry.getAudioInfo is not a function");
chrome.test.succeed();
}
]);
)");
}

class PendingApprovalTelemetryExtensionTelemetryApiBrowserTest
: public TelemetryExtensionTelemetryApiBrowserTest {
public:
PendingApprovalTelemetryExtensionTelemetryApiBrowserTest() {
feature_list_.InitAndEnableFeature(
extensions_features::kTelemetryExtensionPendingApprovalApi);
}

private:
base::test::ScopedFeatureList feature_list_;
};

IN_PROC_BROWSER_TEST_F(PendingApprovalTelemetryExtensionTelemetryApiBrowserTest,
GetAudioInfo_Error) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// If Probe interface is not available on this version of ash-chrome, this
// test suite will no-op.
if (!IsServiceAvailable()) {
return;
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)

// Configure FakeProbeService.
{
auto fake_service_impl = std::make_unique<FakeProbeService>();
fake_service_impl->SetExpectedLastRequestedCategories(
{crosapi::mojom::ProbeCategoryEnum::kAudio});

SetServiceForTesting(std::move(fake_service_impl));
}

CreateExtensionAndRunServiceWorker(R"(
chrome.test.runTests([
async function getAudioInfo() {
await chrome.test.assertPromiseRejects(
chrome.os.telemetry.getAudioInfo(),
'Error: API internal error'
);
chrome.test.succeed();
}
]);
)");
}

IN_PROC_BROWSER_TEST_F(PendingApprovalTelemetryExtensionTelemetryApiBrowserTest,
GetAudioInfo_Success) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// If Probe interface is not available on this version of ash-chrome, this
// test suite will no-op.
if (!IsServiceAvailable()) {
return;
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)

// Configure FakeProbeService.
{
auto telemetry_info = crosapi::mojom::ProbeTelemetryInfo::New();

{
std::vector<crosapi::mojom::ProbeAudioOutputNodeInfoPtr> output_infos;
auto output_node_info = crosapi::mojom::ProbeAudioOutputNodeInfo::New();
output_node_info->id = crosapi::mojom::UInt64Value::New(43);
output_node_info->name = "Internal Speaker";
output_node_info->device_name = "HDA Intel PCH: CA0132 Analog:0,0";
output_node_info->active = crosapi::mojom::BoolValue::New(false);
output_node_info->node_volume = crosapi::mojom::UInt8Value::New(212);
output_infos.push_back(std::move(output_node_info));

std::vector<crosapi::mojom::ProbeAudioInputNodeInfoPtr> input_infos;
auto input_node_info = crosapi::mojom::ProbeAudioInputNodeInfo::New();
input_node_info->id = crosapi::mojom::UInt64Value::New(42);
input_node_info->name = "External Mic";
input_node_info->device_name = "HDA Intel PCH: CA0132 Analog:1,0";
input_node_info->active = crosapi::mojom::BoolValue::New(true);
input_node_info->node_gain = crosapi::mojom::UInt8Value::New(1);
input_infos.push_back(std::move(input_node_info));

auto audio_info = crosapi::mojom::ProbeAudioInfo::New();
audio_info->output_mute = crosapi::mojom::BoolValue::New(true);
audio_info->input_mute = crosapi::mojom::BoolValue::New(false);
audio_info->underruns = crosapi::mojom::UInt32Value::New(56);
audio_info->severe_underruns = crosapi::mojom::UInt32Value::New(3);
audio_info->output_nodes = std::move(output_infos);
audio_info->input_nodes = std::move(input_infos);

telemetry_info->audio_result =
crosapi::mojom::ProbeAudioResult::NewAudioInfo(std::move(audio_info));
}

auto fake_service_impl = std::make_unique<FakeProbeService>();
fake_service_impl->SetProbeTelemetryInfoResponse(std::move(telemetry_info));
fake_service_impl->SetExpectedLastRequestedCategories(
{crosapi::mojom::ProbeCategoryEnum::kAudio});

SetServiceForTesting(std::move(fake_service_impl));
}

CreateExtensionAndRunServiceWorker(R"(
chrome.test.runTests([
async function getAudioInfo() {
const result = await chrome.os.telemetry.getAudioInfo();
chrome.test.assertEq(
// The dictionary members are ordered lexicographically by the Unicode
// codepoints that comprise their identifiers.
{
inputMute: false,
inputNodes: [{
active: true,
deviceName: 'HDA Intel PCH: CA0132 Analog:1,0',
id: 42,
name: 'External Mic',
nodeGain: 1,
}],
outputMute: true,
outputNodes: [{
active: false,
deviceName: 'HDA Intel PCH: CA0132 Analog:0,0',
id: 43,
name: 'Internal Speaker',
nodeVolume: 212
}],
severeUnderruns: 3,
underruns: 56,
}, result);
chrome.test.succeed();
}
]);
)");
}

IN_PROC_BROWSER_TEST_F(TelemetryExtensionTelemetryApiBrowserTest,
GetBatteryInfo_ApiInternalError) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
Expand Down
Expand Up @@ -28,6 +28,71 @@ namespace telemetry_service = ::crosapi::mojom;
} // namespace

namespace unchecked {
chromeos::api::os_telemetry::AudioInputNodeInfo UncheckedConvertPtr(
crosapi::mojom::ProbeAudioInputNodeInfoPtr input) {
telemetry_api::AudioInputNodeInfo result;

if (input->id) {
result.id = input->id->value;
}
result.name = input->name;
result.device_name = input->device_name;
if (input->active) {
result.active = input->active->value;
}
if (input->node_gain) {
result.node_gain = input->node_gain->value;
}

return result;
}

chromeos::api::os_telemetry::AudioOutputNodeInfo UncheckedConvertPtr(
crosapi::mojom::ProbeAudioOutputNodeInfoPtr input) {
telemetry_api::AudioOutputNodeInfo result;

if (input->id) {
result.id = input->id->value;
}
result.name = input->name;
result.device_name = input->device_name;
if (input->active) {
result.active = input->active->value;
}
if (input->node_volume) {
result.node_volume = input->node_volume->value;
}

return result;
}

telemetry_api::AudioInfo UncheckedConvertPtr(
telemetry_service::ProbeAudioInfoPtr input) {
telemetry_api::AudioInfo result;

if (input->output_mute) {
result.output_mute = input->output_mute->value;
}
if (input->input_mute) {
result.input_mute = input->input_mute->value;
}
if (input->underruns) {
result.underruns = input->underruns->value;
}
if (input->severe_underruns) {
result.severe_underruns = input->severe_underruns->value;
}
if (input->output_nodes) {
result.output_nodes = ConvertPtrVector<telemetry_api::AudioOutputNodeInfo>(
std::move(input->output_nodes.value()));
}
if (input->input_nodes) {
result.input_nodes = ConvertPtrVector<telemetry_api::AudioInputNodeInfo>(
std::move(input->input_nodes.value()));
}

return result;
}

telemetry_api::CpuCStateInfo UncheckedConvertPtr(
telemetry_service::ProbeCpuCStateInfoPtr input) {
Expand Down
Expand Up @@ -27,6 +27,15 @@ namespace unchecked {
// nullptr, they should be called only via ConvertPtr wrapper that checks
// whether input pointer is nullptr.

chromeos::api::os_telemetry::AudioInputNodeInfo UncheckedConvertPtr(
crosapi::mojom::ProbeAudioInputNodeInfoPtr input);

chromeos::api::os_telemetry::AudioOutputNodeInfo UncheckedConvertPtr(
crosapi::mojom::ProbeAudioOutputNodeInfoPtr input);

chromeos::api::os_telemetry::AudioInfo UncheckedConvertPtr(
crosapi::mojom::ProbeAudioInfoPtr input);

chromeos::api::os_telemetry::CpuCStateInfo UncheckedConvertPtr(
crosapi::mojom::ProbeCpuCStateInfoPtr input);

Expand Down

0 comments on commit 48acd26

Please sign in to comment.