// Copyright 2018 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 "components/update_client/protocol_parser_json.h"

#include <utility>

#include "base/json/json_reader.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"

namespace update_client {

namespace {

bool ParseManifest(const base::Value& manifest_node,
                   ProtocolParser::Result* result,
                   std::string* error) {
  if (!manifest_node.is_dict()) {
    *error = "'manifest' is not a dictionary.";
  }
  const auto* version = manifest_node.FindKey("version");
  if (!version || !version->is_string()) {
    *error = "Missing version for manifest.";
    return false;
  }

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

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

  const auto* packages_node = manifest_node.FindKey("packages");
  if (!packages_node || !packages_node->is_dict()) {
    *error = "Missing packages in manifest or 'packages' is not a dictionary.";
    return false;
  }
  const auto* package_node = packages_node->FindKey("package");
  if (!package_node || !package_node->is_list()) {
    *error = "Missing package in packages.";
    return false;
  }

  for (const auto& package : package_node->GetList()) {
    if (!package.is_dict()) {
      *error = "'package' is not a dictionary.";
      return false;
    }
    ProtocolParser::Result::Manifest::Package p;
    const auto* name = package.FindKey("name");
    if (!name || !name->is_string()) {
      *error = "Missing name for package.";
      return false;
    }
    p.name = name->GetString();

    const auto* namediff = package.FindKey("namediff");
    if (namediff && namediff->is_string())
      p.namediff = namediff->GetString();

    const auto* fingerprint = package.FindKey("fp");
    if (fingerprint && fingerprint->is_string())
      p.fingerprint = fingerprint->GetString();

    const auto* hash_sha256 = package.FindKey("hash_sha256");
    if (hash_sha256 && hash_sha256->is_string())
      p.hash_sha256 = hash_sha256->GetString();

    const auto* size = package.FindKey("size");
    if (size && (size->is_int() || size->is_double())) {
      const auto val = size->GetDouble();
      if (0 <= val && val < kProtocolMaxInt)
        p.size = size->GetDouble();
    }

    const auto* hashdiff_sha256 = package.FindKey("hashdiff_sha256");
    if (hashdiff_sha256 && hashdiff_sha256->is_string())
      p.hashdiff_sha256 = hashdiff_sha256->GetString();

    const auto* sizediff = package.FindKey("sizediff");
    if (sizediff && (sizediff->is_int() || sizediff->is_double())) {
      const auto val = sizediff->GetDouble();
      if (0 <= val && val < kProtocolMaxInt)
        p.sizediff = sizediff->GetDouble();
    }

    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 auto* action_node = actions_node.FindKey("action");
  if (!action_node || !action_node->is_list())
    return;

  const auto& action_list = action_node->GetList();
  if (action_list.empty() || !action_list[0].is_dict())
    return;

  const auto* run = action_list[0].FindKey("run");
  if (run && run->is_string())
    result->action_run = run->GetString();
}

bool ParseUrls(const base::Value& urls_node,
               ProtocolParser::Result* result,
               std::string* error) {
  if (!urls_node.is_dict()) {
    *error = "'urls' is not a dictionary.";
    return false;
  }
  const auto* url_node = urls_node.FindKey("url");
  if (!url_node || !url_node->is_list()) {
    *error = "Missing url on urls.";
    return false;
  }

  for (const auto& url : url_node->GetList()) {
    if (!url.is_dict())
      continue;
    const auto* codebase = url.FindKey("codebase");
    if (codebase && codebase->is_string()) {
      GURL crx_url(codebase->GetString());
      if (crx_url.is_valid())
        result->crx_urls.push_back(std::move(crx_url));
    }
    const auto* codebasediff = url.FindKey("codebasediff");
    if (codebasediff && codebasediff->is_string()) {
      GURL crx_diffurl(codebasediff->GetString());
      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;
}

bool ParseUpdateCheck(const base::Value& updatecheck_node,
                      ProtocolParser::Result* result,
                      std::string* error) {
  if (!updatecheck_node.is_dict()) {
    *error = "'updatecheck' is not a dictionary.";
    return false;
  }
  const auto* status = updatecheck_node.FindKey("status");
  if (!status || !status->is_string()) {
    *error = "Missing status on updatecheck node";
    return false;
  }

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

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

    const auto* urls_node = updatecheck_node.FindKey("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.FindKey("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,
              ProtocolParser::Result* result,
              std::string* error) {
  if (!app_node.is_dict()) {
    *error = "'app' is not a dictionary.";
    return false;
  }
  for (const auto* cohort_key :
       {ProtocolParser::Result::kCohort, ProtocolParser::Result::kCohortHint,
        ProtocolParser::Result::kCohortName}) {
    const auto* cohort_value = app_node.FindKey(cohort_key);
    if (cohort_value && cohort_value->is_string())
      result->cohort_attrs[cohort_key] = cohort_value->GetString();
  }
  const auto* appid = app_node.FindKey("appid");
  if (appid && appid->is_string())
    result->extension_id = appid->GetString();
  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 auto* status = app_node.FindKey("status");
  if (status && status->is_string()) {
    result->status = status->GetString();
    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;
    }
  }

  DCHECK(result->status.empty() || result->status == "ok");
  const auto* updatecheck_node = app_node.FindKey("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) {
  DCHECK(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(
      {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 auto* response_node = doc->FindKey("response");
  if (!response_node || !response_node->is_dict()) {
    ParseError("Missing 'response' element or 'response' is not a dictionary.");
    return false;
  }
  const auto* protocol = response_node->FindKey("protocol");
  if (!protocol || !protocol->is_string() ||
      protocol->GetString() != kProtocolVersion) {
    ParseError(
        "Missing/incorrect protocol."
        "(expected '%s', found '%s')",
        kProtocolVersion, protocol->GetString().c_str());
    return false;
  }

  const auto* daystart_node = response_node->FindKey("daystart");
  if (daystart_node && daystart_node->is_dict()) {
    const auto* elapsed_seconds = daystart_node->FindKey("elapsed_seconds");
    if (elapsed_seconds && elapsed_seconds->is_int())
      results->daystart_elapsed_seconds = elapsed_seconds->GetInt();
    const auto* elapsed_days = daystart_node->FindKey("elapsed_days");
    if (elapsed_days && elapsed_days->is_int())
      results->daystart_elapsed_days = elapsed_days->GetInt();
  }

  const auto* app_node = response_node->FindKey("app");
  if (app_node && app_node->is_list()) {
    for (const auto& app : app_node->GetList()) {
      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
