{% from 'templates/macros.tmpl' import license, source_files_for_generated_file, platform_buildflag %}
{{license()}}
{{source_files_for_generated_file(template_file, input_files)}}
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/mojom/origin_trial_feature/origin_trial_feature.mojom-shared.h"
#include "third_party/blink/renderer/platform/feature_context.h"
#include "third_party/blink/renderer/platform/runtime_feature_state/runtime_feature_state_override_context.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
RuntimeEnabledFeaturesBase::Backup::Backup()
: {% for feature in features -%}
{%- if feature.is_protected_feature -%}
{{feature.data_member_name}}(RuntimeEnabledFeaturesBase::get_{{feature.data_member_name}}())
{%- else -%}
{{feature.data_member_name}}(RuntimeEnabledFeaturesBase::{{feature.data_member_name}})
{%- endif -%}
{%- if not loop.last %},
{%+ endif -%}
{% endfor %} {}
void RuntimeEnabledFeaturesBase::Backup::Restore() {
{% for feature in features %}
{% if feature.is_protected_feature %}
RuntimeEnabledFeaturesBase::Set{{feature.name}}Enabled({{feature.data_member_name}});
{% else %}
RuntimeEnabledFeaturesBase::{{feature.data_member_name}} = {{feature.data_member_name}};
{% endif %}
{% endfor %}
}
{% for feature_set in feature_sets %}
void RuntimeEnabledFeaturesBase::Set{{feature_set|capitalize}}FeaturesEnabled(bool enable) {
{% for feature in features if feature.status_type == 'str' and feature.status == feature_set %}
Set{{feature.name}}Enabled(enable);
{% endfor %}
// Platform-dependent features
{% for platform in platforms %}
#if {{platform_buildflag(platform)}}
{% for feature in features if feature.status_type == 'dict' and feature.status[platform] == feature_set %}
Set{{feature.name}}Enabled(enable);
{% endfor %}
#endif
{% endfor %}
// Default values for platforms not specifically handled above
#if
{%- for platform in platforms %}
{%- if not loop.first %} &&{% endif %}
!{{platform_buildflag(platform)}}
{%- endfor %}
{% for feature in features if feature.status_type == 'dict' and feature.status['default'] == feature_set %}
Set{{feature.name}}Enabled(enable);
{% endfor %}
#endif
}
{% endfor %}
void RuntimeEnabledFeaturesBase::SetOriginTrialControlledFeaturesEnabled(bool enable) {
{% for feature in origin_trial_controlled_features %}
Set{{feature.name}}Enabled(enable);
{% endfor %}
}
void RuntimeEnabledFeaturesBase::SetFeatureEnabledFromString(
const std::string& name, bool enable) {
static const struct {
const char* name;
void (*SetFunction)(bool);
} kFeatures[] = {
{% for feature in features|sort(attribute='name') %}
{"{{feature.name}}", Set{{feature.name}}Enabled},
{% endfor %}
};
auto feature = std::lower_bound(std::begin(kFeatures), std::end(kFeatures), name, [](const auto& feature, const std::string& name) {
return feature.name < name;
});
if (feature != std::end(kFeatures) && feature->name == name)
feature->SetFunction(enable);
else
DLOG(ERROR) << "RuntimeEnabledFeature not recognized: " << name;
}
bool RuntimeEnabledFeaturesBase::IsFeatureEnabledFromString(
const std::string& name) {
static const struct {
const char* name;
bool (*GetFunction)();
} kFeatures[] = {
{% for feature in features|sort(attribute='name') %}
{% if not feature.in_origin_trial %}
{"{{feature.name}}", {{feature.name}}Enabled},
{% endif %}
{% endfor %}
};
auto feature = std::lower_bound(std::begin(kFeatures), std::end(kFeatures), name, [](const auto& feature, const std::string& name) {
return feature.name < name;
});
if (feature != std::end(kFeatures) && feature->name == name) {
return feature->GetFunction();
} else {
CHECK(false) << " RuntimeEnabledFeature not recognized: " << name;
return false;
}
}
// static
void RuntimeEnabledFeaturesBase::UpdateStatusFromBaseFeatures() {
struct BaseFeatureToRuntimeFeatureMap {
const base::Feature& feature;
void (*enabler)(bool enable);
bool if_overridden;
};
const BaseFeatureToRuntimeFeatureMap mappings[] = {
{% for feature in features|sort(attribute='name') %}
{% if feature.base_feature %}
{blink::features::k{{feature.base_feature}}, Set{{feature.name}}Enabled,
{{'true' if feature.copied_from_base_feature_if == "overridden" else 'false'}}},
{% endif %}
{% endfor %}
};
for (const auto& map : mappings) {
const bool feature_enabled = base::FeatureList::IsEnabled(map.feature);
const bool is_overridden =
base::FeatureList::GetStateIfOverridden(map.feature).has_value();
if (map.if_overridden) {
if (is_overridden)
map.enabler(feature_enabled);
} else {
if (feature_enabled || is_overridden)
map.enabler(feature_enabled);
}
}
}
{% for feature in features %}
{% if feature.is_protected_feature %}
void RuntimeEnabledFeaturesBase::Set{{feature.name}}Enabled(bool enabled) {
if (get_{{feature.data_member_name}}() == enabled) {
return;
}
base::AutoWritableMemory protected_memory_writer({{feature.data_member_name}});
protected_memory_writer.GetProtectedData() = enabled;
}
{% endif %}
{% endfor %}
{% for feature in features %}
{%if feature.is_overridable_feature and not feature.in_origin_trial%}
bool RuntimeEnabledFeaturesBase::{{feature.name}}Enabled(const FeatureContext* context) {
if(context && context->GetRuntimeFeatureStateOverrideContext()
->Is{{feature.name}}ForceEnabled()) {
return true;
}
if(context && context->GetRuntimeFeatureStateOverrideContext()
->Is{{feature.name}}ForceDisabled()) {
return false;
}
return {{feature.name}}Enabled();
}
{% endif %}
{% endfor %}
{% for feature in origin_trial_controlled_features %}
bool RuntimeEnabledFeaturesBase::{{feature.name}}Enabled(const FeatureContext* context) {
{% if feature.is_overridable_feature%}
if(context && context->GetRuntimeFeatureStateOverrideContext()
->Is{{feature.name}}ForceEnabled()) {
return true;
}
if(context && context->GetRuntimeFeatureStateOverrideContext()
->Is{{feature.name}}ForceDisabled()) {
return false;
}
{% endif %}
{% for depends_on in feature.depends_on %}
if (!RuntimeEnabledFeaturesBase::{{depends_on}}Enabled(context))
return false;
{% endfor %}
{% for implied_by in feature.implied_by %}
if (RuntimeEnabledFeaturesBase::{{implied_by}}Enabled(context))
return true;
{% endfor %}
{% if feature.is_protected_feature %}
if (get_{{feature.data_member_name}}())
{% else %}
if ({{feature.data_member_name}})
{% endif %}
return true;
{% if not feature.origin_trial_feature_name %}
// The feature does not have an origin trial name and its runtime flag
// is not enabled.
return false;
{% else %}
return context && context->FeatureEnabled(mojom::blink::OriginTrialFeature::k{{feature.name}});
{% endif %}
}
{% endfor %}
{% for feature in features %}
{% if feature.status_type == 'str' %}
{% if feature.is_protected_feature %}
DEFINE_PROTECTED_DATA base::ProtectedMemory<bool> RuntimeEnabledFeaturesBase::{{feature.data_member_name}};
{% else %}
bool RuntimeEnabledFeaturesBase::{{feature.data_member_name}} = {{'true' if feature.status == 'stable' else 'false'}};
{% endif %}
{% endif %}
{% endfor %}
// Platform-dependent features
{% for platform in platforms %}
#if {{platform_buildflag(platform)}}
{% for feature in features %}
{% if feature.status_type == 'dict' %}
bool RuntimeEnabledFeaturesBase::{{feature.data_member_name}} = {{'true' if feature.status[platform] == 'stable' else 'false'}};
{% endif %}
{% endfor %}
#endif
{% endfor %}
// Default values for platforms not specifically handled above
#if
{%- for platform in platforms %}
{%- if not loop.first %} &&{% endif %}
!{{platform_buildflag(platform)}}
{%- endfor %}
{% for feature in features %}
{% if feature.status_type == 'dict' %}
bool RuntimeEnabledFeaturesBase::{{feature.data_member_name}} = {{'true' if feature.status['default'] == 'stable' else 'false'}};
{% endif %}
{% endfor %}
#endif
// Simple getter methods for protected memory values that ensure they are
// properly initialized before first access.
{% for feature in features %}
{% if feature.is_protected_feature %}
bool RuntimeEnabledFeaturesBase::get_{{feature.data_member_name}}() {
static base::ProtectedMemoryInitializer {{feature.data_member_name}}initializer({{feature.data_member_name}}, {{'true' if feature.status == 'stable' else 'false'}});
return *{{feature.data_member_name}};
}
{% endif %}
{% endfor %}
} // namespace blink