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


#include "services/network/public/cpp/permissions_policy/permissions_policy_features_generated.h"

#include "base/command_line.h"
#include "base/containers/fixed_flat_set.h"
#include "base/no_destructor.h"
#include "base/feature_list.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"

namespace network {

// Applies new defaults based on flags.
void UpdatePermissionsPolicyFeatureListFlagDefaults(PermissionsPolicyFeatureList& mutable_feature_list) {
  {% for feature in features %}
  {%- if feature.default_value_behind_flag %}
    {%- for flag, default_value in feature.default_value_behind_flag %}
      {%- if not loop.first %} else {% endif %}
  if (base::FeatureList::IsEnabled(network::features::k{{flag}})) {
    mutable_feature_list.find(network::mojom::PermissionsPolicyFeature::k{{feature.name}})->second =
      PermissionsPolicyFeatureDefault::{{default_value}};
  }
    {%- endfor %}

  {% elif feature.default_value_behind_switch %}
    {%- for switch, default_value in feature.default_value_behind_switch %}
      {%- if not loop.first %} else {% endif %}
  if (base::CommandLine::InitializedForCurrentProcess() &&
      base::CommandLine::ForCurrentProcess()->HasSwitch(network::switches::k{{switch}})) {
    mutable_feature_list.find(network::mojom::PermissionsPolicyFeature::k{{feature.name}})->second =
      PermissionsPolicyFeatureDefault::{{default_value}};
  }
    {%- endfor %}

  {% endif %}
  {%- endfor %}
}

// The base list with no flags or special cases.
PermissionsPolicyFeatureList GetBasePermissionsPolicyFeatureList() {
  static const base::NoDestructor<PermissionsPolicyFeatureList> feature_list({
      {%- for feature in features %}
        {
          network::mojom::PermissionsPolicyFeature::k{{feature.name}},
          PermissionsPolicyFeatureDefault::{{feature.feature_default}}
        },
      {%- endfor %}
    });
  return *feature_list;
}

// Defaults with "unload" using EnabledForNone.
PermissionsPolicyFeatureList& GetPermissionsPolicyFeatureListUnloadNone() {
  static base::NoDestructor<PermissionsPolicyFeatureList> feature_list([] {
    PermissionsPolicyFeatureList map = GetBasePermissionsPolicyFeatureList();
    UpdatePermissionsPolicyFeatureListFlagDefaults(map);

{# Apply special case for unload if present. #}
{% for feature in features %}
  {% if feature.name.original is equalto "Unload" %}
    map.find(network::mojom::PermissionsPolicyFeature::kUnload)->second =
        PermissionsPolicyFeatureDefault::EnableForNone;
  {% endif %}
{% endfor %}

    return map;
  }());
  return *feature_list;
}

// Defaults with "unload" using EnabledForAll.
PermissionsPolicyFeatureList& GetPermissionsPolicyFeatureListUnloadAll() {
  static base::NoDestructor<PermissionsPolicyFeatureList> feature_list([] {
    PermissionsPolicyFeatureList map = GetBasePermissionsPolicyFeatureList();
    UpdatePermissionsPolicyFeatureListFlagDefaults(map);

{# Apply special case for unload if present. #}
{% for feature in features %}
  {% if feature.name.original is equalto "Unload" %}
    map.find(network::mojom::PermissionsPolicyFeature::kUnload)->second =
        PermissionsPolicyFeatureDefault::EnableForAll;
  {% endif %}
{% endfor %}

    return map;
  }());
  return *feature_list;
}

bool IsPermissionsPolicyFeatureGuardedByIsolatedContext(
    std::string_view feature_name) {
  static constexpr auto kIsolatedContextFeatures = base::MakeFixedFlatSet<std::string_view>({
      {%- for feature in features %}
        {%- if feature.visibility == "IsolatedContext" %}
          "{{feature.permissions_policy_name}}",
        {%- endif %}
      {%- endfor %}
  });
  return kIsolatedContextFeatures.contains(feature_name);
}

} // namespace network
