blob: f9df58f7043ff2fcda7c7bef378068e4452f66a2 [file] [log] [blame]
// Copyright 2025 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/metrics/k12_age_classification_metrics_provider.h"
#include <optional>
#include "ash/constants/ash_switches.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/ash/login/existing_user_controller.h"
#include "chrome/browser/ash/login/test/logged_in_user_mixin.h"
#include "chrome/browser/ash/login/test/session_manager_state_waiter.h"
#include "chrome/browser/ash/login/wizard_controller.h"
#include "chrome/browser/ash/ownership/fake_owner_settings_service.h"
#include "chrome/browser/ash/policy/core/device_local_account.h"
#include "chrome/browser/ash/policy/core/device_policy_cros_browser_test.h"
#include "chrome/browser/ash/policy/test_support/embedded_policy_test_server_mixin.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part_ash.h"
#include "chrome/test/base/fake_gaia_mixin.h"
#include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h"
#include "components/metrics/metrics_service.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_store.h"
#include "components/policy/core/common/cloud/test/policy_builder.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "content/public/test/browser_test.h"
namespace {
namespace em = enterprise_management;
using K12AgeClassificationSegment =
K12AgeClassificationMetricsProvider::K12AgeClassificationSegment;
using testing::InvokeWithoutArgs;
constexpr char kAccountId1[] = "dla1@example.com";
std::optional<em::PolicyData::K12AgeClassificationMetricsLogSegment>
GetK12AgeClassificationMetricsLogSegment(K12AgeClassificationSegment segment) {
switch (segment) {
case K12AgeClassificationSegment::kAgeUnder18:
return em::PolicyData::AGE_UNDER18;
case K12AgeClassificationSegment::kAgeEqualOrOver18:
return em::PolicyData::AGE_EQUAL_OR_OVER18;
case K12AgeClassificationSegment::kAgeUnspecified:
[[fallthrough]];
default:
return em::PolicyData::AGE_UNSPECIFIED;
}
}
void ProvideHistograms() {
// The purpose of the below call is to avoid a DCHECK failure in an unrelated
// metrics provider, in |FieldTrialsProvider::ProvideCurrentSessionData()|.
metrics::SystemProfileProto system_profile_proto;
// Downstream functions do not use system_profile_proto so there is no risk of
// UAF.
g_browser_process->metrics_service()
->GetDelegatingProviderForTesting()
->ProvideSystemProfileMetricsWithLogCreationTime(base::TimeTicks::Now(),
&system_profile_proto);
g_browser_process->metrics_service()
->GetDelegatingProviderForTesting()
->OnDidCreateMetricsLog();
}
class TestCase {
public:
explicit TestCase(K12AgeClassificationSegment segment) : segment_(segment) {}
std::string GetTestName() const {
switch (segment_) {
case K12AgeClassificationSegment::kAgeUnder18:
return "AgeUnder18";
case K12AgeClassificationSegment::kAgeEqualOrOver18:
return "AgeEqualOrOver18";
case K12AgeClassificationSegment::kAgeUnspecified:
return "AgeUnspecified";
}
}
K12AgeClassificationSegment GetSegment() const { return segment_; }
std::optional<em::PolicyData::K12AgeClassificationMetricsLogSegment>
GetK12AgeClassificationMetricsLogSegment() const {
return ::GetK12AgeClassificationMetricsLogSegment(segment_);
}
private:
const K12AgeClassificationSegment segment_;
};
class K12AgeClassificationMetricsProviderTest
: public policy::DevicePolicyCrosBrowserTest,
public testing::WithParamInterface<TestCase> {
protected:
void SetUpInProcessBrowserTestFixture() override {
policy::DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
InitializePolicy();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(ash::switches::kOobeSkipPostLogin);
DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line);
}
void InitializePolicy() {
device_policy()->policy_data().set_public_key_version(1);
}
void SetDevicePolicy() {
device_local_account_policy_.SetDefaultSigningKey();
device_local_account_policy_.Build();
logged_in_user_mixin_.GetEmbeddedPolicyTestServerMixin()
->UpdateExternalPolicy(
policy::dm_protocol::kChromePublicAccountPolicyType, kAccountId1,
device_local_account_policy_.payload().SerializeAsString());
session_manager_client()->set_device_local_account_policy(
kAccountId1, device_local_account_policy_.GetBlob());
}
void LogInUser() {
std::optional<em::PolicyData::K12AgeClassificationMetricsLogSegment>
log_segment = GetParam().GetK12AgeClassificationMetricsLogSegment();
if (log_segment) {
logged_in_user_mixin_.GetEmbeddedPolicyTestServerMixin()
->SetK12AgeClassificationMetricsLogSegment(log_segment.value());
}
logged_in_user_mixin_.LogInUser();
}
int GetExpectedUmaValue() {
return static_cast<int>(GetParam().GetSegment());
}
private:
ash::LoggedInUserMixin logged_in_user_mixin_{
&mixin_host_, /*test_base=*/this, embedded_test_server(),
ash::LoggedInUserMixin::LogInType::kManaged};
policy::UserPolicyBuilder device_local_account_policy_;
};
IN_PROC_BROWSER_TEST_P(K12AgeClassificationMetricsProviderTest, Uma) {
base::HistogramTester histogram_tester;
SetDevicePolicy();
// Simulate calling ProvideHistograms() prior to logging in.
ProvideHistograms();
// No metrics were recorded.
histogram_tester.ExpectTotalCount(
K12AgeClassificationMetricsProvider::kHistogramName, 0);
LogInUser();
// Simulate calling ProvideHistograms() after logging in.
ProvideHistograms();
histogram_tester.ExpectUniqueSample(
K12AgeClassificationMetricsProvider::kHistogramName,
GetExpectedUmaValue(), 1);
}
INSTANTIATE_TEST_SUITE_P(
All,
K12AgeClassificationMetricsProviderTest,
testing::Values(TestCase(K12AgeClassificationSegment::kAgeUnder18),
TestCase(K12AgeClassificationSegment::kAgeEqualOrOver18),
TestCase(K12AgeClassificationSegment::kAgeUnspecified)));
} // namespace