File: demographic_metrics_provider.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (139 lines) | stat: -rw-r--r-- 5,013 bytes parent folder | download | duplicates (3)
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