chromium/components/flags_ui/flags_state.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "components/flags_ui/flags_state.h"

#include <algorithm>
#include <memory>
#include <string_view>
#include <utility>

#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/feature_list_buildflags.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/not_fatal_until.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/flags_ui/feature_entry.h"
#include "components/flags_ui/flags_storage.h"
#include "components/flags_ui/flags_ui_switches.h"
#include "components/variations/field_trial_config/field_trial_util.h"
#include "components/variations/variations_associated_data.h"
#include "components/variations/variations_switches.h"
#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace flags_ui {

namespace internal {
const char kTrialGroupAboutFlags[] =;
}  // namespace internal

namespace {

// Separator used for origin list values. The list of origins provided from
// the command line or from the text input in chrome://flags are concatenated
// using this separator. The value is then appended as a command line switch
// and saved in the dictionary pref (kAboutFlagsOriginLists).
// E.g. --isolate_origins=http://example1.net,http://example2.net
const char kOriginListValueSeparator[] =;

const struct {} kBitsToOs[] =;

// Adds a |StringValue| to |list| for each platform where |bitmask| indicates
// whether the entry is available on that platform.
void AddOsStrings(unsigned bitmask, base::Value::List* list) {}

// Returns true if none of this entry's options have been enabled.
bool IsDefaultValue(const FeatureEntry& entry,
                    const std::set<std::string>& enabled_entries) {}

// Returns the Value::List representing the choice data in the specified entry.
base::Value::List CreateOptionsData(
    const FeatureEntry& entry,
    const std::set<std::string>& enabled_entries) {}

// Registers variation parameters specified by |feature_variation_params| for
// the field trial named |feature_trial_name|, unless a group for this trial has
// already been created (e.g. via command-line switches that take precedence
// over about:flags). In the trial, the function creates a new constant group
// with the given |trail_group| name.
base::FieldTrial* RegisterFeatureVariationParameters(
    const std::string& feature_trial_name,
    const std::map<std::string, std::string>& feature_variation_params,
    const std::string& trial_group) {}

// Returns true if |value| is safe to include in a command line string in the
// form of --flag=value.
bool IsSafeValue(const std::string& value) {}

// Sanitizes |value| which contains a list of origins separated by whitespace
// and/or comma. The sanitized vector of origins is intended to be added to the
// command line, so this is a security critical operation: The sanitized value
// must have no whitespaces, each individual origin must be separated by a
// comma, and each origin must represent a url::Origin(). The list is not
// reordered.
std::vector<std::string> TokenizeOriginList(const std::string& value) {}

// Combines the origin lists contained in |value1| and |value2| separated by
// commas. The lists are concatenated, with invalid or duplicate origins
// removed.
std::string CombineAndSanitizeOriginLists(const std::string& value1,
                                          const std::string& value2) {}

// Returns the sanitized combined origin list by concatenating the command line
// and the pref values. Invalid or duplicate origins are dropped.
std::string GetCombinedOriginListValue(const FlagsStorage& flags_storage,
                                       const base::CommandLine& command_line,
                                       const std::string& internal_entry_name,
                                       const std::string& command_line_switch) {}

std::string GetCombinedStringValue(const FlagsStorage& flags_storage,
                                   const base::CommandLine& command_line,
                                   const std::string& internal_entry_name,
                                   const std::string& command_line_switch) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
// Removes the specified command line switch (if present).
void RemoveCommandLineSwitch(base::CommandLine* current_cl,
                             const std::string& switch_to_remove) {
  base::CommandLine new_cl(current_cl->GetProgram());
  const base::CommandLine::SwitchMap switches = current_cl->GetSwitches();
  for (const auto& it : switches) {
    const auto& switch_name = it.first;
    const auto& switch_value = it.second;
    if (switch_name != switch_to_remove) {
      if (switch_value.empty()) {
        new_cl.AppendSwitch(switch_name);
      } else {
        new_cl.AppendSwitchNative(switch_name, switch_value);
      }
    }
  }
  *current_cl = new_cl;
}

// ChromeOS does not call ConvertFlagsToSwitches on startup (see
// ChromeFeatureListCreator::ConvertFlagsToSwitches() for details) so the
// command line cannot be updated using pref values. Instead, this method
// modifies it on the fly when the user makes a change.
void DidModifyOriginListFlag(const FlagsStorage& flags_storage,
                             const FeatureEntry& entry) {
  base::CommandLine* current_cl = base::CommandLine::ForCurrentProcess();
  const std::string new_value = GetCombinedOriginListValue(
      flags_storage, *current_cl, entry.internal_name,
      entry.switches.command_line_switch);

  RemoveCommandLineSwitch(current_cl, entry.switches.command_line_switch);

  const std::string sanitized =
      CombineAndSanitizeOriginLists(std::string(), new_value);
  current_cl->AppendSwitchASCII(entry.switches.command_line_switch, sanitized);
}

// ChromeOS does not call ConvertFlagsToSwitches on startup (see
// ChromeFeatureListCreator::ConvertFlagsToSwitches() for details) so the
// command line cannot be updated using pref values. Instead, this method
// modifies it on the fly when the user makes a change.
void DidModifyStringFlag(const FlagsStorage& flags_storage,
                         const FeatureEntry& entry) {
  base::CommandLine* current_cl = base::CommandLine::ForCurrentProcess();
  const std::string new_value =
      GetCombinedStringValue(flags_storage, *current_cl, entry.internal_name,
                             entry.switches.command_line_switch);

  RemoveCommandLineSwitch(current_cl, entry.switches.command_line_switch);

  current_cl->AppendSwitchASCII(entry.switches.command_line_switch, new_value);
}
#endif

}  // namespace

struct FlagsState::SwitchEntry {};

bool FlagsState::Delegate::ShouldExcludeFlag(const FlagsStorage* state,
                                             const FeatureEntry& entry) {}

FlagsState::Delegate::Delegate() = default;
FlagsState::Delegate::~Delegate() = default;

FlagsState::FlagsState(base::span<const FeatureEntry> feature_entries,
                       FlagsState::Delegate* delegate)
    :{}

FlagsState::~FlagsState() {}

void FlagsState::ConvertFlagsToSwitches(
    FlagsStorage* flags_storage,
    base::CommandLine* command_line,
    SentinelsMode sentinels,
    const char* enable_features_flag_name,
    const char* disable_features_flag_name) {}

void FlagsState::GetSwitchesAndFeaturesFromFlags(
    FlagsStorage* flags_storage,
    std::set<std::string>* switches,
    std::set<std::string>* features,
    std::set<std::string>* variation_ids) const {}

bool FlagsState::IsRestartNeededToCommitChanges() {}

void FlagsState::SetFeatureEntryEnabled(FlagsStorage* flags_storage,
                                        const std::string& internal_name,
                                        bool enable) {}

void FlagsState::SetOriginListFlag(const std::string& internal_name,
                                   const std::string& value,
                                   FlagsStorage* flags_storage) {}

void FlagsState::SetStringFlag(const std::string& internal_name,
                               const std::string& value,
                               FlagsStorage* flags_storage) {}

void FlagsState::RemoveFlagsSwitches(
    base::CommandLine::SwitchMap* switch_list) {}

void FlagsState::ResetAllFlags(FlagsStorage* flags_storage) {}

void FlagsState::Reset() {}

std::vector<std::string> FlagsState::RegisterAllFeatureVariationParameters(
    FlagsStorage* flags_storage,
    base::FeatureList* feature_list) {}

// static
std::vector<std::string> FlagsState::RegisterEnabledFeatureVariationParameters(
    const base::span<const FeatureEntry>& feature_entries,
    const std::set<std::string>& enabled_entries,
    const std::string& trial_group,
    base::FeatureList* feature_list) {}

void FlagsState::GetFlagFeatureEntries(
    FlagsStorage* flags_storage,
    FlagAccess access,
    base::Value::List& supported_entries,
    base::Value::List& unsupported_entries,
    base::RepeatingCallback<bool(const FeatureEntry&)> skip_feature_entry) {}

// static
unsigned short FlagsState::GetCurrentPlatform() {}

void FlagsState::AddSwitchMapping(
    const std::string& key,
    const std::string& switch_name,
    const std::string& switch_value,
    std::map<std::string, SwitchEntry>* name_to_switch_map) const {}

void FlagsState::AddFeatureMapping(
    const std::string& key,
    const std::string& feature_name,
    bool feature_state,
    const std::string& variation_id,
    std::map<std::string, SwitchEntry>* name_to_switch_map) const {}

void FlagsState::AddSwitchesToCommandLine(
    const std::set<std::string>& enabled_entries,
    const std::map<std::string, SwitchEntry>& name_to_switch_map,
    SentinelsMode sentinels,
    base::CommandLine* command_line,
    const char* enable_features_flag_name,
    const char* disable_features_flag_name) {}

void FlagsState::MergeFeatureCommandLineSwitch(
    const std::map<std::string, bool>& feature_switches,
    const char* switch_name,
    bool feature_state,
    base::CommandLine* command_line) {}

void FlagsState::MergeVariationIdsCommandLineSwitch(
    const std::vector<std::string>& variation_ids,
    base::CommandLine* command_line) {}

std::set<std::string> FlagsState::SanitizeList(
    const FlagsStorage* storage,
    const std::set<std::string>& enabled_entries,
    int platform_mask) const {}

void FlagsState::GetSanitizedEnabledFlags(FlagsStorage* flags_storage,
                                          std::set<std::string>* result) const {}

void FlagsState::GetSanitizedEnabledFlagsForCurrentPlatform(
    FlagsStorage* flags_storage,
    std::set<std::string>* result) const {}

void FlagsState::GenerateFlagsToSwitchesMapping(
    FlagsStorage* flags_storage,
    const base::CommandLine& command_line,
    std::set<std::string>* enabled_entries,
    std::map<std::string, SwitchEntry>* name_to_switch_map) const {}

const FeatureEntry* FlagsState::FindFeatureEntryByName(
    const std::string& internal_name) const {}

bool FlagsState::IsSupportedFeature(const FlagsStorage* storage,
                                    const std::string& name,
                                    int platform_mask) const {}

}  // namespace flags_ui