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

#include "components/update_client/protocol_parser_json.h"

#include <string>
#include <utility>

#include "base/check.h"
#include "base/json/json_reader.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "base/version.h"
#include "components/update_client/protocol_definition.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace update_client {

namespace {

std::string GetValueString(const base::Value::Dict& node, const char* key) {
  const std::string* value = node.FindString(key);
  return value ? *value : std::string();
}

bool ParseManifest(const base::Value& manifest_node_val,
                   ProtocolParser::Result* result,
                   std::string* error) {
  if (!manifest_node_val.is_dict()) {
    *error = "'manifest' is not a dictionary.";
    return false;
  }
  const base::Value::Dict& manifest_node = manifest_node_val.GetDict();
  const std::string* version = manifest_node.FindString("version");
  if (!version) {
    *error = "Missing version for manifest.";
    return false;
  }

  result->manifest.version = *version;
  if (!base::Version(result->manifest.version).IsValid()) {
    *error =
        base::StrCat({"Invalid version: '", result->manifest.version, "'."});
    return false;
  }

  // Get the optional minimum browser version.
  const std::string* browser_min_version =
      manifest_node.FindString("prodversionmin");
  if (browser_min_version) {
    result->manifest.browser_min_version = *browser_min_version;
    if (!base::Version(result->manifest.browser_min_version).IsValid()) {
      *error = base::StrCat({"Invalid prodversionmin: '",
                             result->manifest.browser_min_version, "'."});
      return false;
    }
  }

  result->manifest.run = GetValueString(manifest_node, "run");
  result->manifest.arguments = GetValueString(manifest_node, "arguments");

  const base::Value::Dict* packages_node = manifest_node.FindDict("packages");
  if (!packages_node) {
    *error = "Missing packages in manifest or 'packages' is not a dictionary.";
    return false;
  }
  const base::Value::List* package_node = packages_node->FindList("package");
  if (!package_node) {
    *error = "Missing package in packages.";
    return false;
  }

  for (const auto& package_val : *package_node) {
    if (!package_val.is_dict()) {
      *error = "'package' is not a dictionary.";
      return false;
    }
    const base::Value::Dict& package = package_val.GetDict();
    ProtocolParser::Result::Manifest::Package p;
    const std::string* name = package.FindString("name");
    if (!name) {
      *error = "Missing name for package.";
      return false;
    }
    p.name = *name;

    p.namediff = GetValueString(package, "namediff");
    p.fingerprint = GetValueString(package, "fp");
    p.hash_sha256 = GetValueString(package, "hash_sha256");
    p.hashdiff_sha256 = GetValueString(package, "hashdiff_sha256");

    const absl::optional<double> size = package.FindDouble("size");
    if (size) {
      const double val = size.value();
      if (0 <= val && val < kProtocolMaxInt)
        p.size = val;
    }

    const absl::optional<double> sizediff = package.FindDouble("sizediff");
    if (sizediff) {
      const double val = sizediff.value();
      if (0 <= val && val < kProtocolMaxInt)
        p.sizediff = val;
    }

    result->manifest.packages.push_back(std::move(p));
  }

  return true;
}

void ParseActions(const base::Value& actions_node,
                  ProtocolParser::Result* result) {
  if (!actions_node.is_dict())
    return;

  const base::Value::List* action_node =
      actions_node.GetDict().FindList("action");
  if (!action_node) {
    return;
  }

  const base::Value::List& action_list = *action_node;
  if (action_list.empty() || !action_list[0].is_dict())
    return;

  result->action_run = GetValueString(action_list[0].GetDict(), "run");
}

bool ParseUrls(const base::Value& urls_node_val,
               ProtocolParser::Result* result,
               std::string* error) {
  if (!urls_node_val.is_dict()) {
    *error = "'urls' is not a dictionary.";
    return false;
  }
  const base::Value::Dict& urls_node = urls_node_val.GetDict();
  const base::Value::List* url_node = urls_node.FindList("url");
  if (!url_node) {
    *error = "Missing url on urls.";
    return false;
  }

  for (const base::Value& url_val : *url_node) {
    if (!url_val.is_dict()) {
      continue;
    }
    const base::Value::Dict& url = url_val.GetDict();
    const std::string* codebase = url.FindString("codebase");
    if (codebase) {
      GURL crx_url(*codebase);
      if (crx_url.is_valid()) {
        result->crx_urls.push_back(std::move(crx_url));
      }
    }
    const std::string* codebasediff = url.FindString("codebasediff");
    if (codebasediff) {
      GURL crx_diffurl(*codebasediff);
      if (crx_diffurl.is_valid()) {
        result->crx_diffurls.push_back(std::move(crx_diffurl));
      }
    }
  }

  // Expect at least one url for full update.
  if (result->crx_urls.empty()) {
    *error = "Missing valid url for full update.";
    return false;
  }

  return true;
}

void ParseData(const base::Value& data_node_val,
               ProtocolParser::Result* result) {
  if (!data_node_val.is_dict()) {
    return;
  }
  const base::Value::Dict& data_node = data_node_val.GetDict();

  result->data.emplace_back(
      GetValueString(data_node, "status"), GetValueString(data_node, "name"),
      GetValueString(data_node, "index"), GetValueString(data_node, "#text"));
}

bool ParseUpdateCheck(const base::Value& updatecheck_node_val,
                      ProtocolParser::Result* result,
                      std::string* error) {
  if (!updatecheck_node_val.is_dict()) {
    *error = "'updatecheck' is not a dictionary.";
    return false;
  }
  const base::Value::Dict& updatecheck_node = updatecheck_node_val.GetDict();

  for (auto kv : updatecheck_node) {
    if (kv.first.front() == '_' && kv.second.is_string()) {
      result->custom_attributes[kv.first] = kv.second.GetString();
    }
  }

  const std::string* status = updatecheck_node.FindString("status");
  if (!status) {
    *error = "Missing status on updatecheck node";
    return false;
  }

  result->status = *status;
  if (result->status == "noupdate") {
    const auto* actions_node = updatecheck_node.Find("actions");
    if (actions_node)
      ParseActions(*actions_node, result);
    return true;
  }

  if (result->status == "ok") {
    const auto* actions_node = updatecheck_node.Find("actions");
    if (actions_node)
      ParseActions(*actions_node, result);

    const auto* urls_node = updatecheck_node.Find("urls");
    if (!urls_node) {
      *error = "Missing urls on updatecheck.";
      return false;
    }

    if (!ParseUrls(*urls_node, result, error))
      return false;

    const auto* manifest_node = updatecheck_node.Find("manifest");
    if (!manifest_node) {
      *error = "Missing manifest on updatecheck.";
      return false;
    }
    return ParseManifest(*manifest_node, result, error);
  }

  // Return the |updatecheck| element status as a parsing error.
  *error = result->status;
  return false;
}

bool ParseApp(const base::Value& app_node_val,
              ProtocolParser::Result* result,
              std::string* error) {
  if (!app_node_val.is_dict()) {
    *error = "'app' is not a dictionary.";
    return false;
  }
  const base::Value::Dict& app_node = app_node_val.GetDict();
  for (const auto* cohort_key :
       {ProtocolParser::Result::kCohort, ProtocolParser::Result::kCohortHint,
        ProtocolParser::Result::kCohortName}) {
    const std::string* cohort_value = app_node.FindString(cohort_key);
    if (cohort_value) {
      result->cohort_attrs[cohort_key] = *cohort_value;
    }
  }
  const std::string* appid = app_node.FindString("appid");
  if (appid) {
    result->extension_id = *appid;
  }
  if (result->extension_id.empty()) {
    *error = "Missing appid on app node";
    return false;
  }

  // Read the |status| attribute for the app.
  // If the status is one of the defined app status error literals, then return
  // it in the result as if it were an updatecheck status, then stop parsing,
  // and return success.
  const std::string* status = app_node.FindString("status");
  if (status) {
    result->status = *status;
    if (result->status == "restricted" ||
        result->status == "error-unknownApplication" ||
        result->status == "error-invalidAppId")
      return true;

    // If the status was not handled above and the status is not "ok", then
    // this must be a status literal that that the parser does not know about.
    if (!result->status.empty() && result->status != "ok") {
      *error = "Unknown app status";
      return false;
    }
  }

  CHECK(result->status.empty() || result->status == "ok");

  if (const base::Value::List* data_node = app_node.FindList("data")) {
    base::ranges::for_each(*data_node, [&result](const base::Value& data) {
      ParseData(data, result);
    });
  }

  const auto* updatecheck_node = app_node.Find("updatecheck");
  if (!updatecheck_node) {
    *error = "Missing updatecheck on app.";
    return false;
  }

  return ParseUpdateCheck(*updatecheck_node, result, error);
}

}  // namespace

bool ProtocolParserJSON::DoParse(const std::string& response_json,
                                 Results* results) {
  CHECK(results);

  if (response_json.empty()) {
    ParseError("Empty JSON.");
    return false;
  }

  // The JSON response contains a prefix to prevent XSSI.
  constexpr char kJSONPrefix[] = ")]}'";
  if (!base::StartsWith(response_json, kJSONPrefix,
                        base::CompareCase::SENSITIVE)) {
    ParseError("Missing secure JSON prefix.");
    return false;
  }
  const auto doc = base::JSONReader::Read(base::MakeStringPiece(
      response_json.begin() + std::char_traits<char>::length(kJSONPrefix),
      response_json.end()));
  if (!doc) {
    ParseError("JSON read error.");
    return false;
  }
  if (!doc->is_dict()) {
    ParseError("JSON document is not a dictionary.");
    return false;
  }
  const base::Value::Dict* response_node = doc->GetDict().FindDict("response");
  if (!response_node) {
    ParseError("Missing 'response' element or 'response' is not a dictionary.");
    return false;
  }
  const std::string* protocol = response_node->FindString("protocol");
  if (!protocol) {
    ParseError("Missing/non-string protocol.");
    return false;
  }
  if (*protocol != kProtocolVersion) {
    ParseError("Incorrect protocol. (expected '%s', found '%s')",
               kProtocolVersion, protocol->c_str());
    return false;
  }

  const base::Value::Dict* daystart_node = response_node->FindDict("daystart");
  if (daystart_node) {
    const absl::optional<int> elapsed_seconds =
        daystart_node->FindInt("elapsed_seconds");
    if (elapsed_seconds) {
      results->daystart_elapsed_seconds = elapsed_seconds.value();
    }
    const absl::optional<int> elapsed_days =
        daystart_node->FindInt("elapsed_days");
    if (elapsed_days) {
      results->daystart_elapsed_days = elapsed_days.value();
    }
  }

  const base::Value::Dict* systemrequirements_node =
      response_node->FindDict("systemrequirements");
  if (systemrequirements_node) {
    const std::string* platform =
        systemrequirements_node->FindString("platform");
    if (platform) {
      results->system_requirements.platform = *platform;
    }
    const std::string* arch = systemrequirements_node->FindString("arch");
    if (arch) {
      results->system_requirements.arch = *arch;
    }
    const std::string* min_os_version =
        systemrequirements_node->FindString("min_os_version");
    if (min_os_version) {
      results->system_requirements.min_os_version = *min_os_version;
    }
  }

  const base::Value::List* app_node = response_node->FindList("app");
  if (app_node) {
    for (const auto& app : *app_node) {
      Result result;
      std::string error;
      if (ParseApp(app, &result, &error))
        results->list.push_back(result);
      else
        ParseError("%s", error.c_str());
    }
  }

  return true;
}

}  // namespace update_client
