xref: /aosp_15_r20/external/cronet/components/cronet/android/cronet_base_feature.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 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.
4 
5 #include "components/cronet/android/cronet_base_feature.h"
6 
7 #include "base/debug/leak_annotations.h"
8 #include "base/feature_list.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/field_trial_params.h"
11 
12 namespace cronet {
13 
14 using ::org::chromium::net::httpflags::BaseFeatureOverrides;
15 
ApplyBaseFeatureOverrides(const BaseFeatureOverrides & overrides)16 void ApplyBaseFeatureOverrides(const BaseFeatureOverrides& overrides) {
17   if (base::FeatureList::GetInstance() != nullptr) {
18     LOG(WARNING) << "Not setting Cronet base::Feature overrides as "
19                     "base::Feature is already initialized";
20     return;
21   }
22 
23   // We need to ensure base::FieldTrialList is initialized, otherwise the call
24   // to base::FieldTrialList::CreateFieldTrial() below will crash.
25   {
26     // Intentional leak (singleton). Note that we can't use a static
27     // base::NoDestructor here because that would lead to the FieldTrialList
28     // singleton not getting properly reset between unit tests.
29     auto* const field_trial_list = new base::FieldTrialList();
30     ANNOTATE_LEAKING_OBJECT_PTR(field_trial_list);
31     (void)field_trial_list;
32   }
33 
34   auto feature_list = std::make_unique<base::FeatureList>();
35   for (const auto& [feature_name, feature_state] : overrides.feature_states()) {
36     // Cronet uses its own bespoke metrics logging system, and never reports
37     // base::FieldTrial data back to Finch. We still need to provide a
38     // FieldTrial to be able to register the base::Feature override and to
39     // associate params, so let's create a fake one with bogus names. This is
40     // similar in principle to how Chrome base::Features can be overridden from
41     // the command line, and in fact the naming scheme below is inspired by how
42     // base::FeatureList::InitializeFromCommandLine() generates fake field trial
43     // and group names, with an additional "Cronet" prefix.
44     const std::string field_trial_name = "CronetStudy" + feature_name;
45     const std::string field_trial_group = "CronetGroup" + feature_name;
46     auto* const field_trial = base::FieldTrialList::CreateFieldTrial(
47         field_trial_name, field_trial_group);
48     CHECK(field_trial != nullptr)
49         << "Unable to create field trial for feature: " << feature_name;
50     feature_list->RegisterFieldTrialOverride(
51         feature_name,
52         feature_state.has_enabled()
53             ? (feature_state.enabled()
54                    ? base::FeatureList::OVERRIDE_ENABLE_FEATURE
55                    : base::FeatureList::OVERRIDE_DISABLE_FEATURE)
56             : base::FeatureList::OVERRIDE_USE_DEFAULT,
57         field_trial);
58     if (!feature_state.params().empty()) {
59       base::AssociateFieldTrialParams(
60           field_trial_name, field_trial_group,
61           {feature_state.params().begin(), feature_state.params().end()});
62     }
63   }
64   base::FeatureList::SetInstance(std::move(feature_list));
65 }
66 
67 }  // namespace cronet
68