demographic_metrics_provider.cc 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // 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. #include "components/metrics/demographics/demographic_metrics_provider.h"
  5. #include "base/feature_list.h"
  6. #include "base/metrics/histogram_functions.h"
  7. #include "build/chromeos_buildflags.h"
  8. #include "components/sync/driver/sync_service_utils.h"
  9. #include "third_party/abseil-cpp/absl/types/optional.h"
  10. #include "third_party/metrics_proto/ukm/report.pb.h"
  11. namespace metrics {
  12. namespace {
  13. bool CanUploadDemographicsToGoogle(syncer::SyncService* sync_service) {
  14. DCHECK(sync_service);
  15. // PRIORITY_PREFERENCES is the sync datatype used to propagate demographics
  16. // information to the client. In its absence, demographics info is unavailable
  17. // thus cannot be uploaded.
  18. switch (GetUploadToGoogleState(sync_service, syncer::PRIORITY_PREFERENCES)) {
  19. case syncer::UploadState::NOT_ACTIVE:
  20. return false;
  21. case syncer::UploadState::INITIALIZING:
  22. // Note that INITIALIZING is considered good enough, because sync is known
  23. // to be enabled, and transient errors don't really matter here.
  24. case syncer::UploadState::ACTIVE:
  25. return true;
  26. }
  27. }
  28. } // namespace
  29. // static
  30. const base::Feature DemographicMetricsProvider::kDemographicMetricsReporting = {
  31. "DemographicMetricsReporting", base::FEATURE_ENABLED_BY_DEFAULT};
  32. DemographicMetricsProvider::DemographicMetricsProvider(
  33. std::unique_ptr<ProfileClient> profile_client,
  34. MetricsLogUploader::MetricServiceType metrics_service_type)
  35. : profile_client_(std::move(profile_client)),
  36. metrics_service_type_(metrics_service_type) {
  37. DCHECK(profile_client_);
  38. }
  39. DemographicMetricsProvider::~DemographicMetricsProvider() {}
  40. absl::optional<UserDemographics>
  41. DemographicMetricsProvider::ProvideSyncedUserNoisedBirthYearAndGender() {
  42. // Skip if feature disabled.
  43. if (!base::FeatureList::IsEnabled(kDemographicMetricsReporting))
  44. return absl::nullopt;
  45. #if !BUILDFLAG(IS_CHROMEOS_ASH)
  46. // Skip if not exactly one Profile on disk. Having more than one Profile that
  47. // is using the browser can make demographics less relevant. This approach
  48. // cannot determine if there is more than 1 distinct user using the Profile.
  49. // ChromeOS almost always has more than one profile on disk, so this check
  50. // doesn't work. We have a profile selection strategy for ChromeOS, so skip
  51. // this check for ChromeOS.
  52. // TODO(crbug/1145655): LaCros will behave similarly to desktop Chrome and
  53. // reduce the number of profiles on disk to one, so remove these #if guards
  54. // after LaCros release.
  55. if (profile_client_->GetNumberOfProfilesOnDisk() != 1) {
  56. LogUserDemographicsStatusInHistogram(
  57. UserDemographicsStatus::kMoreThanOneProfile);
  58. return absl::nullopt;
  59. }
  60. #endif // !BUILDFLAG(IS_CHROMEOS_ASH)
  61. syncer::SyncService* sync_service = profile_client_->GetSyncService();
  62. // Skip if no sync service.
  63. if (!sync_service) {
  64. LogUserDemographicsStatusInHistogram(
  65. UserDemographicsStatus::kNoSyncService);
  66. return absl::nullopt;
  67. }
  68. if (!CanUploadDemographicsToGoogle(sync_service)) {
  69. LogUserDemographicsStatusInHistogram(
  70. UserDemographicsStatus::kSyncNotEnabled);
  71. return absl::nullopt;
  72. }
  73. UserDemographicsResult demographics_result =
  74. GetUserNoisedBirthYearAndGenderFromPrefs(
  75. profile_client_->GetNetworkTime(), profile_client_->GetPrefService());
  76. LogUserDemographicsStatusInHistogram(demographics_result.status());
  77. if (demographics_result.IsSuccess())
  78. return demographics_result.value();
  79. return absl::nullopt;
  80. }
  81. void DemographicMetricsProvider::ProvideCurrentSessionData(
  82. ChromeUserMetricsExtension* uma_proto) {
  83. ProvideSyncedUserNoisedBirthYearAndGender(uma_proto);
  84. }
  85. void DemographicMetricsProvider::
  86. ProvideSyncedUserNoisedBirthYearAndGenderToReport(ukm::Report* report) {
  87. ProvideSyncedUserNoisedBirthYearAndGender(report);
  88. }
  89. void DemographicMetricsProvider::LogUserDemographicsStatusInHistogram(
  90. UserDemographicsStatus status) {
  91. switch (metrics_service_type_) {
  92. case MetricsLogUploader::MetricServiceType::UMA:
  93. base::UmaHistogramEnumeration("UMA.UserDemographics.Status", status);
  94. // If the user demographics data was retrieved successfully, then the user
  95. // must be between the ages of |kUserDemographicsMinAgeInYears|+1=21 and
  96. // |kUserDemographicsMaxAgeInYears|=85, so the user is not a minor.
  97. base::UmaHistogramBoolean("UMA.UserDemographics.IsNoisedAgeOver21Under85",
  98. status == UserDemographicsStatus::kSuccess);
  99. return;
  100. case MetricsLogUploader::MetricServiceType::UKM:
  101. base::UmaHistogramEnumeration("UKM.UserDemographics.Status", status);
  102. return;
  103. }
  104. NOTREACHED();
  105. }
  106. } // namespace metrics