#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "base/feature_list.h"
#include <stddef.h>
#include <string>
#include <string_view>
#include <tuple>
#include "base/base_switches.h"
#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/persistent_memory_allocator.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/pickle.h"
#include "base/rand_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "base/feature_visitor.h"
#endif
namespace base {
namespace {
FeatureList* g_feature_list_instance = …;
class EarlyFeatureAccessTracker { … };
#if DCHECK_IS_ON()
const char* g_reason_overrides_disallowed = …;
void DCheckOverridesAllowed() { … }
#else
void DCheckOverridesAllowed() {}
#endif
struct FeatureEntry { … };
bool SplitIntoTwo(std::string_view text,
std::string_view separator,
std::string_view* first,
std::string* second) { … }
bool ParseEnableFeatures(const std::string& enable_features,
std::string* parsed_enable_features,
std::string* force_fieldtrials,
std::string* force_fieldtrial_params) { … }
std::pair<FeatureList::OverrideState, uint16_t> UnpackFeatureCache(
uint32_t packed_cache_value) { … }
uint32_t PackFeatureCache(FeatureList::OverrideState override_state,
uint32_t caching_context) { … }
uint16_t g_current_caching_context = …;
}
#if BUILDFLAG(DCHECK_IS_CONFIGURABLE)
BASE_FEATURE(kDCheckIsFatalFeature,
"DcheckIsFatal",
FEATURE_DISABLED_BY_DEFAULT);
#endif
FeatureList::FeatureList() : … { … }
FeatureList::~FeatureList() = default;
FeatureList::ScopedDisallowOverrides::ScopedDisallowOverrides(
const char* reason)
#if DCHECK_IS_ON()
: … { … }
#else
{
}
#endif
FeatureList::ScopedDisallowOverrides::~ScopedDisallowOverrides() { … }
void FeatureList::InitFromCommandLine(const std::string& enable_features,
const std::string& disable_features) { … }
void FeatureList::InitFromSharedMemory(PersistentMemoryAllocator* allocator) { … }
bool FeatureList::IsFeatureOverridden(const std::string& feature_name) const { … }
bool FeatureList::IsFeatureOverriddenFromCommandLine(
const std::string& feature_name) const { … }
bool FeatureList::IsFeatureOverriddenFromCommandLine(
const std::string& feature_name,
OverrideState state) const { … }
void FeatureList::AssociateReportingFieldTrial(
const std::string& feature_name,
OverrideState for_overridden_state,
FieldTrial* field_trial) { … }
void FeatureList::RegisterFieldTrialOverride(const std::string& feature_name,
OverrideState override_state,
FieldTrial* field_trial) { … }
void FeatureList::RegisterExtraFeatureOverrides(
const std::vector<FeatureOverrideInfo>& extra_overrides) { … }
void FeatureList::AddFeaturesToAllocator(PersistentMemoryAllocator* allocator) { … }
void FeatureList::GetFeatureOverrides(std::string* enable_overrides,
std::string* disable_overrides,
bool include_group_name) const { … }
void FeatureList::GetCommandLineFeatureOverrides(
std::string* enable_overrides,
std::string* disable_overrides) const { … }
bool FeatureList::IsEnabled(const Feature& feature) { … }
bool FeatureList::IsValidFeatureOrFieldTrialName(std::string_view name) { … }
std::optional<bool> FeatureList::GetStateIfOverridden(const Feature& feature) { … }
FieldTrial* FeatureList::GetFieldTrial(const Feature& feature) { … }
std::vector<std::string_view> FeatureList::SplitFeatureListString(
std::string_view input) { … }
bool FeatureList::ParseEnableFeatureString(std::string_view enable_feature,
std::string* feature_name,
std::string* study_name,
std::string* group_name,
std::string* params) { … }
bool FeatureList::InitInstance(const std::string& enable_features,
const std::string& disable_features) { … }
bool FeatureList::InitInstance(
const std::string& enable_features,
const std::string& disable_features,
const std::vector<FeatureOverrideInfo>& extra_overrides) { … }
FeatureList* FeatureList::GetInstance() { … }
void FeatureList::SetInstance(std::unique_ptr<FeatureList> instance) { … }
void FeatureList::SetEarlyAccessInstance(
std::unique_ptr<FeatureList> instance,
base::flat_set<std::string> allowed_feature_names) { … }
std::unique_ptr<FeatureList> FeatureList::ClearInstanceForTesting() { … }
void FeatureList::RestoreInstanceForTesting(
std::unique_ptr<FeatureList> instance) { … }
void FeatureList::FailOnFeatureAccessWithoutFeatureList() { … }
const Feature* FeatureList::GetEarlyAccessedFeatureForTesting() { … }
void FeatureList::ResetEarlyFeatureAccessTrackerForTesting() { … }
void FeatureList::AddEarlyAllowedFeatureForTesting(std::string feature_name) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
void FeatureList::VisitFeaturesAndParams(FeatureVisitor& visitor) {
CHECK(g_feature_list_instance);
FieldTrialParamAssociator* params_associator =
FieldTrialParamAssociator::GetInstance();
for (auto& feature_override : g_feature_list_instance->overrides_) {
FieldTrial* field_trial = feature_override.second.field_trial;
std::string trial_name;
std::string group_name;
FieldTrialParams params;
if (field_trial) {
trial_name = field_trial->trial_name();
group_name = field_trial->group_name();
params_associator->GetFieldTrialParamsWithoutFallback(
trial_name, group_name, ¶ms);
}
visitor.Visit(feature_override.first,
feature_override.second.overridden_state, params, trial_name,
group_name);
}
}
#endif
void FeatureList::FinalizeInitialization() { … }
bool FeatureList::IsFeatureEnabled(const Feature& feature) const { … }
std::optional<bool> FeatureList::IsFeatureEnabledIfOverridden(
const Feature& feature) const { … }
FeatureList::OverrideState FeatureList::GetOverrideState(
const Feature& feature) const { … }
FeatureList::OverrideState FeatureList::GetOverrideStateByFeatureName(
std::string_view feature_name) const { … }
FieldTrial* FeatureList::GetAssociatedFieldTrial(const Feature& feature) const { … }
const base::FeatureList::OverrideEntry*
FeatureList::GetOverrideEntryByFeatureName(std::string_view name) const { … }
FieldTrial* FeatureList::GetAssociatedFieldTrialByFeatureName(
std::string_view name) const { … }
bool FeatureList::HasAssociatedFieldTrialByFeatureName(
std::string_view name) const { … }
FieldTrial* FeatureList::GetEnabledFieldTrialByFeatureName(
std::string_view name) const { … }
std::unique_ptr<FeatureList::Accessor> FeatureList::ConstructAccessor() { … }
void FeatureList::RegisterOverridesFromCommandLine(
const std::string& feature_list,
OverrideState overridden_state) { … }
void FeatureList::RegisterOverride(std::string_view feature_name,
OverrideState overridden_state,
FieldTrial* field_trial) { … }
void FeatureList::GetFeatureOverridesImpl(std::string* enable_overrides,
std::string* disable_overrides,
bool command_line_only,
bool include_group_name) const { … }
bool FeatureList::CheckFeatureIdentity(const Feature& feature) const { … }
bool FeatureList::IsEarlyAccessInstance() const { … }
bool FeatureList::AllowFeatureAccess(const Feature& feature) const { … }
FeatureList::OverrideEntry::OverrideEntry(OverrideState overridden_state,
FieldTrial* field_trial)
: … { … }
FeatureList::Accessor::Accessor(FeatureList* feature_list)
: … { … }
FeatureList::OverrideState FeatureList::Accessor::GetOverrideStateByFeatureName(
std::string_view feature_name) { … }
bool FeatureList::Accessor::GetParamsByFeatureName(
std::string_view feature_name,
std::map<std::string, std::string>* params) { … }
}