1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chrome_browser_field_trials.h"
9 #include "base/command_line.h"
10 #include "base/feature_list.h"
11 #include "base/files/file_util.h"
12 #include "base/metrics/field_trial.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_util.h"
15 #include "base/time/time.h"
16 #include "build/build_config.h"
17 #include "build/chromeos_buildflags.h"
18 #include "chrome/browser/metrics/chrome_browser_sampling_trials.h"
19 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
20 #include "chrome/browser/metrics/chrome_metrics_service_client.h"
21 #include "chrome/browser/ui/startup/first_run_service.h"
22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "components/metrics/metrics_pref_names.h"
25 #include "components/metrics/persistent_histograms.h"
26 #include "components/signin/public/base/signin_buildflags.h"
27 #include "components/version_info/version_info.h"
29 #if BUILDFLAG(IS_ANDROID)
30 #include "base/android/build_info.h"
31 #include "base/android/bundle_utils.h"
32 #include "base/task/thread_pool/environment_config.h"
33 #include "chrome/browser/android/flags/chrome_cached_flags.h"
34 #include "chrome/browser/android/signin/fre_mobile_identity_consistency_field_trial.h"
35 #include "chrome/browser/flags/android/chrome_feature_list.h"
36 #include "chrome/common/chrome_features.h"
39 #if BUILDFLAG(IS_CHROMEOS_ASH)
40 #include "chrome/common/channel_info.h"
41 #include "chromeos/ash/components/login/auth/recovery/recovery_utils.h"
42 #include "chromeos/ash/services/multidevice_setup/public/cpp/first_run_field_trial.h"
45 #if BUILDFLAG(IS_CHROMEOS_LACROS)
46 // GN doesn't understand conditional includes, so we need nogncheck here.
47 // See crbug.com/1125897.
48 #include "chromeos/startup/startup.h" // nogncheck
51 ChromeBrowserFieldTrials::ChromeBrowserFieldTrials(PrefService* local_state)
52 : local_state_(local_state) {
56 ChromeBrowserFieldTrials::~ChromeBrowserFieldTrials() = default;
58 void ChromeBrowserFieldTrials::OnVariationsSetupComplete() {
59 #if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS_LACROS)
60 // Persistent histograms must be enabled ASAP, but depends on Features.
61 // For non-Fuchsia platforms, it is enabled earlier on, and is not controlled
63 // See //chrome/app/chrome_main_delegate.cc.
64 bool histogram_init_and_cleanup = true;
65 #if BUILDFLAG(IS_CHROMEOS_LACROS)
66 // For Lacros, when prelaunching at login screen, we want to postpone the
67 // initialization and cleanup of persistent histograms to when the user has
68 // logged in and the cryptohome is accessible.
69 histogram_init_and_cleanup &= chromeos::IsLaunchedWithPostLoginParams();
71 base::FilePath metrics_dir;
72 if (histogram_init_and_cleanup) {
73 if (base::PathService::Get(chrome::DIR_USER_DATA, &metrics_dir)) {
74 InstantiatePersistentHistogramsWithFeaturesAndCleanup(metrics_dir);
79 #endif // BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS_LACROS)
82 void ChromeBrowserFieldTrials::SetUpClientSideFieldTrials(
84 const variations::EntropyProviders& entropy_providers,
85 base::FeatureList* feature_list) {
86 // Only create the fallback trials if there isn't already a variations seed
87 // being applied. This should occur during first run when first-run variations
88 // isn't supported. It's assumed that, if there is a seed, then it either
89 // contains the relevant studies, or is intentionally omitted, so no fallback
90 // is needed. The exception is for sampling trials. Fallback trials are
91 // created even if no variations seed was applied. This allows testing the
92 // fallback code by intentionally omitting the sampling trial from a
94 metrics::CreateFallbackSamplingTrialsIfNeeded(
95 entropy_providers.default_entropy(), feature_list);
96 metrics::CreateFallbackUkmSamplingTrialIfNeeded(
97 entropy_providers.default_entropy(), feature_list);
98 #if BUILDFLAG(IS_CHROMEOS_ASH)
99 // For this feature we will use the client-side trial for rollout. The
100 // server-side/Finch config will be used only as a kill-switch. If it's
101 // configured - it will override the local trial.
102 ash::CreateFallbackFieldTrialForRecovery(
103 chrome::GetChannel() == version_info::Channel::STABLE, feature_list);
106 #if BUILDFLAG(IS_CHROMEOS_ASH)
107 ash::multidevice_setup::CreateFirstRunFieldTrial(feature_list);
110 #if BUILDFLAG(ENABLE_DICE_SUPPORT) && !BUILDFLAG(IS_WIN)
111 FirstRunService::SetUpClientSideFieldTrialIfNeeded(
112 entropy_providers.default_entropy(), feature_list);
115 #if BUILDFLAG(IS_ANDROID)
116 // RegisterSyntheticTrials doesn't have access to entropy providers which are
117 // needed to verify group consistency for
118 // FREMobileIdentityConsistencySynthetic and decide whether to assign
119 // a variation ID to that study. To work around that - grab the variation ID
120 // here and perform the actual registration in RegisterSyntheticTrials().
121 fre_consistency_trial_variation_id_ =
122 fre_mobile_identity_consistency_field_trial::GetFREFieldTrialVariationId(
123 entropy_providers.low_entropy_value(),
124 entropy_providers.low_entropy_domain());
125 #endif // BUILDFLAG(IS_ANDROID)
128 void ChromeBrowserFieldTrials::RegisterSyntheticTrials() {
129 #if BUILDFLAG(IS_ANDROID)
130 static constexpr char kReachedCodeProfilerTrial[] =
131 "ReachedCodeProfilerSynthetic2";
132 std::string reached_code_profiler_group =
133 chrome::android::GetReachedCodeProfilerTrialGroup();
134 if (!reached_code_profiler_group.empty()) {
135 ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
136 kReachedCodeProfilerTrial, reached_code_profiler_group);
140 // BackgroundThreadPoolSynthetic field trial.
141 const char* group_name;
142 // Target group as indicated by finch feature.
143 bool feature_enabled =
144 base::FeatureList::IsEnabled(chrome::android::kBackgroundThreadPool);
145 // Whether the feature was overridden by either the commandline or Finch.
146 bool feature_overridden =
147 base::FeatureList::GetInstance()->IsFeatureOverridden(
148 chrome::android::kBackgroundThreadPool.name);
149 // Whether the feature was overridden manually via the commandline.
150 bool cmdline_overridden =
151 feature_overridden &&
152 base::FeatureList::GetInstance()->IsFeatureOverriddenFromCommandLine(
153 chrome::android::kBackgroundThreadPool.name);
154 // The finch feature value is cached by Java in a setting and applied via a
155 // command line flag. Check if this has happened -- it may not have happened
156 // if this is the first startup after the feature is enabled.
157 bool actually_enabled =
158 base::internal::CanUseBackgroundThreadTypeForWorkerThread();
159 // Use the default group if either the feature wasn't overridden or if the
160 // feature target state and actual state don't agree. Also separate users
161 // that override the feature via the commandline into separate groups.
162 if (actually_enabled != feature_enabled || !feature_overridden) {
163 group_name = "Default";
164 } else if (cmdline_overridden && feature_enabled) {
165 group_name = "ForceEnabled";
166 } else if (cmdline_overridden && !feature_enabled) {
167 group_name = "ForceDisabled";
168 } else if (feature_enabled) {
169 group_name = "Enabled";
171 group_name = "Disabled";
173 static constexpr char kBackgroundThreadPoolTrial[] =
174 "BackgroundThreadPoolSynthetic";
175 ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
176 kBackgroundThreadPoolTrial, group_name);
179 // MobileIdentityConsistencyFREVariationsSynthetic field trial.
180 // This trial experiments with different title and subtitle variation in
181 // the FRE UI. This is a follow up experiment to
182 // MobileIdentityConsistencyFRESynthetic.
183 static constexpr char kFREMobileIdentityConsistencyVariationsTrial[] =
184 "FREMobileIdentityConsistencyVariationsSynthetic";
185 const std::string variation_group =
186 fre_mobile_identity_consistency_field_trial::GetFREFieldTrialGroupName();
187 ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
188 kFREMobileIdentityConsistencyVariationsTrial, variation_group,
189 variations::SyntheticTrialAnnotationMode::kCurrentLog);
190 if (fre_consistency_trial_variation_id_ != variations::EMPTY_ID) {
191 variations::AssociateGoogleVariationID(
192 variations::GOOGLE_WEB_PROPERTIES_ANY_CONTEXT,
193 kFREMobileIdentityConsistencyVariationsTrial, variation_group,
194 fre_consistency_trial_variation_id_);
196 #endif // BUILDFLAG(IS_ANDROID)
197 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
198 FirstRunService::EnsureStickToFirstRunCohort();