| // 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. |