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.
}
|