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

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

Powered by Google App Engine
This is Rietveld 408576698