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

#include "third_party/blink/renderer/core/feature_policy/feature_policy_parser.h"

#include <algorithm>
#include <utility>

#include <bitset>
#include "base/metrics/histogram_macros.h"
#include "net/http/structured_headers.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "url/origin.h"

namespace blink {
namespace {

class ParsedFeaturePolicies final
    : public GarbageCollected<ParsedFeaturePolicies>,
      public Supplement<ExecutionContext> {
 public:
  static const char kSupplementName[];

  static ParsedFeaturePolicies& From(ExecutionContext& context) {
    ParsedFeaturePolicies* policies =
        Supplement<ExecutionContext>::From<ParsedFeaturePolicies>(context);
    if (!policies) {
      policies = MakeGarbageCollected<ParsedFeaturePolicies>(context);
      Supplement<ExecutionContext>::ProvideTo(context, policies);
    }
    return *policies;
  }

  explicit ParsedFeaturePolicies(ExecutionContext& context)
      : Supplement<ExecutionContext>(context),
        policies_(
            static_cast<size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) +
            1) {}

  bool Observed(mojom::blink::FeaturePolicyFeature feature) {
    size_t feature_index = static_cast<size_t>(feature);
    if (policies_[feature_index])
      return true;
    policies_[feature_index] = true;
    return false;
  }

 private:
  // Tracks which feature policies have already been parsed, so as not to count
  // them multiple times.
  Vector<bool> policies_;
};

const char ParsedFeaturePolicies::kSupplementName[] = "ParsedFeaturePolicies";

class FeatureObserver {
 public:
  // Returns whether the feature has been observed before or not.
  bool FeatureObserved(mojom::blink::FeaturePolicyFeature feature);

 private:
  std::bitset<
      static_cast<size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) + 1>
      features_specified_;
};

class ParsingContext {
  STACK_ALLOCATED();

 public:
  ParsingContext(PolicyParserMessageBuffer& logger,
                 scoped_refptr<const SecurityOrigin> self_origin,
                 scoped_refptr<const SecurityOrigin> src_origin,
                 const FeatureNameMap& feature_names,
                 ExecutionContext* execution_context)
      : logger_(logger),
        self_origin_(self_origin),
        src_origin_(src_origin),
        feature_names_(feature_names),
        execution_context_(execution_context) {}

  ~ParsingContext() = default;

  ParsedFeaturePolicy ParseFeaturePolicy(const String& policy);
  ParsedFeaturePolicy ParsePermissionsPolicy(const String& policy);

 private:
  // Following is the intermediate represetnation(IR) of feature policy.
  // Parsing of syntax structures is done in this IR, but semantic checks, e.g.
  // whether feature_name is valid, are not yet performed.
  struct FeaturePolicyDeclarationNode {
    String feature_name;
    Vector<String> allowlist;
  };
  using FeaturePolicyNode = Vector<FeaturePolicyDeclarationNode>;

  ParsedFeaturePolicy ParseIR(const FeaturePolicyNode& root);
  FeaturePolicyNode ParseFeaturePolicyToIR(const String& policy);
  FeaturePolicyNode ParsePermissionsPolicyToIR(const String& policy);

  // normally 1 char = 1 byte
  // max length to parse = 2^16 = 64 kB
  static constexpr wtf_size_t MAX_LENGTH_PARSE = 1 << 16;

  base::Optional<ParsedFeaturePolicyDeclaration> ParseFeature(
      const FeaturePolicyDeclarationNode&);

  struct ParsedAllowlist {
    std::vector<url::Origin> allowed_origins;
    bool matches_all_origins{false};
    bool matches_opaque_src{false};

    ParsedAllowlist() : allowed_origins({}) {}
  };

  base::Optional<mojom::blink::FeaturePolicyFeature> ParseFeatureName(
      const String& feature_name);

  // Parse allowlist for feature.
  ParsedAllowlist ParseAllowlist(const Vector<String>& origin_strings);

  void ReportFeatureUsage(mojom::blink::FeaturePolicyFeature feature);

  // This function should be called after Allowlist Histograms related flags
  // have been captured.
  void RecordAllowlistTypeUsage(size_t origin_count);
  // The use of various allowlist types should only be recorded once per page.
  // For simplicity, this recording assumes that the ParseHeader method is
  // called once when creating a new document, and similarly the ParseAttribute
  // method is called once for a frame. It is possible for multiple calls, but
  // the additional complexity to guarantee only one record isn't warranted as
  // yet.
  void ReportAllowlistTypeUsage();

  PolicyParserMessageBuffer& logger_;
  scoped_refptr<const SecurityOrigin> self_origin_;
  scoped_refptr<const SecurityOrigin> src_origin_;
  const FeatureNameMap& feature_names_;
  ExecutionContext* execution_context_;

  // Flags for the types of items which can be used in allowlists.
  bool allowlist_includes_star_ = false;
  bool allowlist_includes_self_ = false;
  bool allowlist_includes_src_ = false;
  bool allowlist_includes_none_ = false;
  bool allowlist_includes_origin_ = false;

  HashSet<FeaturePolicyAllowlistType> allowlist_types_used_;

  FeatureObserver feature_observer_;
};

bool FeatureObserver::FeatureObserved(
    mojom::blink::FeaturePolicyFeature feature) {
  if (features_specified_[static_cast<size_t>(feature)]) {
    return true;
  } else {
    features_specified_.set(static_cast<size_t>(feature));
    return false;
  }
}

void ParsingContext::ReportFeatureUsage(
    mojom::blink::FeaturePolicyFeature feature) {
  if (src_origin_) {
    if (!execution_context_ ||
        !ParsedFeaturePolicies::From(*execution_context_).Observed(feature)) {
      UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.Allow",
                                feature);
    }
  } else {
    UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.FeaturePolicy.Header", feature);
  }
}

void ParsingContext::RecordAllowlistTypeUsage(size_t origin_count) {
  // Record the type of allowlist used.
  if (origin_count == 0) {
    allowlist_types_used_.insert(FeaturePolicyAllowlistType::kEmpty);
  } else if (origin_count == 1) {
    if (allowlist_includes_star_)
      allowlist_types_used_.insert(FeaturePolicyAllowlistType::kStar);
    else if (allowlist_includes_self_)
      allowlist_types_used_.insert(FeaturePolicyAllowlistType::kSelf);
    else if (allowlist_includes_src_)
      allowlist_types_used_.insert(FeaturePolicyAllowlistType::kSrc);
    else if (allowlist_includes_none_)
      allowlist_types_used_.insert(FeaturePolicyAllowlistType::kNone);
    else
      allowlist_types_used_.insert(FeaturePolicyAllowlistType::kOrigins);
  } else {
    if (allowlist_includes_origin_) {
      if (allowlist_includes_star_ || allowlist_includes_none_ ||
          allowlist_includes_src_ || allowlist_includes_self_)
        allowlist_types_used_.insert(FeaturePolicyAllowlistType::kMixed);
      else
        allowlist_types_used_.insert(FeaturePolicyAllowlistType::kOrigins);
    } else {
      allowlist_types_used_.insert(FeaturePolicyAllowlistType::kKeywordsOnly);
    }
  }
  // Reset all flags.
  allowlist_includes_star_ = false;
  allowlist_includes_self_ = false;
  allowlist_includes_src_ = false;
  allowlist_includes_none_ = false;
  allowlist_includes_origin_ = false;
}

void ParsingContext::ReportAllowlistTypeUsage() {
  for (const FeaturePolicyAllowlistType allowlist_type :
       allowlist_types_used_) {
    if (src_origin_) {
      UMA_HISTOGRAM_ENUMERATION(
          "Blink.UseCounter.FeaturePolicy.AttributeAllowlistType",
          allowlist_type);
    } else {
      UMA_HISTOGRAM_ENUMERATION(
          "Blink.UseCounter.FeaturePolicy.HeaderAllowlistType", allowlist_type);
    }
  }
}

base::Optional<mojom::blink::FeaturePolicyFeature>
ParsingContext::ParseFeatureName(const String& feature_name) {
  DCHECK(!feature_name.IsEmpty());
  if (!feature_names_.Contains(feature_name)) {
    logger_.Warn("Unrecognized feature: '" + feature_name + "'.");
    return base::nullopt;
  }
  if (DisabledByOriginTrial(feature_name, execution_context_)) {
    logger_.Warn("Origin trial controlled feature not enabled: '" +
                 feature_name + "'.");
    return base::nullopt;
  }
  mojom::blink::FeaturePolicyFeature feature = feature_names_.at(feature_name);

  return feature;
}

ParsingContext::ParsedAllowlist ParsingContext::ParseAllowlist(
    const Vector<String>& origin_strings) {
  ParsedAllowlist allowlist;
  if (origin_strings.IsEmpty()) {
    // If a policy entry has no listed origins (e.g. "feature_name1" in
    // allow="feature_name1; feature_name2 value"), enable the feature for:
    //     a. |self_origin|, if we are parsing a header policy (i.e.,
    //       |src_origin| is null);
    //     b. |src_origin|, if we are parsing an allow attribute (i.e.,
    //       |src_origin| is not null), |src_origin| is not opaque; or
    //     c. the opaque origin of the frame, if |src_origin| is opaque.
    if (!src_origin_) {
      allowlist.allowed_origins.push_back(self_origin_->ToUrlOrigin());
    } else if (!src_origin_->IsOpaque()) {
      allowlist.allowed_origins.push_back(src_origin_->ToUrlOrigin());
    } else {
      allowlist.matches_opaque_src = true;
    }
  } else {
    for (const String& origin_string : origin_strings) {
      DCHECK(!origin_string.IsEmpty());

      if (!origin_string.ContainsOnlyASCIIOrEmpty()) {
        logger_.Warn("Non-ASCII characters in origin.");
        continue;
      }

      // Determine the target of the declaration. This may be a specific
      // origin, either explicitly written, or one of the special keywords
      // 'self' or 'src'. ('src' can only be used in the iframe allow
      // attribute.)
      url::Origin target_origin;

      // If the iframe will have an opaque origin (for example, if it is
      // sandboxed, or has a data: URL), then 'src' needs to refer to the
      // opaque origin of the frame, which is not known yet. In this case,
      // the |matches_opaque_src| flag on the declaration is set, rather than
      // adding an origin to the allowlist.
      bool target_is_opaque = false;
      bool target_is_all = false;

      // 'self' origin is used if the origin is exactly 'self'.
      if (EqualIgnoringASCIICase(origin_string, "'self'")) {
        allowlist_includes_self_ = true;
        target_origin = self_origin_->ToUrlOrigin();
      }
      // 'src' origin is used if |src_origin| is available and the
      // origin is a match for 'src'. |src_origin| is only set
      // when parsing an iframe allow attribute.
      else if (src_origin_ && EqualIgnoringASCIICase(origin_string, "'src'")) {
        allowlist_includes_src_ = true;
        if (!src_origin_->IsOpaque()) {
          target_origin = src_origin_->ToUrlOrigin();
        } else {
          target_is_opaque = true;
        }
      } else if (EqualIgnoringASCIICase(origin_string, "'none'")) {
        allowlist_includes_none_ = true;
        continue;
      } else if (origin_string == "*") {
        allowlist_includes_star_ = true;
        target_is_all = true;
      }
      // Otherwise, parse the origin string and verify that the result is
      // valid. Invalid strings will produce an opaque origin, which will
      // result in an error message.
      else {
        scoped_refptr<SecurityOrigin> parsed_origin =
            SecurityOrigin::CreateFromString(origin_string);
        if (!parsed_origin->IsOpaque()) {
          target_origin = parsed_origin->ToUrlOrigin();
          allowlist_includes_origin_ = true;
        } else {
          logger_.Warn("Unrecognized origin: '" + origin_string + "'.");
          continue;
        }
      }

      if (target_is_all) {
        allowlist.matches_all_origins = true;
        allowlist.matches_opaque_src = true;
      } else if (target_is_opaque) {
        allowlist.matches_opaque_src = true;
      } else {
        allowlist.allowed_origins.push_back(target_origin);
      }
    }
  }

  // Size reduction: remove all items in the allowlist if target is all.
  if (allowlist.matches_all_origins)
    allowlist.allowed_origins.clear();

  // Sort |allowed_origins| in alphabetical order.
  std::sort(allowlist.allowed_origins.begin(), allowlist.allowed_origins.end());

  RecordAllowlistTypeUsage(origin_strings.size());

  return allowlist;
}

base::Optional<ParsedFeaturePolicyDeclaration> ParsingContext::ParseFeature(
    const FeaturePolicyDeclarationNode& declaration_node) {
  base::Optional<mojom::blink::FeaturePolicyFeature> feature =
      ParseFeatureName(declaration_node.feature_name);
  if (!feature)
    return base::nullopt;

  ParsedAllowlist parsed_allowlist = ParseAllowlist(declaration_node.allowlist);

  // If same feature appeared more than once, only the first one counts.
  if (feature_observer_.FeatureObserved(*feature))
    return base::nullopt;

  ParsedFeaturePolicyDeclaration parsed_feature(*feature);
  parsed_feature.allowed_origins = std::move(parsed_allowlist.allowed_origins);
  parsed_feature.matches_all_origins = parsed_allowlist.matches_all_origins;
  parsed_feature.matches_opaque_src = parsed_allowlist.matches_opaque_src;

  return parsed_feature;
}

ParsedFeaturePolicy ParsingContext::ParseFeaturePolicy(const String& policy) {
  return ParseIR(ParseFeaturePolicyToIR(policy));
}

ParsedFeaturePolicy ParsingContext::ParsePermissionsPolicy(
    const String& policy) {
  return ParseIR(ParsePermissionsPolicyToIR(policy));
}

ParsedFeaturePolicy ParsingContext::ParseIR(
    const ParsingContext::FeaturePolicyNode& root) {
  ParsedFeaturePolicy parsed_policy;
  for (const ParsingContext::FeaturePolicyDeclarationNode& declaration_node :
       root) {
    base::Optional<ParsedFeaturePolicyDeclaration> parsed_feature =
        ParseFeature(declaration_node);
    if (parsed_feature) {
      ReportFeatureUsage(parsed_feature->feature);
      parsed_policy.push_back(*parsed_feature);
    }
  }
  ReportAllowlistTypeUsage();
  return parsed_policy;
}

ParsingContext::FeaturePolicyNode ParsingContext::ParseFeaturePolicyToIR(
    const String& policy) {
  ParsingContext::FeaturePolicyNode root;

  if (policy.length() > MAX_LENGTH_PARSE) {
    logger_.Error("Feature policy declaration exceeds size limit(" +
                  String::Number(policy.length()) + ">" +
                  String::Number(MAX_LENGTH_PARSE) + ")");
    return {};
  }

  Vector<String> policy_items;

  if (src_origin_) {
    // Attribute parsing.
    policy_items.push_back(policy);
  } else {
    // Header parsing.
    // RFC2616, section 4.2 specifies that headers appearing multiple times can
    // be combined with a comma. Walk the header string, and parse each comma
    // separated chunk as a separate header.
    // policy_items = [ policy *( "," [ policy ] ) ]
    policy.Split(',', policy_items);
  }

  if (policy_items.size() > 1) {
    UseCounter::Count(
        execution_context_,
        mojom::blink::WebFeature::kFeaturePolicyCommaSeparatedDeclarations);
  }

  for (const String& item : policy_items) {
    Vector<String> feature_entries;
    // feature_entries = [ feature_entry *( ";" [ feature_entry ] ) ]
    item.Split(';', feature_entries);

    if (feature_entries.size() > 1) {
      UseCounter::Count(execution_context_,
                        mojom::blink::WebFeature::
                            kFeaturePolicySemicolonSeparatedDeclarations);
    }

    for (const String& feature_entry : feature_entries) {
      Vector<String> tokens;
      feature_entry.Split(' ', tokens);

      if (tokens.IsEmpty())
        continue;

      ParsingContext::FeaturePolicyDeclarationNode declaration_node;
      // Break tokens into head & tail, where
      // head = feature_name
      // tail = allowlist
      // After feature_name has been set, take tail of tokens vector by
      // erasing the first element.
      declaration_node.feature_name = std::move(tokens.front());
      tokens.erase(tokens.begin());
      declaration_node.allowlist = std::move(tokens);
      root.push_back(declaration_node);
    }
  }

  return root;
}

ParsingContext::FeaturePolicyNode ParsingContext::ParsePermissionsPolicyToIR(
    const String& policy) {
  if (policy.length() > MAX_LENGTH_PARSE) {
    logger_.Error("Permissions policy declaration exceeds size limit(" +
                  String::Number(policy.length()) + ">" +
                  String::Number(MAX_LENGTH_PARSE) + ")");
    return {};
  }

  auto root = net::structured_headers::ParseDictionary(policy.Utf8());
  if (!root) {
    logger_.Error(
        "Parse of permissions policy failed because of errors reported by "
        "structured header parser.");
    return {};
  }

  ParsingContext::FeaturePolicyNode ir_root;
  for (const auto& feature_entry : root.value()) {
    const auto& key = feature_entry.first;
    const char* feature_name = key.c_str();
    const auto& value = feature_entry.second;

    if (!value.params.empty()) {
      logger_.Warn(
          String::Format("Feature %s's parameters are ignored.", feature_name));
    }

    Vector<String> allowlist;
    for (const auto& parameterized_item : value.member) {
      if (!parameterized_item.params.empty()) {
        logger_.Warn(String::Format("Feature %s's parameters are ignored.",
                                    feature_name));
      }

      String allowlist_item;
      if (parameterized_item.item.is_token()) {
        // All special keyword appears as token, i.e. self, src and *.
        const std::string& token_value = parameterized_item.item.GetString();
        if (token_value != "*" && token_value != "self") {
          logger_.Warn(String::Format(
              "Invalid allowlist item(%s) for feature %s. Allowlist item "
              "must be *, self or quoted url.",
              token_value.c_str(), feature_name));
          continue;
        }

        if (token_value == "*") {
          allowlist_item = "*";
        } else {
          allowlist_item = String::Format("'%s'", token_value.c_str());
        }
      } else if (parameterized_item.item.is_string()) {
        allowlist_item = parameterized_item.item.GetString().c_str();
      } else {
        logger_.Warn(
            String::Format("Invalid allowlist item for feature %s. Allowlist "
                           "item must be *, self, or quoted url.",
                           feature_name));
        continue;
      }
      if (!allowlist_item.IsEmpty())
        allowlist.push_back(allowlist_item);
    }

    if (allowlist.IsEmpty())
      allowlist.push_back("'none'");

    ir_root.push_back(
        ParsingContext::FeaturePolicyDeclarationNode{feature_name, allowlist});
  }

  return ir_root;
}

}  // namespace

ParsedFeaturePolicy FeaturePolicyParser::ParseHeader(
    const String& feature_policy_header,
    const String& permissions_policy_header,
    scoped_refptr<const SecurityOrigin> origin,
    PolicyParserMessageBuffer& feature_policy_logger,
    PolicyParserMessageBuffer& permissions_policy_logger,
    ExecutionContext* execution_context) {
  ParsedFeaturePolicy permissions_policy =
      ParsingContext(permissions_policy_logger, origin, nullptr,
                     GetDefaultFeatureNameMap(), execution_context)
          .ParsePermissionsPolicy(permissions_policy_header);
  ParsedFeaturePolicy feature_policy =
      ParsingContext(feature_policy_logger, origin, nullptr,
                     GetDefaultFeatureNameMap(), execution_context)
          .ParseFeaturePolicy(feature_policy_header);

  FeatureObserver observer;
  for (const auto& policy_declaration : permissions_policy) {
    bool feature_observed =
        observer.FeatureObserved(policy_declaration.feature);
    DCHECK(!feature_observed);
  }
  for (const auto& policy_declaration : feature_policy) {
    if (!observer.FeatureObserved(policy_declaration.feature)) {
      permissions_policy.push_back(policy_declaration);
    } else {
      feature_policy_logger.Warn(String::Format(
          "Feature %s has been specified in both Feature-Policy and "
          "Permissions-Policy header. Value defined in Permissions-Policy "
          "header will be used.",
          GetNameForFeature(policy_declaration.feature).Ascii().c_str()));
    }
  }

  return permissions_policy;
}

ParsedFeaturePolicy FeaturePolicyParser::ParseAttribute(
    const String& policy,
    scoped_refptr<const SecurityOrigin> self_origin,
    scoped_refptr<const SecurityOrigin> src_origin,
    PolicyParserMessageBuffer& logger,
    ExecutionContext* execution_context) {
  return ParsingContext(logger, self_origin, src_origin,
                        GetDefaultFeatureNameMap(), execution_context)
      .ParseFeaturePolicy(policy);
}

ParsedFeaturePolicy FeaturePolicyParser::ParseFeaturePolicyForTest(
    const String& policy,
    scoped_refptr<const SecurityOrigin> self_origin,
    scoped_refptr<const SecurityOrigin> src_origin,
    PolicyParserMessageBuffer& logger,
    const FeatureNameMap& feature_names,
    ExecutionContext* execution_context) {
  return ParsingContext(logger, self_origin, src_origin, feature_names,
                        execution_context)
      .ParseFeaturePolicy(policy);
}

ParsedFeaturePolicy FeaturePolicyParser::ParsePermissionsPolicyForTest(
    const String& policy,
    scoped_refptr<const SecurityOrigin> self_origin,
    scoped_refptr<const SecurityOrigin> src_origin,
    PolicyParserMessageBuffer& logger,
    const FeatureNameMap& feature_names,
    ExecutionContext* execution_context) {
  return ParsingContext(logger, self_origin, src_origin, feature_names,
                        execution_context)
      .ParsePermissionsPolicy(policy);
}

bool IsFeatureDeclared(mojom::blink::FeaturePolicyFeature feature,
                       const ParsedFeaturePolicy& policy) {
  return std::any_of(policy.begin(), policy.end(),
                     [feature](const auto& declaration) {
                       return declaration.feature == feature;
                     });
}

bool RemoveFeatureIfPresent(mojom::blink::FeaturePolicyFeature feature,
                            ParsedFeaturePolicy& policy) {
  auto new_end = std::remove_if(policy.begin(), policy.end(),
                                [feature](const auto& declaration) {
                                  return declaration.feature == feature;
                                });
  if (new_end == policy.end())
    return false;
  policy.erase(new_end, policy.end());
  return true;
}

bool DisallowFeatureIfNotPresent(mojom::blink::FeaturePolicyFeature feature,
                                 ParsedFeaturePolicy& policy) {
  if (IsFeatureDeclared(feature, policy))
    return false;
  ParsedFeaturePolicyDeclaration allowlist(feature);
  policy.push_back(allowlist);
  return true;
}

bool AllowFeatureEverywhereIfNotPresent(
    mojom::blink::FeaturePolicyFeature feature,
    ParsedFeaturePolicy& policy) {
  if (IsFeatureDeclared(feature, policy))
    return false;
  ParsedFeaturePolicyDeclaration allowlist(feature);
  allowlist.matches_all_origins = true;
  allowlist.matches_opaque_src = true;
  policy.push_back(allowlist);
  return true;
}

void DisallowFeature(mojom::blink::FeaturePolicyFeature feature,
                     ParsedFeaturePolicy& policy) {
  RemoveFeatureIfPresent(feature, policy);
  DisallowFeatureIfNotPresent(feature, policy);
}

bool IsFeatureForMeasurementOnly(mojom::blink::FeaturePolicyFeature feature) {
  return feature == mojom::blink::FeaturePolicyFeature::kWebShare;
}

void AllowFeatureEverywhere(mojom::blink::FeaturePolicyFeature feature,
                            ParsedFeaturePolicy& policy) {
  RemoveFeatureIfPresent(feature, policy);
  AllowFeatureEverywhereIfNotPresent(feature, policy);
}

const Vector<String> GetAvailableFeatures(ExecutionContext* execution_context) {
  Vector<String> available_features;
  for (const auto& feature : GetDefaultFeatureNameMap()) {
    if (!DisabledByOriginTrial(feature.key, execution_context) &&
        !IsFeatureForMeasurementOnly(feature.value)) {
      available_features.push_back(feature.key);
    }
  }
  return available_features;
}

const String& GetNameForFeature(mojom::blink::FeaturePolicyFeature feature) {
  for (const auto& entry : GetDefaultFeatureNameMap()) {
    if (entry.value == feature)
      return entry.key;
  }
  return g_empty_string;
}

}  // namespace blink
