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