1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/metrics/demographics/demographic_metrics_provider.h"
#include <optional>
#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "components/sync/service/sync_service_utils.h"
#include "third_party/metrics_proto/ukm/report.pb.h"
namespace metrics {
namespace {
bool IsValidUploadState(syncer::UploadState upload_state) {
switch (upload_state) {
case syncer::UploadState::NOT_ACTIVE:
return false;
case syncer::UploadState::INITIALIZING:
// Note that INITIALIZING is considered good enough, because sync is known
// to be enabled, and transient errors don't really matter here.
case syncer::UploadState::ACTIVE:
return true;
}
NOTREACHED();
}
bool CanUploadDemographicsToGoogle(syncer::SyncService* sync_service) {
CHECK(sync_service);
// PRIORITY_PREFERENCES is the sync datatype used to propagate demographics
// information to the client. In its absence, demographics info is unavailable
// thus cannot be uploaded.
return IsValidUploadState(syncer::GetUploadToGoogleState(
sync_service, syncer::PRIORITY_PREFERENCES));
}
} // namespace
// static
BASE_FEATURE(kDemographicMetricsReporting,
"DemographicMetricsReporting",
base::FEATURE_ENABLED_BY_DEFAULT);
DemographicMetricsProvider::DemographicMetricsProvider(
std::unique_ptr<ProfileClient> profile_client,
MetricsLogUploader::MetricServiceType metrics_service_type)
: profile_client_(std::move(profile_client)),
metrics_service_type_(metrics_service_type) {
DCHECK(profile_client_);
}
DemographicMetricsProvider::~DemographicMetricsProvider() = default;
std::optional<UserDemographics>
DemographicMetricsProvider::ProvideSyncedUserNoisedBirthYearAndGender() {
// Skip if feature disabled.
if (!base::FeatureList::IsEnabled(kDemographicMetricsReporting))
return std::nullopt;
#if !BUILDFLAG(IS_CHROMEOS)
// Skip if not exactly one Profile on disk. Having more than one Profile that
// is using the browser can make demographics less relevant. This approach
// cannot determine if there is more than 1 distinct user using the Profile.
// ChromeOS almost always has more than one profile on disk, so this check
// doesn't work. We have a profile selection strategy for ChromeOS, so skip
// this check for ChromeOS.
if (profile_client_->GetNumberOfProfilesOnDisk() != 1) {
LogUserDemographicsStatusInHistogram(
UserDemographicsStatus::kMoreThanOneProfile);
return std::nullopt;
}
#endif // !BUILDFLAG(IS_CHROMEOS)
syncer::SyncService* sync_service = profile_client_->GetSyncService();
// Skip if no sync service.
if (!sync_service) {
LogUserDemographicsStatusInHistogram(
UserDemographicsStatus::kNoSyncService);
return std::nullopt;
}
if (!CanUploadDemographicsToGoogle(sync_service)) {
LogUserDemographicsStatusInHistogram(
UserDemographicsStatus::kSyncNotEnabled);
return std::nullopt;
}
UserDemographicsResult demographics_result =
GetUserNoisedBirthYearAndGenderFromPrefs(
profile_client_->GetNetworkTime(), profile_client_->GetLocalState(),
profile_client_->GetProfilePrefs());
LogUserDemographicsStatusInHistogram(demographics_result.status());
if (demographics_result.IsSuccess())
return demographics_result.value();
return std::nullopt;
}
void DemographicMetricsProvider::ProvideCurrentSessionData(
ChromeUserMetricsExtension* uma_proto) {
ProvideSyncedUserNoisedBirthYearAndGender(uma_proto);
}
void DemographicMetricsProvider::
ProvideSyncedUserNoisedBirthYearAndGenderToReport(ukm::Report* report) {
ProvideSyncedUserNoisedBirthYearAndGender(report);
}
void DemographicMetricsProvider::LogUserDemographicsStatusInHistogram(
UserDemographicsStatus status) {
switch (metrics_service_type_) {
case MetricsLogUploader::MetricServiceType::UMA:
base::UmaHistogramEnumeration("UMA.UserDemographics.Status", status);
// If the user demographics data was retrieved successfully, then the user
// must be between the ages of |kUserDemographicsMinAgeInYears|+1=21 and
// |kUserDemographicsMaxAgeInYears|=85, so the user is not a minor.
base::UmaHistogramBoolean("UMA.UserDemographics.IsNoisedAgeOver21Under85",
status == UserDemographicsStatus::kSuccess);
return;
case MetricsLogUploader::MetricServiceType::UKM:
// UKM Metrics doesn't have demographic metrics.
return;
case MetricsLogUploader::MetricServiceType::STRUCTURED_METRICS:
// Structured Metrics doesn't have demographic metrics.
return;
case MetricsLogUploader::MetricServiceType::DWA:
// DWA doesn't have demographic metrics.
return;
}
NOTREACHED();
}
} // namespace metrics
|