File: metrics_reporting_state.cc

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (227 lines) | stat: -rw-r--r-- 9,558 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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// Copyright 2012 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/metrics_reporting_state.h"

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
#include "chrome/common/pref_names.h"
#include "chrome/installer/util/google_update_settings.h"
#include "components/crash/core/common/crash_keys.h"
#include "components/metrics/cloned_install_detector.h"
#include "components/metrics/entropy_state.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics_services_manager/metrics_services_manager.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
#include "chrome/browser/browser_process_platform_part.h"
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_ANDROID)
#include "components/policy/core/common/features.h"
#endif  // BUILDFLAG(IS_ANDROID)

namespace {

enum MetricsReportingChangeHistogramValue {
  METRICS_REPORTING_ERROR,
  METRICS_REPORTING_DISABLED,
  METRICS_REPORTING_ENABLED,
  METRICS_REPORTING_MAX
};

void RecordMetricsReportingHistogramValue(
    MetricsReportingChangeHistogramValue value) {
  UMA_HISTOGRAM_ENUMERATION(
      "UMA.MetricsReporting.Toggle", value, METRICS_REPORTING_MAX);
}

// Tries to set metrics reporting status to |enabled| and returns whatever is
// the result of the update.
bool SetGoogleUpdateSettings(bool enabled) {
  GoogleUpdateSettings::SetCollectStatsConsent(enabled);
  bool updated_pref = GoogleUpdateSettings::GetCollectStatsConsent();
  if (enabled != updated_pref)
    DVLOG(1) << "Unable to set metrics reporting status to " << enabled;

  return updated_pref;
}

// Does the necessary changes for MetricsReportingEnabled changes which needs
// to be done in the main thread.
// As arguments this function gets:
//  |to_update_pref| which indicates what the desired update should be,
//  |callback_fn| is the callback function to be called in the end,
//  |called_from| is from where the call was made,
//  |updated_pref| is the result of attempted update.
// Update considers to be successful if |to_update_pref| and |updated_pref| are
// the same.
void SetMetricsReporting(bool to_update_pref,
                         OnMetricsReportingCallbackType callback_fn,
                         ChangeMetricsReportingStateCalledFrom called_from,
                         bool updated_pref) {
  g_browser_process->local_state()->SetBoolean(
      metrics::prefs::kMetricsReportingEnabled, updated_pref);

  UpdateMetricsPrefsOnPermissionChange(updated_pref, called_from);

  // Uses the current state of whether reporting is enabled to enable services.
  g_browser_process->GetMetricsServicesManager()->UpdateUploadPermissions();

  if (to_update_pref == updated_pref) {
    RecordMetricsReportingHistogramValue(updated_pref ?
        METRICS_REPORTING_ENABLED : METRICS_REPORTING_DISABLED);
  } else {
    RecordMetricsReportingHistogramValue(METRICS_REPORTING_ERROR);
  }
  if (!callback_fn.is_null()) {
    std::move(callback_fn).Run(updated_pref);
  }
}

}  // namespace

void ChangeMetricsReportingState(
    bool enabled,
    ChangeMetricsReportingStateCalledFrom called_from) {
  ChangeMetricsReportingStateWithReply(
      enabled, OnMetricsReportingCallbackType(), called_from);
}

// TODO(gayane): Instead of checking policy before setting the metrics pref set
// the pref and register for notifications for the rest of the changes.
void ChangeMetricsReportingStateWithReply(
    bool enabled,
    OnMetricsReportingCallbackType callback_fn,
    ChangeMetricsReportingStateCalledFrom called_from) {
#if !BUILDFLAG(IS_ANDROID)
  // Chrome OS manages metrics settings externally and changes to reporting
  // should be propagated to metrics service regardless if the policy is managed
  // or not.
  // TODO(crbug.com/40232452): Possibly change |is_chrome_os| to use
  // BUILDFLAG(IS_CHROMEOS).
  bool is_chrome_os =
      (called_from ==
       ChangeMetricsReportingStateCalledFrom::kCrosMetricsSettingsChange) ||
      (called_from ==
       ChangeMetricsReportingStateCalledFrom::kCrosMetricsSettingsCreated) ||
      (called_from ==
       ChangeMetricsReportingStateCalledFrom::kCrosMetricsPreConsent);
  if (IsMetricsReportingPolicyManaged() && !is_chrome_os) {
    if (!callback_fn.is_null()) {
      const bool metrics_enabled =
          ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
      std::move(callback_fn).Run(metrics_enabled);
    }
    return;
  }
#endif
  GoogleUpdateSettings::CollectStatsConsentTaskRunner()
      ->PostTaskAndReplyWithResult(
          FROM_HERE, base::BindOnce(&SetGoogleUpdateSettings, enabled),
          base::BindOnce(&SetMetricsReporting, enabled, std::move(callback_fn),
                         called_from));
}

void UpdateMetricsPrefsOnPermissionChange(
    bool metrics_enabled,
    ChangeMetricsReportingStateCalledFrom called_from) {
  // On Chrome OS settings creation, nothing should be performed (the metrics
  // service is simply being initialized). Otherwise, for users who have
  // metrics reporting disabled, their client ID and low entropy sources would
  // be cleared on each log in. For users who have metrics reporting enabled,
  // their stability metrics and histogram data would be cleared.
  if (called_from ==
      ChangeMetricsReportingStateCalledFrom::kCrosMetricsSettingsCreated) {
    return;
  }
  if (metrics_enabled) {
    // When a user opts in to the metrics reporting service, the previously
    // collected data should be cleared to ensure that nothing is reported
    // before a user opts in and all reported data is accurate.
    g_browser_process->metrics_service()->ClearSavedStabilityMetrics();
    if (called_from == ChangeMetricsReportingStateCalledFrom::kUiSettings) {
      ClearPreviouslyCollectedMetricsData();
    }
    return;
  }
#if BUILDFLAG(IS_ANDROID)
  // When a user disables metrics reporting on Android Chrome, the new
  // sampling trial should be used to determine whether the client is sampled
  // in or out (if the user ever re-enables metrics reporting).
  //
  // Existing metrics-reporting-enabled clients (i.e. the users without this
  // pref set) do not use the new sampling trial; they continue to use
  // MetricsAndCrashSampling. However, if such a user disables metrics
  // reporting and later re-enables it, they will start using the new trial.
  //
  // See crbug/1306481 and the comment above |kUsePostFREFixSamplingTrial| in
  // components/metrics/metrics_pref_names.cc for more details.
  g_browser_process->local_state()->SetBoolean(
      metrics::prefs::kUsePostFREFixSamplingTrial, true);
#endif  // BUILDFLAG(IS_ANDROID)

  // Clear the client id and low entropy sources pref when the user opts out
  // from a non-FRE source. In the FRE flow the entropy source is not cleared
  // since no data has been uploaded yet.
  // Note: This will not affect the running state (e.g. field trial
  // randomization), as the pref is only read on startup.

  UMA_HISTOGRAM_BOOLEAN("UMA.ClientIdCleared", true);

  PrefService* local_state = g_browser_process->local_state();

  local_state->ClearPref(metrics::prefs::kMetricsClientID);
  local_state->ClearPref(metrics::prefs::kMetricsProvisionalClientID);
  local_state->ClearPref(metrics::prefs::kMetricsLogRecordId);

  // Don't clear the entropy state if the user opted out in the FRE. This is to
  // prevent experiments that have been randomized based on the low-entropy
  // source from having their state re-rolled on a subsequent session.
  if (called_from != ChangeMetricsReportingStateCalledFrom::kUiFirstRun) {
    metrics::EntropyState::ClearPrefs(local_state);
  }
  metrics::ClonedInstallDetector::ClearClonedInstallInfo(local_state);
  local_state->ClearPref(metrics::prefs::kMetricsReportingEnabledTimestamp);
  crash_keys::ClearMetricsClientId();
}

void ApplyMetricsReportingPolicy() {
  GoogleUpdateSettings::CollectStatsConsentTaskRunner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          base::IgnoreResult(&GoogleUpdateSettings::SetCollectStatsConsent),
          ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled()));
}

bool IsMetricsReportingPolicyManaged() {
#if BUILDFLAG(IS_CHROMEOS)
  policy::BrowserPolicyConnectorAsh* policy_connector =
      g_browser_process->platform_part()->browser_policy_connector_ash();
  return policy_connector->IsDeviceEnterpriseManaged();
#else
  const PrefService* pref_service = g_browser_process->local_state();
  const PrefService::Preference* pref =
      pref_service->FindPreference(metrics::prefs::kMetricsReportingEnabled);
  return pref && pref->IsManaged();
#endif  // BUILDFLAG(IS_CHROMEOS)
}

void ClearPreviouslyCollectedMetricsData() {
  // Mark histogram data that was collected during the current session up until
  // now as reported so that they are not included in the next log.
  g_browser_process->metrics_service()->MarkCurrentHistogramsAsReported();
  // Note: There is no need to clear User Actions as they do not get recorded
  // when metrics reporting is disabled.
}