blob: 7dd42b16e7d0d0048482a648e4be15241ec64ca4 [file] [log] [blame]
Vincent Boisselle275215f2019-06-27 19:33:511// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Mikel Astiz417050a2020-10-16 06:35:505#include "components/metrics/demographics/demographic_metrics_provider.h"
Vincent Boisselle743efdb2019-07-13 16:59:036
Vincent Boisselle275215f2019-06-27 19:33:517#include "base/feature_list.h"
Vincent Boissellef2acc1a2019-10-18 01:43:518#include "base/metrics/histogram_functions.h"
Toby Huang3f2085ea2020-12-04 20:03:469#include "build/chromeos_buildflags.h"
Mikel Astizf9d22bc2020-10-30 07:59:4510#include "components/sync/driver/sync_service_utils.h"
Anton Bikineev1156b5f2021-05-15 22:35:3611#include "third_party/abseil-cpp/absl/types/optional.h"
Vincent Boissellef2acc1a2019-10-18 01:43:5112#include "third_party/metrics_proto/ukm/report.pb.h"
Vincent Boisselle275215f2019-06-27 19:33:5113
14namespace metrics {
15
Mikel Astizf9d22bc2020-10-30 07:59:4516namespace {
17
18bool CanUploadDemographicsToGoogle(syncer::SyncService* sync_service) {
19 DCHECK(sync_service);
20
21 // Require that the user has opted into sync the feature, without just relying
22 // on PRIORITY_PREFERENCES start sync-ing.
23 if (!sync_service->IsSyncFeatureEnabled()) {
24 return false;
25 }
26
27 switch (GetUploadToGoogleState(sync_service, syncer::PRIORITY_PREFERENCES)) {
28 case syncer::UploadState::NOT_ACTIVE:
29 return false;
30 case syncer::UploadState::INITIALIZING:
31 // Note that INITIALIZING is considered good enough, because sync is known
32 // to be enabled, and transient errors don't really matter here.
33 case syncer::UploadState::ACTIVE:
34 return true;
35 }
36}
37
38} // namespace
39
Vincent Boisselle30da39772019-07-24 18:55:4740// static
41const base::Feature DemographicMetricsProvider::kDemographicMetricsReporting = {
Caitlin Fischer53c61a4e2020-04-17 19:18:3142 "DemographicMetricsReporting", base::FEATURE_ENABLED_BY_DEFAULT};
Vincent Boisselle743efdb2019-07-13 16:59:0343
44DemographicMetricsProvider::DemographicMetricsProvider(
Vincent Boissellef2acc1a2019-10-18 01:43:5145 std::unique_ptr<ProfileClient> profile_client,
46 MetricsLogUploader::MetricServiceType metrics_service_type)
47 : profile_client_(std::move(profile_client)),
48 metrics_service_type_(metrics_service_type) {
Vincent Boisselle30da39772019-07-24 18:55:4749 DCHECK(profile_client_);
Vincent Boisselle743efdb2019-07-13 16:59:0350}
51
Vincent Boisselle30da39772019-07-24 18:55:4752DemographicMetricsProvider::~DemographicMetricsProvider() {}
53
Anton Bikineev1156b5f2021-05-15 22:35:3654absl::optional<UserDemographics>
Vincent Boissellef2acc1a2019-10-18 01:43:5155DemographicMetricsProvider::ProvideSyncedUserNoisedBirthYearAndGender() {
Vincent Boisselle743efdb2019-07-13 16:59:0356 // Skip if feature disabled.
57 if (!base::FeatureList::IsEnabled(kDemographicMetricsReporting))
Anton Bikineev1156b5f2021-05-15 22:35:3658 return absl::nullopt;
Vincent Boisselle743efdb2019-07-13 16:59:0359
Toby Huang3f2085ea2020-12-04 20:03:4660#if !BUILDFLAG(IS_CHROMEOS_ASH)
Vincent Boisselle30da39772019-07-24 18:55:4761 // Skip if not exactly one Profile on disk. Having more than one Profile that
62 // is using the browser can make demographics less relevant. This approach
63 // cannot determine if there is more than 1 distinct user using the Profile.
Toby Huang3f2085ea2020-12-04 20:03:4664
65 // ChromeOS almost always has more than one profile on disk, so this check
66 // doesn't work. We have a profile selection strategy for ChromeOS, so skip
67 // this check for ChromeOS.
68 // TODO(crbug/1145655): LaCros will behave similarly to desktop Chrome and
69 // reduce the number of profiles on disk to one, so remove these #if guards
70 // after LaCros release.
Vincent Boisselle7577df02019-08-01 19:07:0471 if (profile_client_->GetNumberOfProfilesOnDisk() != 1) {
Vincent Boissellef2acc1a2019-10-18 01:43:5172 LogUserDemographicsStatusInHistogram(
Mikel Astizf4226912020-10-19 19:10:3773 UserDemographicsStatus::kMoreThanOneProfile);
Anton Bikineev1156b5f2021-05-15 22:35:3674 return absl::nullopt;
Vincent Boisselle7577df02019-08-01 19:07:0475 }
Toby Huang3f2085ea2020-12-04 20:03:4676#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
Vincent Boisselle743efdb2019-07-13 16:59:0377
Vincent Boisselle30da39772019-07-24 18:55:4778 syncer::SyncService* sync_service = profile_client_->GetSyncService();
79 // Skip if no sync service.
Vincent Boisselle7577df02019-08-01 19:07:0480 if (!sync_service) {
Vincent Boissellef2acc1a2019-10-18 01:43:5181 LogUserDemographicsStatusInHistogram(
Mikel Astizf4226912020-10-19 19:10:3782 UserDemographicsStatus::kNoSyncService);
Anton Bikineev1156b5f2021-05-15 22:35:3683 return absl::nullopt;
Vincent Boisselle7577df02019-08-01 19:07:0484 }
Vincent Boisselle30da39772019-07-24 18:55:4785
Mikel Astizf9d22bc2020-10-30 07:59:4586 if (!CanUploadDemographicsToGoogle(sync_service)) {
Mikel Astizf4226912020-10-19 19:10:3787 LogUserDemographicsStatusInHistogram(
88 UserDemographicsStatus::kSyncNotEnabled);
Anton Bikineev1156b5f2021-05-15 22:35:3689 return absl::nullopt;
Mikel Astizf4226912020-10-19 19:10:3790 }
91
92 UserDemographicsResult demographics_result =
93 GetUserNoisedBirthYearAndGenderFromPrefs(
94 profile_client_->GetNetworkTime(), profile_client_->GetPrefService());
Vincent Boissellef2acc1a2019-10-18 01:43:5195 LogUserDemographicsStatusInHistogram(demographics_result.status());
96
97 if (demographics_result.IsSuccess())
98 return demographics_result.value();
99
Anton Bikineev1156b5f2021-05-15 22:35:36100 return absl::nullopt;
Vincent Boissellef2acc1a2019-10-18 01:43:51101}
102
103void DemographicMetricsProvider::ProvideCurrentSessionData(
104 ChromeUserMetricsExtension* uma_proto) {
105 ProvideSyncedUserNoisedBirthYearAndGender(uma_proto);
106}
107
108void DemographicMetricsProvider::
109 ProvideSyncedUserNoisedBirthYearAndGenderToReport(ukm::Report* report) {
110 ProvideSyncedUserNoisedBirthYearAndGender(report);
111}
112
113void DemographicMetricsProvider::LogUserDemographicsStatusInHistogram(
Mikel Astizf4226912020-10-19 19:10:37114 UserDemographicsStatus status) {
Vincent Boissellef2acc1a2019-10-18 01:43:51115 switch (metrics_service_type_) {
116 case MetricsLogUploader::MetricServiceType::UMA:
117 base::UmaHistogramEnumeration("UMA.UserDemographics.Status", status);
Toby Huangbe623692020-12-08 22:17:14118 // If the user demographics data was retrieved successfully, then the user
119 // must be between the ages of |kUserDemographicsMinAgeInYears|+1=21 and
120 // |kUserDemographicsMaxAgeinYears|=85, so the user is not a minor.
121 base::UmaHistogramBoolean("UMA.UserDemographics.IsNoisedAgeOver21Under85",
122 status == UserDemographicsStatus::kSuccess);
Vincent Boissellef2acc1a2019-10-18 01:43:51123 return;
124 case MetricsLogUploader::MetricServiceType::UKM:
125 base::UmaHistogramEnumeration("UKM.UserDemographics.Status", status);
126 return;
Vincent Boisselle30da39772019-07-24 18:55:47127 }
Vincent Boissellef2acc1a2019-10-18 01:43:51128 NOTREACHED();
Vincent Boisselle30da39772019-07-24 18:55:47129}
Vincent Boisselle275215f2019-06-27 19:33:51130
131} // namespace metrics