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

#include "third_party/blink/public/common/feature_policy/document_policy.h"

#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "net/http/structured_headers.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom.h"

namespace blink {

// static
std::unique_ptr<DocumentPolicy> DocumentPolicy::CreateWithHeaderPolicy(
    const ParsedDocumentPolicy& header_policy) {
  DocumentPolicyFeatureState feature_defaults;
  for (const auto& entry : GetDocumentPolicyFeatureInfoMap())
    feature_defaults.emplace(entry.first, entry.second.default_value);
  return CreateWithHeaderPolicy(header_policy.feature_state,
                                header_policy.endpoint_map, feature_defaults);
}

// static
std::unique_ptr<DocumentPolicy> DocumentPolicy::CopyStateFrom(
    const DocumentPolicy* source) {
  if (!source)
    return nullptr;

  std::unique_ptr<DocumentPolicy> new_policy =
      DocumentPolicy::CreateWithHeaderPolicy(
          {/* header_policy */ {}, /* endpoint_map */ {}});

  new_policy->internal_feature_state_ = source->internal_feature_state_;
  new_policy->endpoint_map_ = source->endpoint_map_;
  return new_policy;
}

namespace {
net::structured_headers::Item PolicyValueToItem(const PolicyValue& value) {
  switch (value.Type()) {
    case mojom::PolicyValueType::kBool:
      return net::structured_headers::Item{value.BoolValue()};
    case mojom::PolicyValueType::kDecDouble:
      return net::structured_headers::Item{value.DoubleValue()};
    default:
      NOTREACHED();
      return net::structured_headers::Item{
          nullptr, net::structured_headers::Item::ItemType::kNullType};
  }
}

}  // namespace

// static
base::Optional<std::string> DocumentPolicy::Serialize(
    const DocumentPolicyFeatureState& policy) {
  return DocumentPolicy::SerializeInternal(policy,
                                           GetDocumentPolicyFeatureInfoMap());
}

// static
base::Optional<std::string> DocumentPolicy::SerializeInternal(
    const DocumentPolicyFeatureState& policy,
    const DocumentPolicyFeatureInfoMap& feature_info_map) {
  net::structured_headers::Dictionary root;

  std::vector<std::pair<mojom::DocumentPolicyFeature, PolicyValue>>
      sorted_policy(policy.begin(), policy.end());
  std::sort(sorted_policy.begin(), sorted_policy.end(),
            [&](const auto& a, const auto& b) {
              const std::string& feature_a =
                  feature_info_map.at(a.first).feature_name;
              const std::string& feature_b =
                  feature_info_map.at(b.first).feature_name;
              return feature_a < feature_b;
            });

  for (const auto& policy_entry : sorted_policy) {
    const mojom::DocumentPolicyFeature feature = policy_entry.first;
    const std::string& feature_name = feature_info_map.at(feature).feature_name;
    const PolicyValue& value = policy_entry.second;

    root[feature_name] = net::structured_headers::ParameterizedMember(
        PolicyValueToItem(value), /* parameters */ {});
  }

  return net::structured_headers::SerializeDictionary(root);
}

// static
DocumentPolicyFeatureState DocumentPolicy::MergeFeatureState(
    const DocumentPolicyFeatureState& base_policy,
    const DocumentPolicyFeatureState& override_policy) {
  DocumentPolicyFeatureState result;
  auto i1 = base_policy.begin();
  auto i2 = override_policy.begin();

  // Because std::map is by default ordered in ascending order based on key
  // value, we can run 2 iterators simultaneously through both maps to merge
  // them.
  while (i1 != base_policy.end() || i2 != override_policy.end()) {
    if (i1 == base_policy.end()) {
      result.insert(*i2);
      i2++;
    } else if (i2 == override_policy.end()) {
      result.insert(*i1);
      i1++;
    } else {
      if (i1->first == i2->first) {
        const PolicyValue& base_value = i1->second;
        const PolicyValue& override_value = i2->second;
        // When policy value has strictness ordering e.g. boolean, take the
        // stricter one. In this case a.IsCompatibleWith(b) means a is eq or
        // stricter than b.
        // When policy value does not have strictness ordering, e.g. enum,
        // take override_value. In this case a.IsCompatibleWith(b) means
        // a != b.
        const PolicyValue& new_value =
            base_value.IsCompatibleWith(override_value) ? base_value
                                                        : override_value;
        result.emplace(i1->first, new_value);
        i1++;
        i2++;
      } else if (i1->first < i2->first) {
        result.insert(*i1);
        i1++;
      } else {
        result.insert(*i2);
        i2++;
      }
    }
  }

  return result;
}

bool DocumentPolicy::IsFeatureEnabled(
    mojom::DocumentPolicyFeature feature) const {
  mojom::PolicyValueType feature_type =
      GetDocumentPolicyFeatureInfoMap().at(feature).default_value.Type();
  return IsFeatureEnabled(feature,
                          PolicyValue::CreateMaxPolicyValue(feature_type));
}

bool DocumentPolicy::IsFeatureEnabled(
    mojom::DocumentPolicyFeature feature,
    const PolicyValue& threshold_value) const {
  return threshold_value.IsCompatibleWith(GetFeatureValue(feature));
}

PolicyValue DocumentPolicy::GetFeatureValue(
    mojom::DocumentPolicyFeature feature) const {
  return internal_feature_state_[static_cast<size_t>(feature)];
}

const base::Optional<std::string> DocumentPolicy::GetFeatureEndpoint(
    mojom::DocumentPolicyFeature feature) const {
  auto endpoint_it = endpoint_map_.find(feature);
  if (endpoint_it != endpoint_map_.end()) {
    return endpoint_it->second;
  } else {
    return base::nullopt;
  }
}

void DocumentPolicy::UpdateFeatureState(
    const DocumentPolicyFeatureState& feature_state) {
  for (const auto& feature_and_value : feature_state) {
    internal_feature_state_[static_cast<size_t>(feature_and_value.first)] =
        feature_and_value.second;
  }
}

DocumentPolicy::DocumentPolicy(const DocumentPolicyFeatureState& header_policy,
                               const FeatureEndpointMap& endpoint_map,
                               const DocumentPolicyFeatureState& defaults)
    : endpoint_map_(endpoint_map) {
  // Fill the internal feature state with default value first,
  // and overwrite the value if it is specified in the header.
  UpdateFeatureState(defaults);
  UpdateFeatureState(header_policy);
}

// static
std::unique_ptr<DocumentPolicy> DocumentPolicy::CreateWithHeaderPolicy(
    const DocumentPolicyFeatureState& header_policy,
    const FeatureEndpointMap& endpoint_map,
    const DocumentPolicyFeatureState& defaults) {
  std::unique_ptr<DocumentPolicy> new_policy = base::WrapUnique(
      new DocumentPolicy(header_policy, endpoint_map, defaults));
  return new_policy;
}

// static
bool DocumentPolicy::IsPolicyCompatible(
    const DocumentPolicyFeatureState& required_policy,
    const DocumentPolicyFeatureState& incoming_policy) {
  for (const auto& required_entry : required_policy) {
    const auto& feature = required_entry.first;
    const auto& required_value = required_entry.second;
    // Use default value when incoming policy does not specify a value.
    const auto incoming_entry = incoming_policy.find(feature);
    const auto& incoming_value =
        incoming_entry != incoming_policy.end()
            ? incoming_entry->second
            : GetDocumentPolicyFeatureInfoMap().at(feature).default_value;

    if (!incoming_value.IsCompatibleWith(required_value))
      return false;
  }
  return true;
}

}  // namespace blink
