// Copyright 2016 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 "content/browser/payments/payment_app_database.h"

#include <map>
#include <utility>

#include "base/base64.h"
#include "base/bind.h"
#include "base/optional.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "content/browser/payments/payment_app.pb.h"
#include "content/browser/payments/payment_app_context_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace content {
namespace {

using ::payments::mojom::PaymentHandlerStatus;
using ::payments::mojom::PaymentInstrument;
using ::payments::mojom::PaymentInstrumentPtr;

const char kPaymentAppPrefix[] = "PaymentApp:";
const char kPaymentInstrumentPrefix[] = "PaymentInstrument:";
const char kPaymentInstrumentKeyInfoPrefix[] = "PaymentInstrumentKeyInfo:";

// |pattern| is the scope URL of the service worker registration.
std::string CreatePaymentAppKey(const std::string& pattern) {
  return kPaymentAppPrefix + pattern;
}

std::string CreatePaymentInstrumentKey(const std::string& instrument_key) {
  return kPaymentInstrumentPrefix + instrument_key;
}

std::string CreatePaymentInstrumentKeyInfoKey(
    const std::string& instrument_key) {
  return kPaymentInstrumentKeyInfoPrefix + instrument_key;
}

std::map<uint64_t, std::string> ToStoredPaymentInstrumentKeyInfos(
    const std::vector<std::string>& inputs) {
  std::map<uint64_t, std::string> key_info;
  for (const auto& input : inputs) {
    StoredPaymentInstrumentKeyInfoProto key_info_proto;
    if (!key_info_proto.ParseFromString(input))
      return std::map<uint64_t, std::string>();

    key_info.insert(std::pair<uint64_t, std::string>(
        key_info_proto.insertion_order(), key_info_proto.key()));
  }

  return key_info;
}

PaymentInstrumentPtr ToPaymentInstrumentForMojo(const std::string& input) {
  StoredPaymentInstrumentProto instrument_proto;
  if (!instrument_proto.ParseFromString(input))
    return nullptr;

  PaymentInstrumentPtr instrument = PaymentInstrument::New();
  instrument->name = instrument_proto.name();
  for (const auto& icon_proto : instrument_proto.icons()) {
    blink::Manifest::ImageResource icon;
    icon.src = GURL(icon_proto.src());
    icon.type = base::UTF8ToUTF16(icon_proto.type());
    for (const auto& size_proto : icon_proto.sizes()) {
      icon.sizes.emplace_back(size_proto.width(), size_proto.height());
    }
    instrument->icons.emplace_back(icon);
  }
  instrument->method = instrument_proto.method();
  instrument->stringified_capabilities =
      instrument_proto.stringified_capabilities();

  return instrument;
}

std::unique_ptr<StoredPaymentApp> ToStoredPaymentApp(const std::string& input) {
  StoredPaymentAppProto app_proto;
  if (!app_proto.ParseFromString(input))
    return std::unique_ptr<StoredPaymentApp>();

  std::unique_ptr<StoredPaymentApp> app = std::make_unique<StoredPaymentApp>();
  app->registration_id = app_proto.registration_id();
  app->scope = GURL(app_proto.scope());
  app->name = app_proto.name();
  app->prefer_related_applications = app_proto.prefer_related_applications();
  for (const auto& related_app : app_proto.related_applications()) {
    app->related_applications.emplace_back(StoredRelatedApplication());
    app->related_applications.back().platform = related_app.platform();
    app->related_applications.back().id = related_app.id();
  }
  app->user_hint = app_proto.user_hint();

  if (!app_proto.icon().empty()) {
    std::string icon_raw_data;
    base::Base64Decode(app_proto.icon(), &icon_raw_data);
    app->icon = std::make_unique<SkBitmap>();
    // Note that the icon has been decoded to PNG raw data regardless of the
    // original icon format that was downloaded.
    bool success = gfx::PNGCodec::Decode(
        reinterpret_cast<const unsigned char*>(icon_raw_data.data()),
        icon_raw_data.size(), app->icon.get());
    DCHECK(success);
  }

  return app;
}

}  // namespace

PaymentAppDatabase::PaymentAppDatabase(
    scoped_refptr<ServiceWorkerContextWrapper> service_worker_context)
    : service_worker_context_(service_worker_context), weak_ptr_factory_(this) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
}

PaymentAppDatabase::~PaymentAppDatabase() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
}

void PaymentAppDatabase::ReadAllPaymentApps(
    ReadAllPaymentAppsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->GetUserDataForAllRegistrationsByKeyPrefix(
      kPaymentAppPrefix,
      base::BindOnce(&PaymentAppDatabase::DidReadAllPaymentApps,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DeletePaymentInstrument(
    const GURL& scope,
    const std::string& instrument_key,
    DeletePaymentInstrumentCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->FindReadyRegistrationForScope(
      scope,
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToDeletePaymentInstrument,
          weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback)));
}

void PaymentAppDatabase::ReadPaymentInstrument(
    const GURL& scope,
    const std::string& instrument_key,
    ReadPaymentInstrumentCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->FindReadyRegistrationForScope(
      scope,
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToReadPaymentInstrument,
          weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback)));
}

void PaymentAppDatabase::KeysOfPaymentInstruments(
    const GURL& scope,
    KeysOfPaymentInstrumentsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->FindReadyRegistrationForScope(
      scope,
      base::BindOnce(&PaymentAppDatabase::DidFindRegistrationToGetKeys,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::HasPaymentInstrument(
    const GURL& scope,
    const std::string& instrument_key,
    HasPaymentInstrumentCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->FindReadyRegistrationForScope(
      scope,
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToHasPaymentInstrument,
          weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback)));
}

void PaymentAppDatabase::WritePaymentInstrument(
    const GURL& scope,
    const std::string& instrument_key,
    PaymentInstrumentPtr instrument,
    WritePaymentInstrumentCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (instrument->icons.size() > 0) {
    std::vector<blink::Manifest::ImageResource> icons(instrument->icons);
    PaymentInstrumentIconFetcher::Start(
        scope, service_worker_context_->GetProviderHostIds(scope.GetOrigin()),
        icons,
        base::BindOnce(&PaymentAppDatabase::DidFetchedPaymentInstrumentIcon,
                       weak_ptr_factory_.GetWeakPtr(), scope, instrument_key,
                       std::move(instrument), std::move(callback)));
  } else {
    service_worker_context_->FindReadyRegistrationForScope(
        scope,
        base::BindOnce(
            &PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument,
            weak_ptr_factory_.GetWeakPtr(), instrument_key,
            std::move(instrument), std::string(), std::move(callback)));
  }
}

void PaymentAppDatabase::DidFetchedPaymentInstrumentIcon(
    const GURL& scope,
    const std::string& instrument_key,
    payments::mojom::PaymentInstrumentPtr instrument,
    WritePaymentInstrumentCallback callback,
    const std::string& icon) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (icon.empty()) {
    std::move(callback).Run(PaymentHandlerStatus::FETCH_INSTRUMENT_ICON_FAILED);
    return;
  }

  service_worker_context_->FindReadyRegistrationForScope(
      scope,
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument,
          weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(instrument),
          icon, std::move(callback)));
}

void PaymentAppDatabase::FetchAndUpdatePaymentAppInfo(
    const GURL& context,
    const GURL& scope,
    FetchAndUpdatePaymentAppInfoCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  PaymentAppInfoFetcher::Start(
      context, service_worker_context_,
      base::BindOnce(&PaymentAppDatabase::FetchPaymentAppInfoCallback,
                     weak_ptr_factory_.GetWeakPtr(), scope,
                     std::move(callback)));
}

void PaymentAppDatabase::FetchPaymentAppInfoCallback(
    const GURL& scope,
    FetchAndUpdatePaymentAppInfoCallback callback,
    std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->FindReadyRegistrationForScope(
      scope, base::BindOnce(
                 &PaymentAppDatabase::DidFindRegistrationToUpdatePaymentAppInfo,
                 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
                 std::move(app_info)));
}

void PaymentAppDatabase::DidFindRegistrationToUpdatePaymentAppInfo(
    FetchAndUpdatePaymentAppInfoCallback callback,
    std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserDataByKeyPrefix(
      registration->id(), CreatePaymentAppKey(registration->scope().spec()),
      base::BindOnce(
          &PaymentAppDatabase::DidGetPaymentAppInfoToUpdatePaymentAppInfo,
          weak_ptr_factory_.GetWeakPtr(), std::move(callback),
          std::move(app_info), registration));
}

void PaymentAppDatabase::DidGetPaymentAppInfoToUpdatePaymentAppInfo(
    FetchAndUpdatePaymentAppInfoCallback callback,
    std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info,
    scoped_refptr<ServiceWorkerRegistration> registration,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  DCHECK_LE(data.size(), 1U);
  StoredPaymentAppProto payment_app_proto;
  if (data.size() == 1U) {
    payment_app_proto.ParseFromString(data[0]);
  }
  payment_app_proto.set_registration_id(registration->id());
  payment_app_proto.set_scope(registration->scope().spec());
  // Do not override name and icon if they are invalid.
  if (!app_info->name.empty()) {
    payment_app_proto.set_name(app_info->name);
  }
  if (!app_info->icon.empty()) {
    payment_app_proto.set_icon(app_info->icon);
  }
  payment_app_proto.set_prefer_related_applications(
      app_info->prefer_related_applications);
  for (const auto& related_app : app_info->related_applications) {
    StoredRelatedApplicationProto* related_app_proto =
        payment_app_proto.add_related_applications();
    related_app_proto->set_platform(related_app.platform);
    related_app_proto->set_id(related_app.id);
  }

  std::string serialized_payment_app;
  bool success = payment_app_proto.SerializeToString(&serialized_payment_app);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration->id(), registration->scope().GetOrigin(),
      {{CreatePaymentAppKey(registration->scope().spec()),
        serialized_payment_app}},
      base::BindOnce(&PaymentAppDatabase::DidUpdatePaymentApp,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
                     app_info->name.empty() | app_info->icon.empty()));
}

void PaymentAppDatabase::DidUpdatePaymentApp(
    FetchAndUpdatePaymentAppInfoCallback callback,
    bool fetch_app_info_failed,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  PaymentHandlerStatus handler_status =
      fetch_app_info_failed
          ? PaymentHandlerStatus::FETCH_PAYMENT_APP_INFO_FAILED
          : PaymentHandlerStatus::SUCCESS;
  handler_status = status == blink::ServiceWorkerStatusCode::kOk
                       ? handler_status
                       : PaymentHandlerStatus::STORAGE_OPERATION_FAILED;
  return std::move(callback).Run(handler_status);
}

void PaymentAppDatabase::ClearPaymentInstruments(
    const GURL& scope,
    ClearPaymentInstrumentsCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->FindReadyRegistrationForScope(
      scope,
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToClearPaymentInstruments,
          weak_ptr_factory_.GetWeakPtr(), scope, std::move(callback)));
}

void PaymentAppDatabase::SetPaymentAppUserHint(const GURL& scope,
                                               const std::string& user_hint) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->FindReadyRegistrationForScope(
      scope,
      base::BindOnce(
          &PaymentAppDatabase::DidFindRegistrationToSetPaymentAppUserHint,
          weak_ptr_factory_.GetWeakPtr(), user_hint));
}

void PaymentAppDatabase::DidFindRegistrationToSetPaymentAppUserHint(
    const std::string& user_hint,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk)
    return;

  service_worker_context_->GetRegistrationUserDataByKeyPrefix(
      registration->id(), CreatePaymentAppKey(registration->scope().spec()),
      base::BindOnce(&PaymentAppDatabase::DidGetPaymentAppInfoToSetUserHint,
                     weak_ptr_factory_.GetWeakPtr(), user_hint,
                     registration->id(), registration->scope()));
}

void PaymentAppDatabase::DidGetPaymentAppInfoToSetUserHint(
    const std::string& user_hint,
    int64_t registration_id,
    const GURL& pattern,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk)
    return;

  DCHECK_LE(data.size(), 1U);
  StoredPaymentAppProto app_proto;
  if (data.size() == 1U) {
    app_proto.ParseFromString(data[0]);
  }
  app_proto.set_user_hint(user_hint);

  std::string serialized_payment_app;
  bool success = app_proto.SerializeToString(&serialized_payment_app);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration_id, pattern.GetOrigin(),
      {{CreatePaymentAppKey(pattern.spec()), serialized_payment_app}},
      base::BindOnce(&PaymentAppDatabase::DidSetPaymentAppUserHint,
                     weak_ptr_factory_.GetWeakPtr()));
}

void PaymentAppDatabase::DidSetPaymentAppUserHint(
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(status == blink::ServiceWorkerStatusCode::kOk);
}

void PaymentAppDatabase::SetPaymentAppInfoForRegisteredServiceWorker(
    int64_t registration_id,
    const std::string& instrument_key,
    const std::string& name,
    const std::string& icon,
    const std::string& method,
    SetPaymentAppInfoCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  service_worker_context_->FindReadyRegistrationForIdOnly(
      registration_id,
      base::BindOnce(&PaymentAppDatabase::DidFindRegistrationToSetPaymentApp,
                     weak_ptr_factory_.GetWeakPtr(), instrument_key, name, icon,
                     method, std::move(callback)));
}

void PaymentAppDatabase::DidFindRegistrationToSetPaymentApp(
    const std::string& instrument_key,
    const std::string& name,
    const std::string& icon,
    const std::string& method,
    SetPaymentAppInfoCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  StoredPaymentAppProto payment_app_proto;
  payment_app_proto.set_registration_id(registration->id());
  payment_app_proto.set_scope(registration->scope().spec());
  payment_app_proto.set_name(name);
  payment_app_proto.set_icon(icon);

  std::string serialized_payment_app;
  bool success = payment_app_proto.SerializeToString(&serialized_payment_app);
  DCHECK(success);

  // Constructing registration_id, registration_origin and storage_key before
  // moving registration.
  int64_t registration_id = registration->id();
  GURL registration_origin = registration->scope().GetOrigin();
  std::string storage_key = CreatePaymentAppKey(registration->scope().spec());
  service_worker_context_->StoreRegistrationUserData(
      registration_id, registration_origin,
      {{storage_key, serialized_payment_app}},
      base::BindOnce(&PaymentAppDatabase::DidWritePaymentAppForSetPaymentApp,
                     weak_ptr_factory_.GetWeakPtr(), instrument_key, method,
                     std::move(callback), std::move(registration)));

  return;
}

void PaymentAppDatabase::DidWritePaymentAppForSetPaymentApp(
    const std::string& instrument_key,
    const std::string& method,
    SetPaymentAppInfoCallback callback,
    scoped_refptr<ServiceWorkerRegistration> registration,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
    return;
  }

  StoredPaymentInstrumentProto instrument_proto;
  instrument_proto.set_registration_id(registration->id());
  instrument_proto.set_instrument_key(instrument_key);
  instrument_proto.set_method(method);

  std::string serialized_instrument;
  bool success = instrument_proto.SerializeToString(&serialized_instrument);
  DCHECK(success);

  StoredPaymentInstrumentKeyInfoProto key_info_proto;
  key_info_proto.set_key(instrument_key);
  key_info_proto.set_insertion_order(base::Time::Now().ToInternalValue());

  std::string serialized_key_info;
  success = key_info_proto.SerializeToString(&serialized_key_info);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration->id(), registration->scope().GetOrigin(),
      {{CreatePaymentInstrumentKey(instrument_key), serialized_instrument},
       {CreatePaymentInstrumentKeyInfoKey(instrument_key),
        serialized_key_info}},
      base::BindOnce(
          &PaymentAppDatabase::DidWritePaymentInstrumentForSetPaymentApp,
          weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidWritePaymentInstrumentForSetPaymentApp(
    SetPaymentAppInfoCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  return std::move(callback).Run(
      status == blink::ServiceWorkerStatusCode::kOk
          ? PaymentHandlerStatus::SUCCESS
          : PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
}

void PaymentAppDatabase::DidReadAllPaymentApps(
    ReadAllPaymentAppsCallback callback,
    const std::vector<std::pair<int64_t, std::string>>& raw_data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentApps());
    return;
  }

  PaymentApps apps;
  for (const auto& item_of_raw_data : raw_data) {
    std::unique_ptr<StoredPaymentApp> app =
        ToStoredPaymentApp(item_of_raw_data.second);
    if (app)
      apps[app->registration_id] = std::move(app);
  }

  if (apps.size() == 0U) {
    std::move(callback).Run(PaymentApps());
    return;
  }

  service_worker_context_->GetUserDataForAllRegistrationsByKeyPrefix(
      kPaymentInstrumentPrefix,
      base::BindOnce(&PaymentAppDatabase::DidReadAllPaymentInstruments,
                     weak_ptr_factory_.GetWeakPtr(), std::move(apps),
                     std::move(callback)));
}

void PaymentAppDatabase::DidReadAllPaymentInstruments(
    PaymentApps apps,
    ReadAllPaymentAppsCallback callback,
    const std::vector<std::pair<int64_t, std::string>>& raw_data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(std::move(apps));
    return;
  }

  for (const auto& item_of_raw_data : raw_data) {
    StoredPaymentInstrumentProto instrument_proto;
    if (!instrument_proto.ParseFromString(item_of_raw_data.second))
      continue;

    int64_t id = instrument_proto.registration_id();
    if (!base::ContainsKey(apps, id))
      continue;

    apps[id]->enabled_methods.emplace_back(instrument_proto.method());
    apps[id]->capabilities.emplace_back(StoredCapabilities());
    for (const auto& network : instrument_proto.supported_card_networks()) {
      apps[id]->capabilities.back().supported_card_networks.emplace_back(
          network);
    }
    for (const auto& type : instrument_proto.supported_card_types()) {
      apps[id]->capabilities.back().supported_card_types.emplace_back(type);
    }
  }

  std::move(callback).Run(std::move(apps));
}

void PaymentAppDatabase::DidFindRegistrationToDeletePaymentInstrument(
    const std::string& instrument_key,
    DeletePaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserData(
      registration->id(), {CreatePaymentInstrumentKey(instrument_key)},
      base::BindOnce(&PaymentAppDatabase::DidFindPaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), registration->id(),
                     instrument_key, std::move(callback)));
}

void PaymentAppDatabase::DidFindPaymentInstrument(
    int64_t registration_id,
    const std::string& instrument_key,
    DeletePaymentInstrumentCallback callback,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
    std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  service_worker_context_->ClearRegistrationUserData(
      registration_id,
      {CreatePaymentInstrumentKey(instrument_key),
       CreatePaymentInstrumentKeyInfoKey(instrument_key)},
      base::BindOnce(&PaymentAppDatabase::DidDeletePaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidDeletePaymentInstrument(
    DeletePaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  return std::move(callback).Run(status == blink::ServiceWorkerStatusCode::kOk
                                     ? PaymentHandlerStatus::SUCCESS
                                     : PaymentHandlerStatus::NOT_FOUND);
}

void PaymentAppDatabase::DidFindRegistrationToReadPaymentInstrument(
    const std::string& instrument_key,
    ReadPaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentInstrument::New(),
                            PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserData(
      registration->id(), {CreatePaymentInstrumentKey(instrument_key)},
      base::BindOnce(&PaymentAppDatabase::DidReadPaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidReadPaymentInstrument(
    ReadPaymentInstrumentCallback callback,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
    std::move(callback).Run(PaymentInstrument::New(),
                            PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  PaymentInstrumentPtr instrument = ToPaymentInstrumentForMojo(data[0]);
  if (!instrument) {
    std::move(callback).Run(PaymentInstrument::New(),
                            PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
    return;
  }

  std::move(callback).Run(std::move(instrument), PaymentHandlerStatus::SUCCESS);
}

void PaymentAppDatabase::DidFindRegistrationToGetKeys(
    KeysOfPaymentInstrumentsCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(std::vector<std::string>(),
                            PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserDataByKeyPrefix(
      registration->id(), {kPaymentInstrumentKeyInfoPrefix},
      base::BindOnce(&PaymentAppDatabase::DidGetKeysOfPaymentInstruments,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidGetKeysOfPaymentInstruments(
    KeysOfPaymentInstrumentsCallback callback,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(std::vector<std::string>(),
                            PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  std::vector<std::string> keys;
  for (const auto& key_info : ToStoredPaymentInstrumentKeyInfos(data)) {
    keys.push_back(key_info.second);
  }

  std::move(callback).Run(keys, PaymentHandlerStatus::SUCCESS);
}

void PaymentAppDatabase::DidFindRegistrationToHasPaymentInstrument(
    const std::string& instrument_key,
    HasPaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  service_worker_context_->GetRegistrationUserData(
      registration->id(), {CreatePaymentInstrumentKey(instrument_key)},
      base::BindOnce(&PaymentAppDatabase::DidHasPaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidHasPaymentInstrument(
    DeletePaymentInstrumentCallback callback,
    const std::vector<std::string>& data,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk || data.size() != 1) {
    std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  std::move(callback).Run(PaymentHandlerStatus::SUCCESS);
}

void PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument(
    const std::string& instrument_key,
    PaymentInstrumentPtr instrument,
    const std::string& decoded_instrument_icon,
    WritePaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  StoredPaymentInstrumentProto instrument_proto;
  instrument_proto.set_registration_id(registration->id());
  instrument_proto.set_decoded_instrument_icon(decoded_instrument_icon);
  instrument_proto.set_instrument_key(instrument_key);
  instrument_proto.set_name(instrument->name);
  instrument_proto.set_method(instrument->method);
  for (const auto& icon : instrument->icons) {
    StoredPaymentInstrumentImageObject* image_object_proto =
        instrument_proto.add_icons();
    image_object_proto->set_src(icon.src.spec());
    image_object_proto->set_type(base::UTF16ToUTF8(icon.type));
    for (const auto& size : icon.sizes) {
      ImageSizeProto* size_proto = image_object_proto->add_sizes();
      size_proto->set_width(size.width());
      size_proto->set_height(size.height());
    }
  }
  instrument_proto.set_stringified_capabilities(
      instrument->stringified_capabilities);
  for (const auto& network : instrument->supported_networks) {
    instrument_proto.add_supported_card_networks(static_cast<int32_t>(network));
  }
  for (const auto& type : instrument->supported_types) {
    instrument_proto.add_supported_card_types(static_cast<int32_t>(type));
  }

  std::string serialized_instrument;
  bool success = instrument_proto.SerializeToString(&serialized_instrument);
  DCHECK(success);

  StoredPaymentInstrumentKeyInfoProto key_info_proto;
  key_info_proto.set_key(instrument_key);
  key_info_proto.set_insertion_order(base::Time::Now().ToInternalValue());

  std::string serialized_key_info;
  success = key_info_proto.SerializeToString(&serialized_key_info);
  DCHECK(success);

  service_worker_context_->StoreRegistrationUserData(
      registration->id(), registration->scope().GetOrigin(),
      {{CreatePaymentInstrumentKey(instrument_key), serialized_instrument},
       {CreatePaymentInstrumentKeyInfoKey(instrument_key),
        serialized_key_info}},
      base::BindOnce(&PaymentAppDatabase::DidWritePaymentInstrument,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidWritePaymentInstrument(
    WritePaymentInstrumentCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  return std::move(callback).Run(
      status == blink::ServiceWorkerStatusCode::kOk
          ? PaymentHandlerStatus::SUCCESS
          : PaymentHandlerStatus::STORAGE_OPERATION_FAILED);
}

void PaymentAppDatabase::DidFindRegistrationToClearPaymentInstruments(
    const GURL& scope,
    ClearPaymentInstrumentsCallback callback,
    blink::ServiceWorkerStatusCode status,
    scoped_refptr<ServiceWorkerRegistration> registration) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status != blink::ServiceWorkerStatusCode::kOk) {
    std::move(callback).Run(PaymentHandlerStatus::NO_ACTIVE_WORKER);
    return;
  }

  KeysOfPaymentInstruments(
      scope,
      base::BindOnce(&PaymentAppDatabase::DidGetKeysToClearPaymentInstruments,
                     weak_ptr_factory_.GetWeakPtr(), std::move(registration),
                     std::move(callback)));
}

void PaymentAppDatabase::DidGetKeysToClearPaymentInstruments(
    scoped_refptr<ServiceWorkerRegistration> registration,
    ClearPaymentInstrumentsCallback callback,
    const std::vector<std::string>& keys,
    PaymentHandlerStatus status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  if (status != PaymentHandlerStatus::SUCCESS) {
    std::move(callback).Run(PaymentHandlerStatus::NOT_FOUND);
    return;
  }

  std::vector<std::string> keys_with_prefix;
  for (const auto& key : keys) {
    keys_with_prefix.push_back(CreatePaymentInstrumentKey(key));
    keys_with_prefix.push_back(CreatePaymentInstrumentKeyInfoKey(key));
  }

  // Clear payment app info after clearing all payment instruments.
  keys_with_prefix.push_back(CreatePaymentAppKey(registration->scope().spec()));

  service_worker_context_->ClearRegistrationUserData(
      registration->id(), keys_with_prefix,
      base::BindOnce(&PaymentAppDatabase::DidClearPaymentInstruments,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void PaymentAppDatabase::DidClearPaymentInstruments(
    ClearPaymentInstrumentsCallback callback,
    blink::ServiceWorkerStatusCode status) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  return std::move(callback).Run(status == blink::ServiceWorkerStatusCode::kOk
                                     ? PaymentHandlerStatus::SUCCESS
                                     : PaymentHandlerStatus::NOT_FOUND);
}

}  // namespace content
