blob: b235df9daff2575a03d000af411608f29fad6ae5 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// 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_event_dispatcher.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/strings/to_string.h"
#include "content/browser/payments/payment_app_provider_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/public/common/content_features.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
namespace content {
namespace {
using payments::mojom::CanMakePaymentEventDataPtr;
using payments::mojom::CanMakePaymentEventResponseType;
using payments::mojom::CanMakePaymentResponsePtr;
using payments::mojom::PaymentEventResponseType;
using payments::mojom::PaymentHandlerResponsePtr;
using payments::mojom::PaymentRequestEventDataPtr;
} // namespace
namespace {
void DidFindRegistration(
PaymentEventDispatcher::ServiceWorkerStartCallback callback,
blink::ServiceWorkerStatusCode service_worker_status,
scoped_refptr<ServiceWorkerRegistration> service_worker_registration) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
std::move(callback).Run(nullptr, service_worker_status);
return;
}
ServiceWorkerVersion* active_version =
service_worker_registration->active_version();
DCHECK(active_version);
active_version->RunAfterStartWorker(
ServiceWorkerMetrics::EventType::PAYMENT_REQUEST,
base::BindOnce(std::move(callback),
base::WrapRefCounted(active_version)));
}
void OnResponseForPaymentRequest(
base::WeakPtr<PaymentAppProviderImpl> provider,
int64_t registration_id,
const url::Origin& sw_origin,
const std::string& payment_request_id,
PaymentAppProvider::InvokePaymentAppCallback callback,
PaymentHandlerResponsePtr response) {
DevToolsBackgroundServicesContextImpl* dev_tools =
provider ? provider->GetDevTools(sw_origin) : nullptr;
if (dev_tools) {
std::stringstream response_type;
response_type << response->response_type;
dev_tools->LogBackgroundServiceEvent(
registration_id, blink::StorageKey::CreateFirstParty(sw_origin),
DevToolsBackgroundService::kPaymentHandler, "Payment response",
/*instance_id=*/payment_request_id,
{{"Method Name", response->method_name},
{"Details", response->stringified_details},
{"Type", response_type.str()}});
}
std::move(callback).Run(std::move(response));
}
void OnResponseForCanMakePayment(
base::WeakPtr<PaymentAppProviderImpl> provider,
int64_t registration_id,
const url::Origin& sw_origin,
const std::string& payment_request_id,
PaymentAppProvider::CanMakePaymentCallback callback,
CanMakePaymentResponsePtr response) {
DevToolsBackgroundServicesContextImpl* dev_tools =
provider ? provider->GetDevTools(sw_origin) : nullptr;
if (dev_tools) {
std::stringstream response_type;
response_type << response->response_type;
std::map<std::string, std::string> data = {
{"Type", response_type.str()},
{"Can Make Payment", base::ToString(response->can_make_payment)}};
dev_tools->LogBackgroundServiceEvent(
registration_id, blink::StorageKey::CreateFirstParty(sw_origin),
DevToolsBackgroundService::kPaymentHandler, "Can make payment response",
/*instance_id=*/payment_request_id, data);
}
std::move(callback).Run(std::move(response));
}
void OnResponseForAbortPayment(base::WeakPtr<PaymentAppProviderImpl> provider,
int64_t registration_id,
const url::Origin& sw_origin,
const std::string& payment_request_id,
PaymentAppProvider::AbortCallback callback,
bool payment_aborted) {
DevToolsBackgroundServicesContextImpl* dev_tools =
provider ? provider->GetDevTools(sw_origin) : nullptr;
if (dev_tools) {
dev_tools->LogBackgroundServiceEvent(
registration_id, blink::StorageKey::CreateFirstParty(sw_origin),
DevToolsBackgroundService::kPaymentHandler, "Abort payment response",
/*instance_id=*/payment_request_id,
{{"Payment Aborted", base::ToString(payment_aborted)}});
}
std::move(callback).Run(payment_aborted);
}
} // namespace
PaymentEventDispatcher::PaymentEventDispatcher() = default;
PaymentEventDispatcher::~PaymentEventDispatcher() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
void PaymentEventDispatcher::DispatchAbortPaymentEvent(
PaymentAppProvider::AbortCallback callback,
scoped_refptr<ServiceWorkerVersion> active_version,
blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false));
return;
}
DCHECK(active_version);
int event_finish_id = active_version->StartRequest(
ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT, base::DoNothing());
// This object self-deletes after either success or error callback is
// invoked.
RespondWithCallback* respond_with_callback = new AbortRespondWithCallback(
active_version, weak_ptr_factory_.GetWeakPtr(), std::move(callback));
active_version->endpoint()->DispatchAbortPaymentEvent(
respond_with_callback->BindNewPipeAndPassRemote(),
active_version->CreateSimpleEventCallback(event_finish_id));
}
void PaymentEventDispatcher::AbortPayment(
int64_t registration_id,
const url::Origin& sw_origin,
const std::string& payment_request_id,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
PaymentAppProvider::AbortCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
service_worker_context->FindReadyRegistrationForIdOnly(
registration_id,
base::BindOnce(
&DidFindRegistration,
base::BindOnce(
&PaymentEventDispatcher::DispatchAbortPaymentEvent,
weak_ptr_factory_.GetWeakPtr(),
base::BindOnce(&OnResponseForAbortPayment, payment_app_provider(),
registration_id, sw_origin, payment_request_id,
std::move(callback)))));
}
void PaymentEventDispatcher::DispatchCanMakePaymentEvent(
CanMakePaymentEventDataPtr event_data,
PaymentAppProvider::CanMakePaymentCallback callback,
scoped_refptr<ServiceWorkerVersion> active_version,
blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
std::move(callback),
PaymentAppProviderUtil::CreateBlankCanMakePaymentResponse(
CanMakePaymentEventResponseType::BROWSER_ERROR)));
return;
}
DCHECK(active_version);
int event_finish_id = active_version->StartRequest(
ServiceWorkerMetrics::EventType::CAN_MAKE_PAYMENT, base::DoNothing());
// This object self-deletes after either success or error callback is
// invoked.
RespondWithCallback* respond_with_callback =
new CanMakePaymentRespondWithCallback(
active_version, weak_ptr_factory_.GetWeakPtr(), std::move(callback));
active_version->endpoint()->DispatchCanMakePaymentEvent(
std::move(event_data), respond_with_callback->BindNewPipeAndPassRemote(),
active_version->CreateSimpleEventCallback(event_finish_id));
}
void PaymentEventDispatcher::CanMakePayment(
int64_t registration_id,
const url::Origin& sw_origin,
const std::string& payment_request_id,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
CanMakePaymentEventDataPtr event_data,
PaymentAppProvider::CanMakePaymentCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
service_worker_context->FindReadyRegistrationForIdOnly(
registration_id,
base::BindOnce(
&DidFindRegistration,
base::BindOnce(
&PaymentEventDispatcher::DispatchCanMakePaymentEvent,
weak_ptr_factory_.GetWeakPtr(), std::move(event_data),
base::BindOnce(&OnResponseForCanMakePayment,
payment_app_provider(), registration_id, sw_origin,
payment_request_id, std::move(callback)))));
}
void PaymentEventDispatcher::DispatchPaymentRequestEvent(
PaymentRequestEventDataPtr event_data,
PaymentAppProvider::InvokePaymentAppCallback callback,
scoped_refptr<ServiceWorkerVersion> active_version,
blink::ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (service_worker_status != blink::ServiceWorkerStatusCode::kOk) {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
std::move(callback),
content::PaymentAppProviderUtil::CreateBlankPaymentHandlerResponse(
PaymentEventResponseType::PAYMENT_EVENT_BROWSER_ERROR)));
return;
}
DCHECK(active_version);
int event_finish_id = active_version->StartRequest(
ServiceWorkerMetrics::EventType::PAYMENT_REQUEST, base::DoNothing());
invoke_respond_with_callback_ = std::make_unique<InvokeRespondWithCallback>(
active_version, weak_ptr_factory_.GetWeakPtr(), std::move(callback));
active_version->endpoint()->DispatchPaymentRequestEvent(
std::move(event_data),
invoke_respond_with_callback_->BindNewPipeAndPassRemote(),
active_version->CreateSimpleEventCallback(event_finish_id));
}
void PaymentEventDispatcher::InvokePayment(
int64_t registration_id,
const url::Origin& sw_origin,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
PaymentRequestEventDataPtr event_data,
PaymentAppProvider::InvokePaymentAppCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
service_worker_context->FindReadyRegistrationForIdOnly(
registration_id,
base::BindOnce(
&DidFindRegistration,
base::BindOnce(
&PaymentEventDispatcher::DispatchPaymentRequestEvent,
weak_ptr_factory_.GetWeakPtr(), std::move(event_data),
base::BindOnce(&OnResponseForPaymentRequest,
payment_app_provider(), registration_id, sw_origin,
event_data->payment_request_id,
std::move(callback)))));
}
void PaymentEventDispatcher::FindRegistration(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
int64_t registration_id,
PaymentEventDispatcher::ServiceWorkerStartCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
service_worker_context->FindReadyRegistrationForIdOnly(
registration_id,
base::BindOnce(&DidFindRegistration, std::move(callback)));
}
void PaymentEventDispatcher::OnClosingOpenedWindow(
PaymentEventResponseType reason) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
InvokeRespondWithCallback* callback = invoke_respond_with_callback_.get();
if (callback)
callback->AbortPaymentSinceOpennedWindowClosing(reason);
}
void PaymentEventDispatcher::ResetRespondWithCallback() {
invoke_respond_with_callback_.reset();
}
base::WeakPtr<PaymentEventDispatcher> PaymentEventDispatcher::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
} // namespace content.