// Copyright 2017 The Chromium OS 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 "authpolicy/policy/extension_policy_encoder.h"

#include <utility>

#include <base/json/json_string_value_serializer.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/values.h>
#include <components/policy/core/common/registry_dict.h>

#include "bindings/authpolicy_containers.pb.h"

namespace policy {

namespace {

// Converts a RegistryDict to a DictionaryValue by converting all keys() to
// Values. In case of name collisions, keys win over values. Similar to
// RegistryDict::ConvertToJSON, just without schema validation.
std::unique_ptr<base::Value> ConvertToValue(const RegistryDict& dict) {
  auto value = std::make_unique<base::DictionaryValue>();
  for (const auto& entry : dict.values())
    value->SetWithoutPathExpansion(entry.first, entry.second->CreateDeepCopy());
  for (const auto& entry : dict.keys())
    value->SetWithoutPathExpansion(entry.first, ConvertToValue(*entry.second));
  return std::move(value);
}

// Verifies that id is a Chrome extension id. Pretty much copied from
// components/crx_file/id_util.cc.
bool IsValidExtensionId(const std::string& id) {
  if (id.size() != 32)
    return false;

  std::string temp = base::ToLowerASCII(id);
  for (size_t n = 0; n < id.size(); n++) {
    char ch = base::ToLowerASCII(id[n]);
    if (ch < 'a' || ch > 'p')
      return false;
  }

  return true;
}

}  // namespace

ExtensionPolicyEncoder::ExtensionPolicyEncoder(const RegistryDict* dict)
    : dict_(dict) {}

void ExtensionPolicyEncoder::EncodePolicy(ExtensionPolicies* policies) const {
  policies->clear();
  for (const auto& id_and_dict : dict_->keys()) {
    const std::string& extension_id = id_and_dict.first;
    const RegistryDict* dict = id_and_dict.second.get();
    DCHECK(dict);
    if (!IsValidExtensionId(extension_id)) {
      LOG(ERROR) << "Failed to convert policy for extension: Invalid ID '"
                 << extension_id << "'. Ignoring.";
      continue;
    }

    // Convert dict to a JSON string.
    std::string json_data;
    std::unique_ptr<base::Value> value = ConvertToValue(*dict);
    JSONStringValueSerializer serializer(&json_data);
    if (!serializer.Serialize(*value)) {
      LOG(ERROR) << "Failed to convert policy for extension '" << extension_id
                 << "' to JSON. Ignoring.";
      continue;
    }

    authpolicy::protos::ExtensionPolicy policy;
    policy.set_id(extension_id);
    policy.set_json_data(std::move(json_data));
    policies->push_back(std::move(policy));

    if (log_policy_values_) {
      // Serialize again, but with pretty printing. This is debug only and
      // usually disabled in production.
      std::string pretty_json;
      JSONStringValueSerializer pretty_serializer(&pretty_json);
      pretty_serializer.set_pretty_print(true);
      pretty_serializer.Serialize(*value);
      LOG(INFO) << "Extension policy (id '" << extension_id << "')";
      std::vector<std::string> lines = base::SplitString(
          pretty_json, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
      for (const std::string& line : lines)
        LOG(INFO) << line;
    }
  }
}

}  // namespace policy
