Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(299)

Side by Side Diff: components/flags_ui/flags_state.cc

Issue 2036193002: Allow overriding variation parameter via chrome://flags. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: After code review #1 Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/flags_ui/flags_state.h" 5 #include "components/flags_ui/flags_state.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/feature_list.h" 8 #include "base/feature_list.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/macros.h" 10 #include "base/macros.h"
11 #include "base/metrics/field_trial.h"
11 #include "base/stl_util.h" 12 #include "base/stl_util.h"
12 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h" 15 #include "base/values.h"
15 #include "build/build_config.h" 16 #include "build/build_config.h"
16 #include "components/flags_ui/feature_entry.h" 17 #include "components/flags_ui/feature_entry.h"
17 #include "components/flags_ui/flags_storage.h" 18 #include "components/flags_ui/flags_storage.h"
18 #include "components/flags_ui/flags_ui_switches.h" 19 #include "components/flags_ui/flags_ui_switches.h"
20 #include "components/variations/variations_associated_data.h"
19 #include "ui/base/l10n/l10n_util.h" 21 #include "ui/base/l10n/l10n_util.h"
20 22
21 namespace flags_ui { 23 namespace flags_ui {
22 24
23 namespace { 25 namespace {
24 26
25 // Convert switch constants to proper CommandLine::StringType strings. 27 // Convert switch constants to proper CommandLine::StringType strings.
26 base::CommandLine::StringType GetSwitchString(const std::string& flag) { 28 base::CommandLine::StringType GetSwitchString(const std::string& flag) {
27 base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM); 29 base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM);
28 cmd_line.AppendSwitch(flag); 30 cmd_line.AppendSwitch(flag);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 // Adds the internal names for the specified entry to |names|. 91 // Adds the internal names for the specified entry to |names|.
90 void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) { 92 void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) {
91 switch (e.type) { 93 switch (e.type) {
92 case FeatureEntry::SINGLE_VALUE: 94 case FeatureEntry::SINGLE_VALUE:
93 case FeatureEntry::SINGLE_DISABLE_VALUE: 95 case FeatureEntry::SINGLE_DISABLE_VALUE:
94 names->insert(e.internal_name); 96 names->insert(e.internal_name);
95 break; 97 break;
96 case FeatureEntry::MULTI_VALUE: 98 case FeatureEntry::MULTI_VALUE:
97 case FeatureEntry::ENABLE_DISABLE_VALUE: 99 case FeatureEntry::ENABLE_DISABLE_VALUE:
98 case FeatureEntry::FEATURE_VALUE: 100 case FeatureEntry::FEATURE_VALUE:
99 for (int i = 0; i < e.num_choices; ++i) 101 case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE:
100 names->insert(e.NameForChoice(i)); 102 for (int i = 0; i < e.num_options; ++i)
103 names->insert(e.NameForOption(i));
101 break; 104 break;
102 } 105 }
103 } 106 }
104 107
105 // Confirms that an entry is valid, used in a DCHECK in 108 // Confirms that an entry is valid, used in a DCHECK in
106 // SanitizeList below. 109 // SanitizeList below.
107 bool ValidateFeatureEntry(const FeatureEntry& e) { 110 bool ValidateFeatureEntry(const FeatureEntry& e) {
108 switch (e.type) { 111 switch (e.type) {
109 case FeatureEntry::SINGLE_VALUE: 112 case FeatureEntry::SINGLE_VALUE:
110 case FeatureEntry::SINGLE_DISABLE_VALUE: 113 case FeatureEntry::SINGLE_DISABLE_VALUE:
111 DCHECK_EQ(0, e.num_choices); 114 DCHECK_EQ(0, e.num_options);
112 DCHECK(!e.choices); 115 DCHECK(!e.choices);
113 return true; 116 return true;
114 case FeatureEntry::MULTI_VALUE: 117 case FeatureEntry::MULTI_VALUE:
115 DCHECK_GT(e.num_choices, 0); 118 DCHECK_GT(e.num_options, 0);
116 DCHECK(e.choices); 119 DCHECK(e.choices);
117 DCHECK(e.choices[0].command_line_switch); 120 DCHECK(e.ChoiceForOption(0).command_line_switch);
118 DCHECK_EQ('\0', e.choices[0].command_line_switch[0]); 121 DCHECK_EQ('\0', e.ChoiceForOption(0).command_line_switch[0]);
119 return true; 122 return true;
120 case FeatureEntry::ENABLE_DISABLE_VALUE: 123 case FeatureEntry::ENABLE_DISABLE_VALUE:
121 DCHECK_EQ(3, e.num_choices); 124 DCHECK_EQ(3, e.num_options);
122 DCHECK(!e.choices); 125 DCHECK(!e.choices);
123 DCHECK(e.command_line_switch); 126 DCHECK(e.command_line_switch);
124 DCHECK(e.command_line_value); 127 DCHECK(e.command_line_value);
125 DCHECK(e.disable_command_line_switch); 128 DCHECK(e.disable_command_line_switch);
126 DCHECK(e.disable_command_line_value); 129 DCHECK(e.disable_command_line_value);
127 return true; 130 return true;
128 case FeatureEntry::FEATURE_VALUE: 131 case FeatureEntry::FEATURE_VALUE:
129 DCHECK_EQ(3, e.num_choices); 132 DCHECK_EQ(3, e.num_options);
130 DCHECK(!e.choices); 133 DCHECK(!e.choices);
131 DCHECK(e.feature); 134 DCHECK(e.feature);
132 return true; 135 return true;
136 case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE:
137 DCHECK_GT(e.num_options, 2);
138 DCHECK(!e.choices);
139 DCHECK(e.feature);
140 DCHECK(e.feature_variations);
141 DCHECK(e.feature_trial_name);
142 return true;
133 } 143 }
134 NOTREACHED(); 144 NOTREACHED();
135 return false; 145 return false;
136 } 146 }
137 147
138 // Returns true if none of this entry's options have been enabled. 148 // Returns true if none of this entry's options have been enabled.
139 bool IsDefaultValue(const FeatureEntry& entry, 149 bool IsDefaultValue(const FeatureEntry& entry,
140 const std::set<std::string>& enabled_entries) { 150 const std::set<std::string>& enabled_entries) {
141 switch (entry.type) { 151 switch (entry.type) {
142 case FeatureEntry::SINGLE_VALUE: 152 case FeatureEntry::SINGLE_VALUE:
143 case FeatureEntry::SINGLE_DISABLE_VALUE: 153 case FeatureEntry::SINGLE_DISABLE_VALUE:
144 return enabled_entries.count(entry.internal_name) == 0; 154 return enabled_entries.count(entry.internal_name) == 0;
145 case FeatureEntry::MULTI_VALUE: 155 case FeatureEntry::MULTI_VALUE:
146 case FeatureEntry::ENABLE_DISABLE_VALUE: 156 case FeatureEntry::ENABLE_DISABLE_VALUE:
147 case FeatureEntry::FEATURE_VALUE: 157 case FeatureEntry::FEATURE_VALUE:
148 for (int i = 0; i < entry.num_choices; ++i) { 158 case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE:
149 if (enabled_entries.count(entry.NameForChoice(i)) > 0) 159 for (int i = 0; i < entry.num_options; ++i) {
160 if (enabled_entries.count(entry.NameForOption(i)) > 0)
150 return false; 161 return false;
151 } 162 }
152 return true; 163 return true;
153 } 164 }
154 NOTREACHED(); 165 NOTREACHED();
155 return true; 166 return true;
156 } 167 }
157 168
158 // Returns the Value representing the choice data in the specified entry. 169 // Returns the Value representing the choice data in the specified entry.
159 base::Value* CreateChoiceData(const FeatureEntry& entry, 170 base::Value* CreateOptionsData(const FeatureEntry& entry,
160 const std::set<std::string>& enabled_entries) { 171 const std::set<std::string>& enabled_entries) {
161 DCHECK(entry.type == FeatureEntry::MULTI_VALUE || 172 DCHECK(entry.type == FeatureEntry::MULTI_VALUE ||
162 entry.type == FeatureEntry::ENABLE_DISABLE_VALUE || 173 entry.type == FeatureEntry::ENABLE_DISABLE_VALUE ||
163 entry.type == FeatureEntry::FEATURE_VALUE); 174 entry.type == FeatureEntry::FEATURE_VALUE ||
175 entry.type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE);
164 base::ListValue* result = new base::ListValue; 176 base::ListValue* result = new base::ListValue;
165 for (int i = 0; i < entry.num_choices; ++i) { 177 for (int i = 0; i < entry.num_options; ++i) {
166 base::DictionaryValue* value = new base::DictionaryValue; 178 base::DictionaryValue* value = new base::DictionaryValue;
167 const std::string name = entry.NameForChoice(i); 179 const std::string name = entry.NameForOption(i);
168 value->SetString("internal_name", name); 180 value->SetString("internal_name", name);
169 value->SetString("description", entry.DescriptionForChoice(i)); 181 value->SetString("description", entry.DescriptionForOption(i));
170 value->SetBoolean("selected", enabled_entries.count(name) > 0); 182 value->SetBoolean("selected", enabled_entries.count(name) > 0);
171 result->Append(value); 183 result->Append(value);
172 } 184 }
173 return result; 185 return result;
174 } 186 }
175 187
188 void RegisterFeatureVariationParameters(
Alexei Svitkine (slow) 2016/06/10 15:46:49 Add a comment please.
jkrcal 2016/06/14 10:04:22 Done.
189 const std::string& feature_trial_name,
190 const FeatureEntry::FeatureVariation& feature_variation) {
191 std::map<std::string, std::string> params;
192 for (int i = 0; i < feature_variation.num_params; ++i) {
193 params[feature_variation.params[i].param_name] =
194 feature_variation.params[i].param_value;
195 }
196
197 bool success = variations::AssociateVariationParams(
198 feature_trial_name, kTrialGroupAboutFlags, params);
199 if (success) {
200 // Successful association also means that no group is created and
201 // selected for the trial. Thus, create the trial to make it active
202 // and to select the group.
Alexei Svitkine (slow) 2016/06/10 15:46:49 The code doesn't match the comment. "active" means
jkrcal 2016/06/14 10:04:22 Done.
203 // This way, the parameters cannot get overwritten in later phases
204 // (such as from the server).
205 base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
206 feature_trial_name, kTrialGroupAboutFlags);
Alexei Svitkine (slow) 2016/06/10 15:46:49 So, this doesn't do any Feature association with t
jkrcal 2016/06/14 10:04:22 No, it does not. Beyond the scope of this CL, IMO.
207 if (!trial) {
208 DLOG(WARNING) << "Could not create the trial " << feature_trial_name
209 << " with group " << kTrialGroupAboutFlags;
210 }
211 }
212 }
213
176 } // namespace 214 } // namespace
177 215
178 // Keeps track of affected switches for each FeatureEntry, based on which 216 // Keeps track of affected switches for each FeatureEntry, based on which
179 // choice is selected for it. 217 // choice is selected for it.
180 struct SwitchEntry { 218 struct SwitchEntry {
181 // Corresponding base::Feature to toggle. 219 // Corresponding base::Feature to toggle.
182 std::string feature_name; 220 std::string feature_name;
183 221
184 // If |feature_name| is not empty, the state (enable/disabled) to set. 222 // If |feature_name| is not empty, the state (enable/disabled) to set.
185 bool feature_state; 223 bool feature_state;
(...skipping 28 matching lines...) Expand all
214 std::map<std::string, SwitchEntry> name_to_switch_map; 252 std::map<std::string, SwitchEntry> name_to_switch_map;
215 for (size_t i = 0; i < num_feature_entries_; ++i) { 253 for (size_t i = 0; i < num_feature_entries_; ++i) {
216 const FeatureEntry& e = feature_entries_[i]; 254 const FeatureEntry& e = feature_entries_[i];
217 switch (e.type) { 255 switch (e.type) {
218 case FeatureEntry::SINGLE_VALUE: 256 case FeatureEntry::SINGLE_VALUE:
219 case FeatureEntry::SINGLE_DISABLE_VALUE: 257 case FeatureEntry::SINGLE_DISABLE_VALUE:
220 AddSwitchMapping(e.internal_name, e.command_line_switch, 258 AddSwitchMapping(e.internal_name, e.command_line_switch,
221 e.command_line_value, &name_to_switch_map); 259 e.command_line_value, &name_to_switch_map);
222 break; 260 break;
223 case FeatureEntry::MULTI_VALUE: 261 case FeatureEntry::MULTI_VALUE:
224 for (int j = 0; j < e.num_choices; ++j) { 262 for (int j = 0; j < e.num_options; ++j) {
225 AddSwitchMapping(e.NameForChoice(j), e.choices[j].command_line_switch, 263 AddSwitchMapping(
226 e.choices[j].command_line_value, 264 e.NameForOption(j), e.ChoiceForOption(j).command_line_switch,
227 &name_to_switch_map); 265 e.ChoiceForOption(j).command_line_value, &name_to_switch_map);
228 } 266 }
229 break; 267 break;
230 case FeatureEntry::ENABLE_DISABLE_VALUE: 268 case FeatureEntry::ENABLE_DISABLE_VALUE:
231 AddSwitchMapping(e.NameForChoice(0), std::string(), std::string(), 269 AddSwitchMapping(e.NameForOption(0), std::string(), std::string(),
232 &name_to_switch_map); 270 &name_to_switch_map);
233 AddSwitchMapping(e.NameForChoice(1), e.command_line_switch, 271 AddSwitchMapping(e.NameForOption(1), e.command_line_switch,
234 e.command_line_value, &name_to_switch_map); 272 e.command_line_value, &name_to_switch_map);
235 AddSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch, 273 AddSwitchMapping(e.NameForOption(2), e.disable_command_line_switch,
236 e.disable_command_line_value, &name_to_switch_map); 274 e.disable_command_line_value, &name_to_switch_map);
237 break; 275 break;
238 case FeatureEntry::FEATURE_VALUE: 276 case FeatureEntry::FEATURE_VALUE:
239 AddFeatureMapping(e.NameForChoice(0), std::string(), false, 277 case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE:
240 &name_to_switch_map); 278 for (int j = 0; j < e.num_options; ++j) {
241 AddFeatureMapping(e.NameForChoice(1), e.feature->name, true, 279 FeatureEntry::State state = e.StateForOption(j);
242 &name_to_switch_map); 280 if (state == FeatureEntry::State::DEFAULT) {
243 AddFeatureMapping(e.NameForChoice(2), e.feature->name, false, 281 AddFeatureMapping(e.NameForOption(j), std::string(), false,
244 &name_to_switch_map); 282 &name_to_switch_map);
283 } else {
284 AddFeatureMapping(e.NameForOption(j), e.feature->name,
285 state == FeatureEntry::State::ENABLED,
286 &name_to_switch_map);
287 }
288 }
245 break; 289 break;
246 } 290 }
247 } 291 }
248 292
249 AddSwitchesToCommandLine(enabled_entries, name_to_switch_map, sentinels, 293 AddSwitchesToCommandLine(enabled_entries, name_to_switch_map, sentinels,
250 command_line, enable_features_flag_name, 294 command_line, enable_features_flag_name,
251 disable_features_flag_name); 295 disable_features_flag_name);
252 } 296 }
253 297
254 bool FlagsState::IsRestartNeededToCommitChanges() { 298 bool FlagsState::IsRestartNeededToCommitChanges() {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 else 339 else
296 needs_restart_ |= (enabled_entries.erase(internal_name) > 0); 340 needs_restart_ |= (enabled_entries.erase(internal_name) > 0);
297 } else if (e->type == FeatureEntry::SINGLE_DISABLE_VALUE) { 341 } else if (e->type == FeatureEntry::SINGLE_DISABLE_VALUE) {
298 if (!enable) 342 if (!enable)
299 needs_restart_ |= enabled_entries.insert(internal_name).second; 343 needs_restart_ |= enabled_entries.insert(internal_name).second;
300 else 344 else
301 needs_restart_ |= (enabled_entries.erase(internal_name) > 0); 345 needs_restart_ |= (enabled_entries.erase(internal_name) > 0);
302 } else { 346 } else {
303 if (enable) { 347 if (enable) {
304 // Enable the first choice. 348 // Enable the first choice.
305 needs_restart_ |= enabled_entries.insert(e->NameForChoice(0)).second; 349 needs_restart_ |= enabled_entries.insert(e->NameForOption(0)).second;
306 } else { 350 } else {
307 // Find the currently enabled choice and disable it. 351 // Find the currently enabled choice and disable it.
308 for (int i = 0; i < e->num_choices; ++i) { 352 for (int i = 0; i < e->num_options; ++i) {
309 std::string choice_name = e->NameForChoice(i); 353 std::string choice_name = e->NameForOption(i);
310 if (enabled_entries.find(choice_name) != enabled_entries.end()) { 354 if (enabled_entries.find(choice_name) != enabled_entries.end()) {
311 needs_restart_ = true; 355 needs_restart_ = true;
312 enabled_entries.erase(choice_name); 356 enabled_entries.erase(choice_name);
313 // Continue on just in case there's a bug and more than one 357 // Continue on just in case there's a bug and more than one
314 // entry for this choice was enabled. 358 // entry for this choice was enabled.
315 } 359 }
316 } 360 }
317 } 361 }
318 } 362 }
319 363
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 std::set<std::string> no_entries; 414 std::set<std::string> no_entries;
371 flags_storage->SetFlags(no_entries); 415 flags_storage->SetFlags(no_entries);
372 } 416 }
373 417
374 void FlagsState::Reset() { 418 void FlagsState::Reset() {
375 needs_restart_ = false; 419 needs_restart_ = false;
376 flags_switches_.clear(); 420 flags_switches_.clear();
377 appended_switches_.clear(); 421 appended_switches_.clear();
378 } 422 }
379 423
424 void FlagsState::RegisterAllFeatureVariationParameters(
425 FlagsStorage* flags_storage) {
426 std::set<std::string> enabled_entries;
427 GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, &enabled_entries);
428
429 for (size_t i = 0; i < num_feature_entries_; ++i) {
430 const FeatureEntry& e = feature_entries_[i];
431 if (e.type == FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE) {
432 for (int j = 0; j < e.num_options; ++j) {
433 const FeatureEntry::FeatureVariation* variation =
434 e.VariationForOption(j);
435 if (enabled_entries.count(e.NameForOption(j)) && variation != nullptr) {
Alexei Svitkine (slow) 2016/06/10 15:46:49 Nit: Reverse the two checks, since != nullptr chec
jkrcal 2016/06/14 10:04:22 Done.
436 // If the option is selected by the user & has variation, register it.
437 RegisterFeatureVariationParameters(e.feature_trial_name, *variation);
438 }
439 }
440 }
441 }
442 }
443
380 void FlagsState::GetFlagFeatureEntries( 444 void FlagsState::GetFlagFeatureEntries(
381 FlagsStorage* flags_storage, 445 FlagsStorage* flags_storage,
382 FlagAccess access, 446 FlagAccess access,
383 base::ListValue* supported_entries, 447 base::ListValue* supported_entries,
384 base::ListValue* unsupported_entries, 448 base::ListValue* unsupported_entries,
385 base::Callback<bool(const FeatureEntry&)> skip_feature_entry) { 449 base::Callback<bool(const FeatureEntry&)> skip_feature_entry) {
386 std::set<std::string> enabled_entries; 450 std::set<std::string> enabled_entries;
387 GetSanitizedEnabledFlags(flags_storage, &enabled_entries); 451 GetSanitizedEnabledFlags(flags_storage, &enabled_entries);
388 452
389 int current_platform = GetCurrentPlatform(); 453 int current_platform = GetCurrentPlatform();
(...skipping 21 matching lines...) Expand all
411 case FeatureEntry::SINGLE_DISABLE_VALUE: 475 case FeatureEntry::SINGLE_DISABLE_VALUE:
412 data->SetBoolean( 476 data->SetBoolean(
413 "enabled", 477 "enabled",
414 (!is_default_value && entry.type == FeatureEntry::SINGLE_VALUE) || 478 (!is_default_value && entry.type == FeatureEntry::SINGLE_VALUE) ||
415 (is_default_value && 479 (is_default_value &&
416 entry.type == FeatureEntry::SINGLE_DISABLE_VALUE)); 480 entry.type == FeatureEntry::SINGLE_DISABLE_VALUE));
417 break; 481 break;
418 case FeatureEntry::MULTI_VALUE: 482 case FeatureEntry::MULTI_VALUE:
419 case FeatureEntry::ENABLE_DISABLE_VALUE: 483 case FeatureEntry::ENABLE_DISABLE_VALUE:
420 case FeatureEntry::FEATURE_VALUE: 484 case FeatureEntry::FEATURE_VALUE:
421 data->Set("choices", CreateChoiceData(entry, enabled_entries)); 485 case FeatureEntry::FEATURE_WITH_VARIATIONS_VALUE:
486 data->Set("options", CreateOptionsData(entry, enabled_entries));
422 break; 487 break;
423 } 488 }
424 489
425 bool supported = (entry.supported_platforms & current_platform) != 0; 490 bool supported = (entry.supported_platforms & current_platform) != 0;
426 #if defined(OS_CHROMEOS) 491 #if defined(OS_CHROMEOS)
427 if (access == kOwnerAccessToFlags && 492 if (access == kOwnerAccessToFlags &&
428 (entry.supported_platforms & kOsCrOSOwnerOnly) != 0) { 493 (entry.supported_platforms & kOsCrOSOwnerOnly) != 0) {
429 supported = true; 494 supported = true;
430 } 495 }
431 #endif 496 #endif
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 } 696 }
632 697
633 std::set<std::string> new_enabled_entries = 698 std::set<std::string> new_enabled_entries =
634 base::STLSetIntersection<std::set<std::string>>(platform_entries, 699 base::STLSetIntersection<std::set<std::string>>(platform_entries,
635 *result); 700 *result);
636 701
637 result->swap(new_enabled_entries); 702 result->swap(new_enabled_entries);
638 } 703 }
639 704
640 } // namespace flags_ui 705 } // namespace flags_ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698