// Copyright 2017 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/payments/content/payment_method_manifest_table.h"

#include <time.h>
#include <string>

#include "base/feature_list.h"
#include "base/notreached.h"
#include "base/time/time.h"
#include "components/payments/core/secure_payment_confirmation_credential.h"
#include "components/webdata/common/web_database.h"
#include "content/public/common/content_features.h"
#include "sql/statement.h"
#include "sql/transaction.h"

namespace payments {
namespace {

// Data valid duration in seconds.
const time_t PAYMENT_METHOD_MANIFEST_VALID_TIME_IN_SECONDS = 90 * 24 * 60 * 60;

WebDatabaseTable::TypeKey GetPaymentMethodManifestKey() {
  // We just need a unique constant. Use the address of a static that
  // COMDAT folding won't touch in an optimizing linker.
  static int table_key = 0;
  return reinterpret_cast<void*>(&table_key);
}

}  // namespace

PaymentMethodManifestTable::PaymentMethodManifestTable() = default;

PaymentMethodManifestTable::~PaymentMethodManifestTable() = default;

PaymentMethodManifestTable* PaymentMethodManifestTable::FromWebDatabase(
    WebDatabase* db) {
  return static_cast<PaymentMethodManifestTable*>(
      db->GetTable(GetPaymentMethodManifestKey()));
}

WebDatabaseTable::TypeKey PaymentMethodManifestTable::GetTypeKey() const {
  return GetPaymentMethodManifestKey();
}

bool PaymentMethodManifestTable::CreateTablesIfNecessary() {
  if (!db_->Execute("CREATE TABLE IF NOT EXISTS payment_method_manifest ( "
                    "expire_date INTEGER NOT NULL DEFAULT 0, "
                    "method_name VARCHAR, "
                    "web_app_id VARCHAR)")) {
    NOTREACHED();
    return false;
  }

  // The `credential_id` column is 20 bytes for UbiKey on Linux, but the size
  // can vary for different authenticators. The relatively small sizes make it
  // OK to make `credential_id` the primary key.
  if (!db_->Execute(
          "CREATE TABLE IF NOT EXISTS secure_payment_confirmation_instrument ( "
          "credential_id BLOB NOT NULL PRIMARY KEY, "
          "relying_party_id VARCHAR NOT NULL, "
          "label VARCHAR NOT NULL, "
          "icon BLOB NOT NULL)")) {
    NOTREACHED();
    return false;
  }

  if (!db_->DoesColumnExist("secure_payment_confirmation_instrument",
                            "date_created")) {
    if (!db_->Execute(
            "ALTER TABLE secure_payment_confirmation_instrument ADD COLUMN "
            "date_created INTEGER NOT NULL DEFAULT 0")) {
      NOTREACHED();
      return false;
    }
  }

  if (!db_->DoesColumnExist("secure_payment_confirmation_instrument",
                            "user_id")) {
    if (!db_->Execute(
            "ALTER TABLE secure_payment_confirmation_instrument ADD COLUMN "
            "user_id BLOB")) {
      NOTREACHED();
      return false;
    }
  }

  return true;
}

bool PaymentMethodManifestTable::IsSyncable() {
  return false;
}

bool PaymentMethodManifestTable::MigrateToVersion(
    int version,
    bool* update_compatible_version) {
  return true;
}

void PaymentMethodManifestTable::RemoveExpiredData() {
  const base::Time now_date_in_seconds = base::Time::NowFromSystemTime();
  sql::Statement s(db_->GetUniqueStatement(
      "DELETE FROM payment_method_manifest WHERE expire_date < ?"));
  s.BindTime(0, now_date_in_seconds);
  s.Run();
}

bool PaymentMethodManifestTable::ClearSecurePaymentConfirmationCredentials(
    base::Time begin,
    base::Time end) {
  sql::Statement s(db_->GetUniqueStatement(
      "DELETE FROM secure_payment_confirmation_instrument WHERE (date_created "
      ">= ? AND date_created < ?) OR (date_created = 0)"));
  s.BindTime(0, begin);
  s.BindTime(1, end);
  return s.Run();
}

bool PaymentMethodManifestTable::AddManifest(
    const std::string& payment_method,
    const std::vector<std::string>& web_app_ids) {
  sql::Transaction transaction(db_);
  if (!transaction.Begin())
    return false;

  sql::Statement s1(db_->GetUniqueStatement(
      "DELETE FROM payment_method_manifest WHERE method_name=?"));
  s1.BindString(0, payment_method);
  if (!s1.Run())
    return false;

  sql::Statement s2(
      db_->GetUniqueStatement("INSERT INTO payment_method_manifest "
                              "(expire_date, method_name, web_app_id) "
                              "VALUES (?, ?, ?)"));
  const base::Time expire_date =
      base::Time::FromTimeT(base::Time::NowFromSystemTime().ToTimeT() +
                            PAYMENT_METHOD_MANIFEST_VALID_TIME_IN_SECONDS);
  for (const auto& id : web_app_ids) {
    int index = 0;
    s2.BindTime(index++, expire_date);
    s2.BindString(index++, payment_method);
    s2.BindString(index, id);
    if (!s2.Run())
      return false;
    s2.Reset(true);
  }

  if (!transaction.Commit())
    return false;

  return true;
}

std::vector<std::string> PaymentMethodManifestTable::GetManifest(
    const std::string& payment_method) {
  std::vector<std::string> web_app_ids;
  sql::Statement s(
      db_->GetUniqueStatement("SELECT web_app_id "
                              "FROM payment_method_manifest "
                              "WHERE method_name=?"));
  s.BindString(0, payment_method);

  while (s.Step()) {
    web_app_ids.emplace_back(s.ColumnString(0));
  }

  return web_app_ids;
}

bool PaymentMethodManifestTable::AddSecurePaymentConfirmationCredential(
    const SecurePaymentConfirmationCredential& credential) {
  if (!credential.IsValidNewCredential())
    return false;

  sql::Transaction transaction(db_);
  if (!transaction.Begin())
    return false;

  {
    // Check for credential identifier reuse by a different relying party.
    sql::Statement s0(
        db_->GetUniqueStatement("SELECT label "
                                "FROM secure_payment_confirmation_instrument "
                                "WHERE credential_id=? "
                                "AND relying_party_id<>?"));
    int index = 0;
    s0.BindBlob(index++, credential.credential_id);
    s0.BindString(index++, credential.relying_party_id);
    if (s0.Step())
      return false;
  }

  {
    sql::Statement s1(db_->GetUniqueStatement(
        "DELETE FROM secure_payment_confirmation_instrument "
        "WHERE credential_id=?"));
    s1.BindBlob(0, credential.credential_id);

    if (!s1.Run())
      return false;
  }

  {
    // The system authenticator will overwrite a discoverable credential with
    // the same relying party and user ID, so we also clear any such credential.
    sql::Statement s2(db_->GetUniqueStatement(
        "DELETE FROM secure_payment_confirmation_instrument "
        "WHERE relying_party_id=? "
        "AND user_id=?"));
    int index = 0;
    s2.BindString(index++, credential.relying_party_id);
    s2.BindBlob(index++, credential.user_id);

    if (!s2.Run())
      return false;
  }

  {
    sql::Statement s3(db_->GetUniqueStatement(
        "INSERT INTO secure_payment_confirmation_instrument "
        "(credential_id, relying_party_id, user_id, label, icon, date_created) "
        "VALUES (?, ?, ?, ?, ?, ?)"));
    int index = 0;
    s3.BindBlob(index++, credential.credential_id);
    s3.BindString(index++, credential.relying_party_id);
    s3.BindBlob(index++, credential.user_id);
    s3.BindString(index++, std::string());
    s3.BindBlob(index++, std::vector<uint8_t>());
    s3.BindTime(index++, base::Time::Now());

    if (!s3.Run())
      return false;
  }

  if (!transaction.Commit())
    return false;

  return true;
}

std::vector<std::unique_ptr<SecurePaymentConfirmationCredential>>
PaymentMethodManifestTable::GetSecurePaymentConfirmationCredentials(
    std::vector<std::vector<uint8_t>> credential_ids,
    const std::string& relying_party_id) {
  std::vector<std::unique_ptr<SecurePaymentConfirmationCredential>> credentials;
  sql::Statement s(
      db_->GetUniqueStatement("SELECT relying_party_id, user_id "
                              "FROM secure_payment_confirmation_instrument "
                              "WHERE credential_id=? "
                              "AND relying_party_id=?"));
  // The `credential_id` temporary variable is not `const` because it is
  // std::move()'d into the credential below.
  for (auto& credential_id : credential_ids) {
    s.Reset(true);
    if (credential_id.empty())
      continue;

    s.BindBlob(0, credential_id);
    s.BindString(1, relying_party_id);

    if (!s.Step())
      continue;

    auto credential = std::make_unique<SecurePaymentConfirmationCredential>();
    credential->credential_id = std::move(credential_id);

    int index = 0;
    credential->relying_party_id = s.ColumnString(index++);
    s.ColumnBlobAsVector(index++, &(credential->user_id));

    if (!credential->IsValid())
      continue;

    credentials.push_back(std::move(credential));
  }

  return credentials;
}

bool PaymentMethodManifestTable::ExecuteForTest(const char* sql) {
  return db_->Execute(sql);
}

bool PaymentMethodManifestTable::RazeForTest() {
  return db_->Raze();
}

bool PaymentMethodManifestTable::DoesColumnExistForTest(
    const char* table_name,
    const char* column_name) {
  return db_->DoesColumnExist(table_name, column_name);
}

}  // namespace payments
