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

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

Issue 1411453004: Componentize internal class FlagsState in flags_ui component. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@feature_entry
Patch Set: Fix compilation on Win32 Created 5 years, 1 month 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "components/flags_ui/flags_state.h"
6
7 #include "base/callback.h"
8 #include "base/feature_list.h"
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "build/build_config.h"
15 #include "components/flags_ui/feature_entry.h"
16 #include "components/flags_ui/flags_storage.h"
17 #include "components/flags_ui/flags_ui_switches.h"
18 #include "ui/base/l10n/l10n_util.h"
19
20 namespace flags_ui {
21
22 namespace {
23
24 const struct {
Alexei Svitkine (slow) 2015/11/16 21:52:54 Nit: I'd define it next to the function that uses
sdefresne 2015/11/17 16:28:56 Done.
25 unsigned bit;
26 const char* const name;
27 } kBitsToOs[] = {
28 {kOsMac, "Mac"},
29 {kOsWin, "Windows"},
30 {kOsLinux, "Linux"},
31 {kOsCrOS, "Chrome OS"},
32 {kOsAndroid, "Android"},
33 {kOsCrOSOwnerOnly, "Chrome OS (owner only)"},
34 };
35
36 // Convert switch constants to proper CommandLine::StringType strings.
37 base::CommandLine::StringType GetSwitchString(const std::string& flag) {
38 base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM);
39 cmd_line.AppendSwitch(flag);
40 DCHECK_EQ(2U, cmd_line.argv().size());
41 return cmd_line.argv()[1];
42 }
43
44 // Scoops flags from a command line.
Alexei Svitkine (slow) 2015/11/16 21:52:54 Nit: Expand the comment to mention the two new par
sdefresne 2015/11/17 16:28:56 Done.
45 std::set<base::CommandLine::StringType> ExtractFlagsFromCommandLine(
46 const base::CommandLine& cmdline,
47 const char* extra_flag_sentinel_begin_flag_name,
48 const char* extra_flag_sentinel_end_flag_name) {
49 DCHECK_EQ(!!extra_flag_sentinel_begin_flag_name,
50 !!extra_flag_sentinel_end_flag_name);
51 std::set<base::CommandLine::StringType> flags;
52 // First do the ones between --flag-switches-begin and --flag-switches-end.
53 base::CommandLine::StringVector::const_iterator first =
54 std::find(cmdline.argv().begin(), cmdline.argv().end(),
55 GetSwitchString(switches::kFlagSwitchesBegin));
56 base::CommandLine::StringVector::const_iterator last =
57 std::find(cmdline.argv().begin(), cmdline.argv().end(),
58 GetSwitchString(switches::kFlagSwitchesEnd));
59 if (first != cmdline.argv().end() && last != cmdline.argv().end())
60 flags.insert(first + 1, last);
61 if (extra_flag_sentinel_begin_flag_name &&
62 extra_flag_sentinel_end_flag_name) {
63 // Then add those between the extra sentinels.
Alexei Svitkine (slow) 2015/11/16 21:52:54 Nit: Move this comment above the outside if and ad
sdefresne 2015/11/17 16:28:56 Done.
64 first = std::find(cmdline.argv().begin(), cmdline.argv().end(),
65 GetSwitchString(extra_flag_sentinel_begin_flag_name));
66 last = std::find(cmdline.argv().begin(), cmdline.argv().end(),
67 GetSwitchString(extra_flag_sentinel_end_flag_name));
68 if (first != cmdline.argv().end() && last != cmdline.argv().end())
69 flags.insert(first + 1, last);
70 }
71 return flags;
72 }
73
74 // Adds a |StringValue| to |list| for each platform where |bitmask| indicates
75 // whether the entry is available on that platform.
76 void AddOsStrings(unsigned bitmask, base::ListValue* list) {
77 for (size_t i = 0; i < arraysize(kBitsToOs); ++i) {
78 if (bitmask & kBitsToOs[i].bit)
79 list->Append(new base::StringValue(kBitsToOs[i].name));
80 }
81 }
82
83 // Adds the internal names for the specified entry to |names|.
84 void AddInternalName(const FeatureEntry& e, std::set<std::string>* names) {
85 switch (e.type) {
86 case FeatureEntry::SINGLE_VALUE:
87 case FeatureEntry::SINGLE_DISABLE_VALUE:
88 names->insert(e.internal_name);
89 break;
90 case FeatureEntry::MULTI_VALUE:
91 case FeatureEntry::ENABLE_DISABLE_VALUE:
92 case FeatureEntry::FEATURE_VALUE:
93 for (int i = 0; i < e.num_choices; ++i)
94 names->insert(e.NameForChoice(i));
95 break;
96 }
97 }
98
99 // Confirms that an entry is valid, used in a DCHECK in
100 // SanitizeList below.
101 bool ValidateFeatureEntry(const FeatureEntry& e) {
102 switch (e.type) {
103 case FeatureEntry::SINGLE_VALUE:
104 case FeatureEntry::SINGLE_DISABLE_VALUE:
105 DCHECK_EQ(0, e.num_choices);
106 DCHECK(!e.choices);
107 return true;
108 case FeatureEntry::MULTI_VALUE:
109 DCHECK_GT(e.num_choices, 0);
110 DCHECK(e.choices);
111 DCHECK(e.choices[0].command_line_switch);
112 DCHECK_EQ('\0', e.choices[0].command_line_switch[0]);
113 return true;
114 case FeatureEntry::ENABLE_DISABLE_VALUE:
115 DCHECK_EQ(3, e.num_choices);
116 DCHECK(!e.choices);
117 DCHECK(e.command_line_switch);
118 DCHECK(e.command_line_value);
119 DCHECK(e.disable_command_line_switch);
120 DCHECK(e.disable_command_line_value);
121 return true;
122 case FeatureEntry::FEATURE_VALUE:
123 DCHECK_EQ(3, e.num_choices);
124 DCHECK(!e.choices);
125 DCHECK(e.feature);
126 return true;
127 }
128 NOTREACHED();
129 return false;
130 }
131
132 // Returns true if none of this entry's options have been enabled.
133 bool IsDefaultValue(const FeatureEntry& entry,
134 const std::set<std::string>& enabled_entries) {
135 switch (entry.type) {
136 case FeatureEntry::SINGLE_VALUE:
137 case FeatureEntry::SINGLE_DISABLE_VALUE:
138 return enabled_entries.count(entry.internal_name) == 0;
139 case FeatureEntry::MULTI_VALUE:
140 case FeatureEntry::ENABLE_DISABLE_VALUE:
141 case FeatureEntry::FEATURE_VALUE:
142 for (int i = 0; i < entry.num_choices; ++i) {
143 if (enabled_entries.count(entry.NameForChoice(i)) > 0)
144 return false;
145 }
146 return true;
147 }
148 NOTREACHED();
149 return true;
150 }
151
152 // Returns the Value representing the choice data in the specified entry.
153 base::Value* CreateChoiceData(const FeatureEntry& entry,
154 const std::set<std::string>& enabled_entries) {
155 DCHECK(entry.type == FeatureEntry::MULTI_VALUE ||
156 entry.type == FeatureEntry::ENABLE_DISABLE_VALUE ||
157 entry.type == FeatureEntry::FEATURE_VALUE);
158 base::ListValue* result = new base::ListValue;
159 for (int i = 0; i < entry.num_choices; ++i) {
160 base::DictionaryValue* value = new base::DictionaryValue;
161 const std::string name = entry.NameForChoice(i);
162 value->SetString("internal_name", name);
163 value->SetString("description", entry.DescriptionForChoice(i));
164 value->SetBoolean("selected", enabled_entries.count(name) > 0);
165 result->Append(value);
166 }
167 return result;
168 }
169
170 } // namespace
171
172 // Keeps track of affected switches for each FeatureEntry, based on which
173 // choice is selected for it.
174 struct SwitchEntry {
175 // Corresponding base::Feature to toggle.
176 std::string feature_name;
177
178 // If |feature_name| is not empty, the state (enable/disabled) to set.
179 bool feature_state;
180
181 // The name of the switch to add.
182 std::string switch_name;
183
184 // If |switch_name| is not empty, the value of the switch to set.
185 std::string switch_value;
186
187 SwitchEntry() : feature_state(false) {}
188 };
189
190 FlagsState::FlagsState(const FeatureEntry* feature_entries,
191 size_t num_feature_entries)
192 : feature_entries_(feature_entries),
193 num_feature_entries_(num_feature_entries),
194 needs_restart_(false) {}
195
196 FlagsState::~FlagsState() {}
197
198 void FlagsState::ConvertFlagsToSwitches(
199 FlagsStorage* flags_storage,
200 base::CommandLine* command_line,
201 SentinelsMode sentinels,
202 const char* enable_features_flag_name,
203 const char* disable_features_flag_name) {
204 std::set<std::string> enabled_entries;
205
206 GetSanitizedEnabledFlagsForCurrentPlatform(flags_storage, &enabled_entries);
207
208 std::map<std::string, SwitchEntry> name_to_switch_map;
209 for (size_t i = 0; i < num_feature_entries_; ++i) {
210 const FeatureEntry& e = feature_entries_[i];
211 switch (e.type) {
212 case FeatureEntry::SINGLE_VALUE:
213 case FeatureEntry::SINGLE_DISABLE_VALUE:
214 AddSwitchMapping(e.internal_name, e.command_line_switch,
215 e.command_line_value, &name_to_switch_map);
216 break;
217 case FeatureEntry::MULTI_VALUE:
218 for (int j = 0; j < e.num_choices; ++j) {
219 AddSwitchMapping(e.NameForChoice(j), e.choices[j].command_line_switch,
220 e.choices[j].command_line_value,
221 &name_to_switch_map);
222 }
223 break;
224 case FeatureEntry::ENABLE_DISABLE_VALUE:
225 AddSwitchMapping(e.NameForChoice(0), std::string(), std::string(),
226 &name_to_switch_map);
227 AddSwitchMapping(e.NameForChoice(1), e.command_line_switch,
228 e.command_line_value, &name_to_switch_map);
229 AddSwitchMapping(e.NameForChoice(2), e.disable_command_line_switch,
230 e.disable_command_line_value, &name_to_switch_map);
231 break;
232 case FeatureEntry::FEATURE_VALUE:
233 AddFeatureMapping(e.NameForChoice(0), std::string(), false,
234 &name_to_switch_map);
235 AddFeatureMapping(e.NameForChoice(1), e.feature->name, true,
236 &name_to_switch_map);
237 AddFeatureMapping(e.NameForChoice(2), e.feature->name, false,
238 &name_to_switch_map);
239 break;
240 }
241 }
242
243 AddSwitchesToCommandLine(enabled_entries, name_to_switch_map, sentinels,
244 command_line, enable_features_flag_name,
245 disable_features_flag_name);
246 }
247
248 bool FlagsState::IsRestartNeededToCommitChanges() {
249 return needs_restart_;
250 }
251
252 void FlagsState::SetFeatureEntryEnabled(FlagsStorage* flags_storage,
253 const std::string& internal_name,
254 bool enable) {
255 size_t at_index = internal_name.find(testing::kMultiSeparator);
256 if (at_index != std::string::npos) {
257 DCHECK(enable);
258 // We're being asked to enable a multi-choice entry. Disable the
259 // currently selected choice.
260 DCHECK_NE(at_index, 0u);
261 const std::string entry_name = internal_name.substr(0, at_index);
262 SetFeatureEntryEnabled(flags_storage, entry_name, false);
263
264 // And enable the new choice, if it is not the default first choice.
265 if (internal_name != entry_name + "@0") {
266 std::set<std::string> enabled_entries;
267 GetSanitizedEnabledFlags(flags_storage, &enabled_entries);
268 needs_restart_ |= enabled_entries.insert(internal_name).second;
269 flags_storage->SetFlags(enabled_entries);
270 }
271 return;
272 }
273
274 std::set<std::string> enabled_entries;
275 GetSanitizedEnabledFlags(flags_storage, &enabled_entries);
276
277 const FeatureEntry* e = nullptr;
278 for (size_t i = 0; i < num_feature_entries_; ++i) {
279 if (feature_entries_[i].internal_name == internal_name) {
280 e = feature_entries_ + i;
281 break;
282 }
283 }
284 DCHECK(e);
285
286 if (e->type == FeatureEntry::SINGLE_VALUE) {
287 if (enable)
288 needs_restart_ |= enabled_entries.insert(internal_name).second;
289 else
290 needs_restart_ |= (enabled_entries.erase(internal_name) > 0);
291 } else if (e->type == FeatureEntry::SINGLE_DISABLE_VALUE) {
292 if (!enable)
293 needs_restart_ |= enabled_entries.insert(internal_name).second;
294 else
295 needs_restart_ |= (enabled_entries.erase(internal_name) > 0);
296 } else {
297 if (enable) {
298 // Enable the first choice.
299 needs_restart_ |= enabled_entries.insert(e->NameForChoice(0)).second;
300 } else {
301 // Find the currently enabled choice and disable it.
302 for (int i = 0; i < e->num_choices; ++i) {
303 std::string choice_name = e->NameForChoice(i);
304 if (enabled_entries.find(choice_name) != enabled_entries.end()) {
305 needs_restart_ = true;
306 enabled_entries.erase(choice_name);
307 // Continue on just in case there's a bug and more than one
308 // entry for this choice was enabled.
309 }
310 }
311 }
312 }
313
314 flags_storage->SetFlags(enabled_entries);
315 }
316
317 void FlagsState::RemoveFlagsSwitches(
318 std::map<std::string, base::CommandLine::StringType>* switch_list) {
319 for (const auto& entry : flags_switches_)
320 switch_list->erase(entry.first);
321
322 // If feature entries were added to --enable-features= or --disable-features=
323 // lists, remove them here while preserving existing values.
324 for (const auto& entry : appended_switches_) {
325 const auto& switch_name = entry.first;
326 const auto& switch_added_values = entry.second;
327
328 // The below is either a std::string or a base::string16 based on platform.
329 const auto& existing_value = (*switch_list)[switch_name];
330 #if defined(OS_WIN)
331 const std::string existing_value_utf8 = base::UTF16ToUTF8(existing_value);
332 #else
333 const std::string& existing_value_utf8 = existing_value;
334 #endif
335
336 std::vector<std::string> features =
337 base::FeatureList::SplitFeatureListString(existing_value_utf8);
338 std::vector<std::string> remaining_features;
339 // For any featrue name in |features| that is not in |switch_added_values| -
340 // i.e. it wasn't added by about_flags code, add it to |remaining_features|.
341 for (const std::string& feature : features) {
342 if (!ContainsKey(switch_added_values, feature))
343 remaining_features.push_back(feature);
344 }
345
346 // Either remove the flag entirely if |remaining_features| is empty, or set
347 // the new list.
348 if (remaining_features.empty()) {
349 switch_list->erase(switch_name);
350 } else {
351 std::string switch_value = base::JoinString(remaining_features, ",");
352 #if defined(OS_WIN)
353 (*switch_list)[switch_name] = base::UTF8ToUTF16(switch_value);
354 #else
355 (*switch_list)[switch_name] = switch_value;
356 #endif
357 }
358 }
359 }
360
361 void FlagsState::ResetAllFlags(FlagsStorage* flags_storage) {
362 needs_restart_ = true;
363
364 std::set<std::string> no_entries;
365 flags_storage->SetFlags(no_entries);
366 }
367
368 void FlagsState::Reset() {
369 needs_restart_ = false;
370 flags_switches_.clear();
371 appended_switches_.clear();
372 }
373
374 void FlagsState::GetFlagFeatureEntries(
375 FlagsStorage* flags_storage,
376 FlagAccess access,
377 base::ListValue* supported_entries,
378 base::ListValue* unsupported_entries,
379 base::Callback<bool(const FeatureEntry&)> skip_feature_entry) {
380 std::set<std::string> enabled_entries;
381 GetSanitizedEnabledFlags(flags_storage, &enabled_entries);
382
383 int current_platform = GetCurrentPlatform();
384
385 for (size_t i = 0; i < num_feature_entries_; ++i) {
386 const FeatureEntry& entry = feature_entries_[i];
387 if (skip_feature_entry.Run(entry))
388 continue;
389
390 base::DictionaryValue* data = new base::DictionaryValue();
391 data->SetString("internal_name", entry.internal_name);
392 data->SetString("name", l10n_util::GetStringUTF16(entry.visible_name_id));
393 data->SetString("description",
394 l10n_util::GetStringUTF16(entry.visible_description_id));
395
396 base::ListValue* supported_platforms = new base::ListValue();
397 AddOsStrings(entry.supported_platforms, supported_platforms);
398 data->Set("supported_platforms", supported_platforms);
399 // True if the switch is not currently passed.
400 bool is_default_value = IsDefaultValue(entry, enabled_entries);
401 data->SetBoolean("is_default", is_default_value);
402
403 switch (entry.type) {
404 case FeatureEntry::SINGLE_VALUE:
405 case FeatureEntry::SINGLE_DISABLE_VALUE:
406 data->SetBoolean(
407 "enabled",
408 (!is_default_value && entry.type == FeatureEntry::SINGLE_VALUE) ||
409 (is_default_value &&
410 entry.type == FeatureEntry::SINGLE_DISABLE_VALUE));
411 break;
412 case FeatureEntry::MULTI_VALUE:
413 case FeatureEntry::ENABLE_DISABLE_VALUE:
414 case FeatureEntry::FEATURE_VALUE:
415 data->Set("choices", CreateChoiceData(entry, enabled_entries));
416 break;
417 default:
Alexei Svitkine (slow) 2015/11/16 21:52:54 Remove default.
sdefresne 2015/11/17 16:28:56 Done.
418 NOTREACHED();
419 }
420
421 bool supported = (entry.supported_platforms & current_platform) != 0;
422 #if defined(OS_CHROMEOS)
423 if (access == kOwnerAccessToFlags &&
424 (entry.supported_platforms & kOsCrOSOwnerOnly) != 0) {
425 supported = true;
426 }
427 #endif
428 if (supported)
429 supported_entries->Append(data);
430 else
431 unsupported_entries->Append(data);
432 }
433 }
434
435 // static
436 int FlagsState::GetCurrentPlatform() {
437 #if defined(OS_MACOSX)
438 return kOsMac;
439 #elif defined(OS_WIN)
440 return kOsWin;
441 #elif defined(OS_CHROMEOS) // Needs to be before the OS_LINUX check.
442 return kOsCrOS;
443 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
444 return kOsLinux;
445 #elif defined(OS_ANDROID)
446 return kOsAndroid;
447 #else
448 #error Unknown platform
449 #endif
450 }
451
452 // static
453 bool FlagsState::AreSwitchesIdenticalToCurrentCommandLine(
454 const base::CommandLine& new_cmdline,
455 const base::CommandLine& active_cmdline,
456 std::set<base::CommandLine::StringType>* out_difference,
457 const char* extra_flag_sentinel_begin_flag_name,
458 const char* extra_flag_sentinel_end_flag_name) {
459 std::set<base::CommandLine::StringType> new_flags =
460 ExtractFlagsFromCommandLine(new_cmdline,
461 extra_flag_sentinel_begin_flag_name,
462 extra_flag_sentinel_end_flag_name);
463 std::set<base::CommandLine::StringType> active_flags =
464 ExtractFlagsFromCommandLine(active_cmdline,
465 extra_flag_sentinel_begin_flag_name,
466 extra_flag_sentinel_end_flag_name);
467
468 bool result = false;
469 // Needed because std::equal doesn't check if the 2nd set is empty.
470 if (new_flags.size() == active_flags.size()) {
471 result =
472 std::equal(new_flags.begin(), new_flags.end(), active_flags.begin());
473 }
474
475 if (out_difference && !result) {
476 std::set_symmetric_difference(
477 new_flags.begin(), new_flags.end(), active_flags.begin(),
478 active_flags.end(),
479 std::inserter(*out_difference, out_difference->begin()));
480 }
481
482 return result;
483 }
484
485 void FlagsState::AddSwitchMapping(
486 const std::string& key,
487 const std::string& switch_name,
488 const std::string& switch_value,
489 std::map<std::string, SwitchEntry>* name_to_switch_map) {
490 DCHECK(!ContainsKey(*name_to_switch_map, key));
491
492 SwitchEntry* entry = &(*name_to_switch_map)[key];
493 entry->switch_name = switch_name;
494 entry->switch_value = switch_value;
495 }
496
497 void FlagsState::AddFeatureMapping(
498 const std::string& key,
499 const std::string& feature_name,
500 bool feature_state,
501 std::map<std::string, SwitchEntry>* name_to_switch_map) {
502 DCHECK(!ContainsKey(*name_to_switch_map, key));
503
504 SwitchEntry* entry = &(*name_to_switch_map)[key];
505 entry->feature_name = feature_name;
506 entry->feature_state = feature_state;
507 }
508
509 void FlagsState::AddSwitchesToCommandLine(
510 const std::set<std::string>& enabled_entries,
511 const std::map<std::string, SwitchEntry>& name_to_switch_map,
512 SentinelsMode sentinels,
513 base::CommandLine* command_line,
514 const char* enable_features_flag_name,
515 const char* disable_features_flag_name) {
516 std::map<std::string, bool> feature_switches;
517 if (sentinels == kAddSentinels) {
518 command_line->AppendSwitch(switches::kFlagSwitchesBegin);
519 flags_switches_[switches::kFlagSwitchesBegin] = std::string();
520 }
521
522 for (const std::string& entry_name : enabled_entries) {
523 const auto& entry_it = name_to_switch_map.find(entry_name);
524 if (entry_it == name_to_switch_map.end()) {
525 NOTREACHED();
526 continue;
527 }
528
529 const SwitchEntry& entry = entry_it->second;
530 if (!entry.feature_name.empty()) {
531 feature_switches[entry.feature_name] = entry.feature_state;
532 } else if (!entry.switch_name.empty()) {
533 command_line->AppendSwitchASCII(entry.switch_name, entry.switch_value);
534 flags_switches_[entry.switch_name] = entry.switch_value;
535 }
536 // If an entry doesn't match either of the above, then it is likely the
537 // default entry for a FEATURE_VALUE entry. Safe to ignore.
538 }
539
540 if (!feature_switches.empty()) {
541 MergeFeatureCommandLineSwitch(feature_switches, enable_features_flag_name,
542 true, command_line);
543 MergeFeatureCommandLineSwitch(feature_switches, disable_features_flag_name,
544 false, command_line);
545 }
546
547 if (sentinels == kAddSentinels) {
548 command_line->AppendSwitch(switches::kFlagSwitchesEnd);
549 flags_switches_[switches::kFlagSwitchesEnd] = std::string();
550 }
551 }
552
553 void FlagsState::MergeFeatureCommandLineSwitch(
554 const std::map<std::string, bool>& feature_switches,
555 const char* switch_name,
556 bool feature_state,
557 base::CommandLine* command_line) {
558 std::string original_switch_value =
559 command_line->GetSwitchValueASCII(switch_name);
560 std::vector<std::string> features =
561 base::FeatureList::SplitFeatureListString(original_switch_value);
562 // Only add features that don't already exist in the lists.
563 // Note: The ContainsValue() call results in O(n^2) performance, but in
564 // practice n should be very small.
565 for (const auto& entry : feature_switches) {
566 if (entry.second == feature_state &&
567 !ContainsValue(features, entry.first)) {
568 features.push_back(entry.first);
569 appended_switches_[switch_name].insert(entry.first);
570 }
571 }
572 // Update the switch value only if it didn't change. This avoids setting an
573 // empty list or duplicating the same list (since AppendSwitch() adds the
574 // switch to the end but doesn't remove previous ones).
575 std::string switch_value = base::JoinString(features, ",");
576 if (switch_value != original_switch_value)
577 command_line->AppendSwitchASCII(switch_name, switch_value);
578 }
579
580 void FlagsState::SanitizeList(FlagsStorage* flags_storage) {
581 std::set<std::string> known_entries;
582 for (size_t i = 0; i < num_feature_entries_; ++i) {
583 DCHECK(ValidateFeatureEntry(feature_entries_[i]));
584 AddInternalName(feature_entries_[i], &known_entries);
585 }
586
587 std::set<std::string> enabled_entries = flags_storage->GetFlags();
588
589 std::set<std::string> new_enabled_entries =
590 base::STLSetIntersection<std::set<std::string>>(known_entries,
591 enabled_entries);
592
593 if (new_enabled_entries != enabled_entries)
594 flags_storage->SetFlags(new_enabled_entries);
595 }
596
597 void FlagsState::GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
598 std::set<std::string>* result) {
599 SanitizeList(flags_storage);
600 *result = flags_storage->GetFlags();
601 }
602
603 void FlagsState::GetSanitizedEnabledFlagsForCurrentPlatform(
604 FlagsStorage* flags_storage,
605 std::set<std::string>* result) {
606 GetSanitizedEnabledFlags(flags_storage, result);
607
608 // Filter out any entries that aren't enabled on the current platform. We
609 // don't remove these from prefs else syncing to a platform with a different
610 // set of entries would be lossy.
611 std::set<std::string> platform_entries;
612 int current_platform = GetCurrentPlatform();
613 for (size_t i = 0; i < num_feature_entries_; ++i) {
614 const FeatureEntry& entry = feature_entries_[i];
615 if (entry.supported_platforms & current_platform)
616 AddInternalName(entry, &platform_entries);
617 #if defined(OS_CHROMEOS)
618 if (feature_entries_[i].supported_platforms & kOsCrOSOwnerOnly)
619 AddInternalName(entry, &platform_entries);
620 #endif
621 }
622
623 std::set<std::string> new_enabled_entries =
624 base::STLSetIntersection<std::set<std::string>>(platform_entries,
625 *result);
626
627 result->swap(new_enabled_entries);
628 }
629
630 } // namespace flags_ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698