blob: 924d36591cccf2301059877632df1a6164979577 [file] [log] [blame]
// 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/image/image.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);
// Note that the icon has been decoded to PNG raw data regardless of the
// original icon format that was downloaded.
gfx::Image icon_image = gfx::Image::CreateFrom1xPNGBytes(
reinterpret_cast<const unsigned char*>(icon_raw_data.data()),
icon_raw_data.size());
app->icon = std::make_unique<SkBitmap>(icon_image.AsBitmap());
}
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_->FindReadyRegistrationForPattern(
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_->FindReadyRegistrationForPattern(
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_->FindReadyRegistrationForPattern(
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_->FindReadyRegistrationForPattern(
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_->FindReadyRegistrationForPattern(
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_->FindReadyRegistrationForPattern(
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_->FindReadyRegistrationForPattern(
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->pattern().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->pattern().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->pattern().GetOrigin(),
{{CreatePaymentAppKey(registration->pattern().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_->FindReadyRegistrationForPattern(
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_->FindReadyRegistrationForPattern(
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->pattern().spec()),
base::BindOnce(&PaymentAppDatabase::DidGetPaymentAppInfoToSetUserHint,
weak_ptr_factory_.GetWeakPtr(), user_hint,
registration->id(), registration->pattern()));
}
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->pattern().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->pattern().GetOrigin();
std::string storage_key = CreatePaymentAppKey(registration->pattern().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->pattern().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->pattern().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->pattern().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