1 // Copyright 2019 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 "base/scoped_add_feature_flags.h"
6
7 #include <string_view>
8
9 #include "base/base_switches.h"
10 #include "base/command_line.h"
11 #include "base/containers/contains.h"
12 #include "base/strings/strcat.h"
13 #include "base/strings/string_util.h"
14
15 namespace base {
16
ScopedAddFeatureFlags(CommandLine * command_line)17 ScopedAddFeatureFlags::ScopedAddFeatureFlags(CommandLine* command_line)
18 : command_line_(command_line) {
19 std::string enabled_features =
20 command_line->GetSwitchValueASCII(switches::kEnableFeatures);
21 std::string disabled_features =
22 command_line->GetSwitchValueASCII(switches::kDisableFeatures);
23 for (std::string_view feature :
24 FeatureList::SplitFeatureListString(enabled_features)) {
25 enabled_features_.emplace_back(feature);
26 }
27 for (std::string_view feature :
28 FeatureList::SplitFeatureListString(disabled_features)) {
29 disabled_features_.emplace_back(feature);
30 }
31 }
32
~ScopedAddFeatureFlags()33 ScopedAddFeatureFlags::~ScopedAddFeatureFlags() {
34 command_line_->RemoveSwitch(switches::kEnableFeatures);
35 command_line_->AppendSwitchASCII(switches::kEnableFeatures,
36 JoinString(enabled_features_, ","));
37 command_line_->RemoveSwitch(switches::kDisableFeatures);
38 command_line_->AppendSwitchASCII(switches::kDisableFeatures,
39 JoinString(disabled_features_, ","));
40 }
41
EnableIfNotSet(const Feature & feature)42 void ScopedAddFeatureFlags::EnableIfNotSet(const Feature& feature) {
43 AddFeatureIfNotSet(feature, /*suffix=*/"", /*enable=*/true);
44 }
45
EnableIfNotSetWithParameter(const Feature & feature,std::string_view name,std::string_view value)46 void ScopedAddFeatureFlags::EnableIfNotSetWithParameter(
47 const Feature& feature,
48 std::string_view name,
49 std::string_view value) {
50 std::string suffix = StrCat({":", name, "/", value});
51 AddFeatureIfNotSet(feature, suffix, true /* enable */);
52 }
53
DisableIfNotSet(const Feature & feature)54 void ScopedAddFeatureFlags::DisableIfNotSet(const Feature& feature) {
55 AddFeatureIfNotSet(feature, /*suffix=*/"", /*enable=*/false);
56 }
57
IsEnabled(const Feature & feature)58 bool ScopedAddFeatureFlags::IsEnabled(const Feature& feature) {
59 return IsEnabledWithParameter(feature, /*parameter_name=*/"",
60 /*parameter_value=*/"");
61 }
62
IsEnabledWithParameter(const Feature & feature,std::string_view parameter_name,std::string_view parameter_value)63 bool ScopedAddFeatureFlags::IsEnabledWithParameter(
64 const Feature& feature,
65 std::string_view parameter_name,
66 std::string_view parameter_value) {
67 std::string feature_name = feature.name;
68 if (!parameter_name.empty()) {
69 StrAppend(&feature_name, {":", parameter_name, "/", parameter_value});
70 }
71 if (Contains(disabled_features_, feature_name))
72 return false;
73 if (Contains(enabled_features_, feature_name))
74 return true;
75 return feature.default_state == FEATURE_ENABLED_BY_DEFAULT;
76 }
77
AddFeatureIfNotSet(const Feature & feature,std::string_view suffix,bool enable)78 void ScopedAddFeatureFlags::AddFeatureIfNotSet(const Feature& feature,
79 std::string_view suffix,
80 bool enable) {
81 std::string feature_name = StrCat({feature.name, suffix});
82 if (Contains(enabled_features_, feature_name) ||
83 Contains(disabled_features_, feature_name)) {
84 return;
85 }
86 if (enable) {
87 enabled_features_.emplace_back(feature_name);
88 } else {
89 disabled_features_.emplace_back(feature_name);
90 }
91 }
92
93 } // namespace base
94