File: chrome_feature_list_creator.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 (341 lines) | stat: -rw-r--r-- 14,759 bytes parent folder | download | duplicates (6)
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
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
// Copyright 2018 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/chrome_feature_list_creator.h"

#include <functional>
#include <set>
#include <vector>

#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/path_service.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/enterprise/browser_management/management_service_factory.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/metrics/chrome_metrics_services_manager_client.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/prefs/chrome_pref_service_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_result_codes.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/installer/util/google_update_settings.h"
#include "components/content_settings/core/common/features.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/language/core/browser/pref_names.h"
#include "components/metrics/clean_exit_beacon.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_state_manager.h"
#include "components/metrics_services_manager/metrics_services_manager.h"
#include "components/policy/core/common/policy_service.h"
#include "components/prefs/json_pref_store.h"
#include "components/prefs/pref_registry.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service_factory.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "components/safe_browsing/core/common/features.h"
#include "components/variations/pref_names.h"
#include "components/variations/service/variations_service.h"
#include "components/variations/variations_crash_keys.h"
#include "components/variations/variations_switches.h"
#include "components/webui/flags/flags_ui_pref_names.h"
#include "components/webui/flags/pref_service_flags_storage.h"
#include "content/public/common/content_switch_dependent_feature_overrides.h"
#include "content/public/common/content_switches.h"
#include "services/network/public/cpp/network_switches.h"
#include "ui/base/resource/resource_bundle.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
#include "chrome/browser/ash/settings/about_flags.h"
#include "chromeos/ash/components/dbus/dbus_thread_manager.h"
#endif  // BUILDFLAG(IS_CHROMEOS)

namespace {

// Returns a list of extra switch-dependent feature overrides to be applied
// during FeatureList initialization. Combines the overrides defined at the
// content layer with additional chrome layer overrides. The overrides
// specified in this list each cause a feature's state to be overridden based on
// the presence of a command line switch.
std::vector<base::FeatureList::FeatureOverrideInfo>
GetSwitchDependentFeatureOverrides(const base::CommandLine& command_line) {
  std::vector<base::FeatureList::FeatureOverrideInfo> overrides =
      content::GetSwitchDependentFeatureOverrides(command_line);

  // Describes a switch-dependent override. See also content layer overrides.
  struct SwitchDependentFeatureOverrideInfo {
    // Switch that the override depends upon. The override will be registered if
    // this switch is present.
    const char* switch_name;
    // Feature to override.
    const std::reference_wrapper<const base::Feature> feature;
    // State to override the feature with.
    base::FeatureList::OverrideState override_state;
  } chrome_layer_override_info[] = {
      // Override for --privacy-sandbox-ads-apis.
      {switches::kEnablePrivacySandboxAdsApis,
       std::cref(privacy_sandbox::kOverridePrivacySandboxSettingsLocalTesting),
       base::FeatureList::OVERRIDE_ENABLE_FEATURE},
      // Enable 3PCD tracking protection UI.
      {network::switches::kTestThirdPartyCookiePhaseout,
       std::cref(content_settings::features::kTrackingProtection3pcd),
       base::FeatureList::OVERRIDE_ENABLE_FEATURE},
  };

  for (const auto& info : chrome_layer_override_info) {
    if (command_line.HasSwitch(info.switch_name)) {
      overrides.emplace_back(info.feature, info.override_state);
    }
  }
  return overrides;
}

}  // namespace

ChromeFeatureListCreator::ChromeFeatureListCreator() = default;

ChromeFeatureListCreator::~ChromeFeatureListCreator() = default;

void ChromeFeatureListCreator::CreateFeatureList() {
  // Get the variation IDs passed through the command line. This is done early
  // on because ConvertFlagsToSwitches() will append to the command line
  // the variation IDs from flags (so that they are visible in about://version).
  // This will be passed on to `VariationsService::SetUpFieldTrials()`, which
  // will manually fetch the variation IDs from flags (hence the reason we do
  // not pass the mutated command line, otherwise the IDs will be duplicated).
  // It also distinguishes between variation IDs coming from the command line
  // and from flags, so we cannot rely on simply putting them all in the
  // command line.
  const std::string command_line_variation_ids =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          variations::switches::kForceVariationIds);
  CreatePrefService();
  ConvertFlagsToSwitches();
  CreateMetricsServices();
  SetupInitialPrefs();
  SetUpFieldTrials(command_line_variation_ids);
}

void ChromeFeatureListCreator::SetApplicationLocale(const std::string& locale) {
  actual_locale_ = locale;
  metrics_services_manager_->GetVariationsService()->EnsureLocaleEquals(locale);
}

void ChromeFeatureListCreator::OverrideCachedUIStrings() {
  metrics_services_manager_->GetVariationsService()->OverrideCachedUIStrings();
}

metrics_services_manager::MetricsServicesManagerClient*
ChromeFeatureListCreator::GetMetricsServicesManagerClient() {
  return metrics_services_manager_client_;
}

std::unique_ptr<PrefService> ChromeFeatureListCreator::TakePrefService() {
  return std::move(local_state_);
}

std::unique_ptr<metrics_services_manager::MetricsServicesManager>
ChromeFeatureListCreator::TakeMetricsServicesManager() {
  return std::move(metrics_services_manager_);
}

std::unique_ptr<policy::ChromeBrowserPolicyConnector>
ChromeFeatureListCreator::TakeChromeBrowserPolicyConnector() {
  return std::move(browser_policy_connector_);
}

#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
std::unique_ptr<installer::InitialPreferences>
ChromeFeatureListCreator::TakeInitialPrefs() {
  return std::move(installer_initial_prefs_);
}
#endif

void ChromeFeatureListCreator::CreatePrefService() {
  base::FilePath local_state_file;
  bool result =
      base::PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_file);
  DCHECK(result);

#if BUILDFLAG(IS_ANDROID)
  base::UmaHistogramBoolean("UMA.Startup.LocalStateFileExistence",
                            base::PathExists(local_state_file));
#endif  // BUILDFLAG(IS_ANDROID)

  auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>();
  RegisterLocalState(pref_registry.get());

#if BUILDFLAG(IS_CHROMEOS)
  // DBus must be initialized before constructing the policy connector.
  CHECK(ash::DBusThreadManager::IsInitialized());
  browser_policy_connector_ =
      std::make_unique<policy::BrowserPolicyConnectorAsh>();
#else
  browser_policy_connector_ =
      std::make_unique<policy::ChromeBrowserPolicyConnector>();
#endif  // BUILDFLAG(IS_CHROMEOS)

  // ManagementService needs Local State but creating local state needs
  // ManagementService, instantiate the underlying PrefStore early and share it
  // between both.
  auto local_state_pref_store =
      base::MakeRefCounted<JsonPrefStore>(local_state_file);

  // Try and read the local state prefs, if it succeeds, use it as the
  // ManagementService's cache.
  if (local_state_pref_store->ReadPrefs() ==
      JsonPrefStore::PREF_READ_ERROR_NONE) {
    auto* platform_management_service =
        policy::ManagementServiceFactory::GetForPlatform();
    platform_management_service->UsePrefStoreAsCache(local_state_pref_store);
  }

  local_state_ = chrome_prefs::CreateLocalState(
      local_state_file, local_state_pref_store,
      browser_policy_connector_->GetPolicyService(), std::move(pref_registry),
      browser_policy_connector_.get());

  // Apply local test policies from the kLocalTestPoliciesForNextStartup pref if
  // there are any.
  browser_policy_connector_->MaybeApplyLocalTestPolicies(local_state_.get());

// TODO(asvitkine): This is done here so that the pref is set before
// VariationsService queries the locale. This should potentially be moved to
// somewhere better, e.g. as a helper in first_run namespace.
#if BUILDFLAG(IS_WIN)
  if (first_run::IsChromeFirstRun()) {
    // During first run we read the google_update registry key to find what
    // language the user selected when downloading the installer. This
    // becomes our default language in the prefs.
    // Other platforms obey the system locale.
    std::wstring install_lang;
    if (GoogleUpdateSettings::GetLanguage(&install_lang)) {
      local_state_->SetString(language::prefs::kApplicationLocale,
                              base::WideToASCII(install_lang));
    }
  }
#endif  // BUILDFLAG(IS_WIN)
}

void ChromeFeatureListCreator::ConvertFlagsToSwitches() {
  // Convert active flags into switches. This needs to be done before
  // ui::ResourceBundle::InitSharedInstanceWithLocale as some loaded resources
  // are affected by experiment flags (--touch-optimized-ui in particular).
  DCHECK(!ui::ResourceBundle::HasSharedInstance());
  TRACE_EVENT0("startup", "ChromeFeatureListCreator::ConvertFlagsToSwitches");

#if BUILDFLAG(IS_CHROMEOS)
  // On Chrome OS, flags are passed on the command line when Chrome gets
  // launched by session_manager. There are separate sets of flags for the login
  // screen environment and user sessions. session_manager populates the former
  // from signed device settings, while flags for user session are stored in
  // preferences and applied via a chrome restart upon user login, see
  // UserSessionManager::RestartToApplyPerSessionFlagsIfNeed for the latter.
  ash::about_flags::ReadOnlyFlagsStorage flags_storage(
      base::CommandLine::ForCurrentProcess());
#else
  flags_ui::PrefServiceFlagsStorage flags_storage(local_state_.get());
#endif  // BUILDFLAG(IS_CHROMEOS)

  about_flags::ConvertFlagsToSwitches(&flags_storage,
                                      base::CommandLine::ForCurrentProcess(),
                                      flags_ui::kAddSentinels);
}

void ChromeFeatureListCreator::SetUpFieldTrials(
    const std::string& command_line_variation_ids) {
  browser_field_trials_ =
      std::make_unique<ChromeBrowserFieldTrials>(local_state_.get());

  metrics_services_manager_->InstantiateFieldTrialList();
  auto feature_list = std::make_unique<base::FeatureList>();
#if BUILDFLAG(IS_CHROMEOS)
  // On Chrome OS, the platform needs to be able to access the
  // FeatureList::Accessor. On other platforms, this API should not be used.
  cros_feature_list_accessor_ = feature_list->ConstructAccessor();
#endif  // BUILDFLAG(IS_CHROMEOS)

  // Associate parameters chosen in about:flags and create trial/group for them.
  flags_ui::PrefServiceFlagsStorage flags_storage(local_state_.get());
  std::vector<std::string> variation_ids =
      about_flags::RegisterAllFeatureVariationParameters(&flags_storage,
                                                         feature_list.get());

  variations::VariationsService* variations_service =
      metrics_services_manager_->GetVariationsService();
  variations_service->SetUpFieldTrials(
      variation_ids, command_line_variation_ids,
      GetSwitchDependentFeatureOverrides(
          *base::CommandLine::ForCurrentProcess()),
      std::move(feature_list), browser_field_trials_.get());
  variations::InitCrashKeys();
}

void ChromeFeatureListCreator::CreateMetricsServices() {
  auto client =
      std::make_unique<ChromeMetricsServicesManagerClient>(local_state_.get());
  metrics_services_manager_client_ = client.get();
  metrics_services_manager_ =
      std::make_unique<metrics_services_manager::MetricsServicesManager>(
          std::move(client));
}

void ChromeFeatureListCreator::SetupInitialPrefs() {
// Android does first run in Java instead of native.
// Chrome OS has its own out-of-box-experience code.
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
  // On first run, we need to process the predictor preferences before the
  // browser's profile_manager object is created, but after ResourceBundle
  // is initialized.
  // If the user specifies an initial preferences file, it is assumed that
  // they want to reset the preferences regardless of whether it's the
  // first run.
  if (!first_run::IsChromeFirstRun()) {
    return;
  }

  installer_initial_prefs_ = first_run::LoadInitialPrefs();
  if (!installer_initial_prefs_) {
    return;
  }

  // Store the initial VariationsService seed in local state, if it exists
  // in master prefs. Note: The getters we call remove them from the installer
  // master prefs, which is why both the seed and signature are retrieved here
  // and not within the ifs below.
  std::string compressed_variations_seed =
      installer_initial_prefs_->GetCompressedVariationsSeed();
  std::string variations_seed_signature =
      installer_initial_prefs_->GetVariationsSeedSignature();

  if (!compressed_variations_seed.empty()) {
    local_state_->SetString(variations::prefs::kVariationsCompressedSeed,
                            compressed_variations_seed);

    if (!variations_seed_signature.empty()) {
      local_state_->SetString(variations::prefs::kVariationsSeedSignature,
                              variations_seed_signature);
    }
    // Set the variation seed date to the current system time. If the user's
    // clock is incorrect, this may cause some field trial expiry checks to
    // not do the right thing until the next seed update from the server,
    // when this value will be updated.
    local_state_->SetInt64(variations::prefs::kVariationsSeedDate,
                           base::Time::Now().ToInternalValue());
  }
#endif  // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
}