diff options
Diffstat (limited to 'dom/payments/ipc/PaymentRequestParent.cpp')
-rw-r--r-- | dom/payments/ipc/PaymentRequestParent.cpp | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/dom/payments/ipc/PaymentRequestParent.cpp b/dom/payments/ipc/PaymentRequestParent.cpp new file mode 100644 index 0000000000..38a41ec9b1 --- /dev/null +++ b/dom/payments/ipc/PaymentRequestParent.cpp @@ -0,0 +1,468 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/ipc/InputStreamUtils.h" +#include "nsArrayUtils.h" +#include "nsCOMPtr.h" +#include "nsIPaymentRequestService.h" +#include "nsISupportsPrimitives.h" +#include "nsServiceManagerUtils.h" +#include "PaymentRequestData.h" +#include "PaymentRequestParent.h" +#include "PaymentRequestService.h" + +namespace mozilla::dom { + +PaymentRequestParent::PaymentRequestParent() + : mActorAlive(true), mRequestId(u""_ns) {} + +mozilla::ipc::IPCResult PaymentRequestParent::RecvRequestPayment( + const IPCPaymentActionRequest& aRequest) { + if (!mActorAlive) { + return IPC_FAIL_NO_REASON(this); + } + switch (aRequest.type()) { + case IPCPaymentActionRequest::TIPCPaymentCreateActionRequest: { + const IPCPaymentCreateActionRequest& request = aRequest; + mRequestId = request.requestId(); + break; + } + case IPCPaymentActionRequest::TIPCPaymentCanMakeActionRequest: { + const IPCPaymentCanMakeActionRequest& request = aRequest; + mRequestId = request.requestId(); + break; + } + case IPCPaymentActionRequest::TIPCPaymentShowActionRequest: { + const IPCPaymentShowActionRequest& request = aRequest; + mRequestId = request.requestId(); + break; + } + case IPCPaymentActionRequest::TIPCPaymentAbortActionRequest: { + const IPCPaymentAbortActionRequest& request = aRequest; + mRequestId = request.requestId(); + break; + } + case IPCPaymentActionRequest::TIPCPaymentCompleteActionRequest: { + const IPCPaymentCompleteActionRequest& request = aRequest; + mRequestId = request.requestId(); + break; + } + case IPCPaymentActionRequest::TIPCPaymentUpdateActionRequest: { + const IPCPaymentUpdateActionRequest& request = aRequest; + mRequestId = request.requestId(); + break; + } + case IPCPaymentActionRequest::TIPCPaymentCloseActionRequest: { + const IPCPaymentCloseActionRequest& request = aRequest; + mRequestId = request.requestId(); + break; + } + case IPCPaymentActionRequest::TIPCPaymentRetryActionRequest: { + const IPCPaymentRetryActionRequest& request = aRequest; + mRequestId = request.requestId(); + break; + } + default: { + return IPC_FAIL(this, "Unknown PaymentRequest action type"); + } + } + nsCOMPtr<nsIPaymentRequestService> service = + do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID); + MOZ_ASSERT(service); + PaymentRequestService* rowService = + static_cast<PaymentRequestService*>(service.get()); + MOZ_ASSERT(rowService); + nsresult rv = rowService->RequestPayment(mRequestId, aRequest, this); + if (NS_WARN_IF(NS_FAILED(rv))) { + return IPC_FAIL(this, "nsIPaymentRequestService::RequestPayment failed"); + } + return IPC_OK(); +} + +nsresult PaymentRequestParent::RespondPayment( + nsIPaymentActionResponse* aResponse) { + if (!NS_IsMainThread()) { + RefPtr<PaymentRequestParent> self = this; + nsCOMPtr<nsIPaymentActionResponse> response = aResponse; + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "PaymentRequestParent::RespondPayment", + [self, response]() { self->RespondPayment(response); }); + return NS_DispatchToMainThread(r); + } + + if (!mActorAlive) { + return NS_ERROR_FAILURE; + } + uint32_t type; + nsresult rv = aResponse->GetType(&type); + NS_ENSURE_SUCCESS(rv, rv); + nsAutoString requestId; + rv = aResponse->GetRequestId(requestId); + NS_ENSURE_SUCCESS(rv, rv); + switch (type) { + case nsIPaymentActionResponse::CANMAKE_ACTION: { + nsCOMPtr<nsIPaymentCanMakeActionResponse> response = + do_QueryInterface(aResponse); + MOZ_ASSERT(response); + bool result; + rv = response->GetResult(&result); + NS_ENSURE_SUCCESS(rv, rv); + IPCPaymentCanMakeActionResponse actionResponse(requestId, result); + if (!SendRespondPayment(actionResponse)) { + return NS_ERROR_FAILURE; + } + break; + } + case nsIPaymentActionResponse::SHOW_ACTION: { + nsCOMPtr<nsIPaymentShowActionResponse> response = + do_QueryInterface(aResponse); + MOZ_ASSERT(response); + uint32_t acceptStatus; + NS_ENSURE_SUCCESS(response->GetAcceptStatus(&acceptStatus), + NS_ERROR_FAILURE); + nsAutoString methodName; + NS_ENSURE_SUCCESS(response->GetMethodName(methodName), NS_ERROR_FAILURE); + IPCPaymentResponseData ipcData; + if (acceptStatus == nsIPaymentActionResponse::PAYMENT_ACCEPTED) { + nsCOMPtr<nsIPaymentResponseData> data; + NS_ENSURE_SUCCESS(response->GetData(getter_AddRefs(data)), + NS_ERROR_FAILURE); + MOZ_ASSERT(data); + NS_ENSURE_SUCCESS(SerializeResponseData(ipcData, data), + NS_ERROR_FAILURE); + } else { + ipcData = IPCGeneralResponse(); + } + + nsAutoString payerName; + NS_ENSURE_SUCCESS(response->GetPayerName(payerName), NS_ERROR_FAILURE); + nsAutoString payerEmail; + NS_ENSURE_SUCCESS(response->GetPayerEmail(payerEmail), NS_ERROR_FAILURE); + nsAutoString payerPhone; + NS_ENSURE_SUCCESS(response->GetPayerPhone(payerPhone), NS_ERROR_FAILURE); + IPCPaymentShowActionResponse actionResponse( + requestId, acceptStatus, methodName, ipcData, payerName, payerEmail, + payerPhone); + if (!SendRespondPayment(actionResponse)) { + return NS_ERROR_FAILURE; + } + break; + } + case nsIPaymentActionResponse::ABORT_ACTION: { + nsCOMPtr<nsIPaymentAbortActionResponse> response = + do_QueryInterface(aResponse); + MOZ_ASSERT(response); + bool isSucceeded; + rv = response->IsSucceeded(&isSucceeded); + NS_ENSURE_SUCCESS(rv, rv); + IPCPaymentAbortActionResponse actionResponse(requestId, isSucceeded); + if (!SendRespondPayment(actionResponse)) { + return NS_ERROR_FAILURE; + } + break; + } + case nsIPaymentActionResponse::COMPLETE_ACTION: { + nsCOMPtr<nsIPaymentCompleteActionResponse> response = + do_QueryInterface(aResponse); + MOZ_ASSERT(response); + bool isCompleted; + rv = response->IsCompleted(&isCompleted); + NS_ENSURE_SUCCESS(rv, rv); + IPCPaymentCompleteActionResponse actionResponse(requestId, isCompleted); + if (!SendRespondPayment(actionResponse)) { + return NS_ERROR_FAILURE; + } + break; + } + default: { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} + +nsresult PaymentRequestParent::ChangeShippingAddress( + const nsAString& aRequestId, nsIPaymentAddress* aAddress) { + if (!NS_IsMainThread()) { + RefPtr<PaymentRequestParent> self = this; + nsCOMPtr<nsIPaymentAddress> address = aAddress; + nsAutoString requestId(aRequestId); + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "dom::PaymentRequestParent::ChangeShippingAddress", + [self, requestId, address]() { + self->ChangeShippingAddress(requestId, address); + }); + return NS_DispatchToMainThread(r); + } + if (!mActorAlive) { + return NS_ERROR_FAILURE; + } + + IPCPaymentAddress ipcAddress; + nsresult rv = SerializeAddress(ipcAddress, aAddress); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString requestId(aRequestId); + if (!SendChangeShippingAddress(requestId, ipcAddress)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +nsresult PaymentRequestParent::ChangeShippingOption(const nsAString& aRequestId, + const nsAString& aOption) { + if (!NS_IsMainThread()) { + RefPtr<PaymentRequestParent> self = this; + nsAutoString requestId(aRequestId); + nsAutoString option(aOption); + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "dom::PaymentRequestParent::ChangeShippingOption", + [self, requestId, option]() { + self->ChangeShippingOption(requestId, option); + }); + return NS_DispatchToMainThread(r); + } + if (!mActorAlive) { + return NS_ERROR_FAILURE; + } + nsAutoString requestId(aRequestId); + nsAutoString option(aOption); + if (!SendChangeShippingOption(requestId, option)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +nsresult PaymentRequestParent::ChangePayerDetail(const nsAString& aRequestId, + const nsAString& aPayerName, + const nsAString& aPayerEmail, + const nsAString& aPayerPhone) { + nsAutoString requestId(aRequestId); + nsAutoString payerName(aPayerName); + nsAutoString payerEmail(aPayerEmail); + nsAutoString payerPhone(aPayerPhone); + if (!NS_IsMainThread()) { + RefPtr<PaymentRequestParent> self = this; + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "dom::PaymentRequestParent::ChangePayerDetail", + [self, requestId, payerName, payerEmail, payerPhone]() { + self->ChangePayerDetail(requestId, payerName, payerEmail, payerPhone); + }); + return NS_DispatchToMainThread(r); + } + if (!mActorAlive) { + return NS_ERROR_FAILURE; + } + if (!SendChangePayerDetail(requestId, payerName, payerEmail, payerPhone)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +nsresult PaymentRequestParent::ChangePaymentMethod( + const nsAString& aRequestId, const nsAString& aMethodName, + nsIMethodChangeDetails* aMethodDetails) { + nsAutoString requestId(aRequestId); + nsAutoString methodName(aMethodName); + nsCOMPtr<nsIMethodChangeDetails> methodDetails(aMethodDetails); + if (!NS_IsMainThread()) { + RefPtr<PaymentRequestParent> self = this; + nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction( + "dom::PaymentRequestParent::ChangePaymentMethod", + [self, requestId, methodName, methodDetails]() { + self->ChangePaymentMethod(requestId, methodName, methodDetails); + }); + return NS_DispatchToMainThread(r); + } + if (!mActorAlive) { + return NS_ERROR_FAILURE; + } + + // Convert nsIMethodChangeDetails to IPCMethodChangeDetails + // aMethodChangeDetails can be null + IPCMethodChangeDetails ipcChangeDetails; + if (aMethodDetails) { + uint32_t dataType; + NS_ENSURE_SUCCESS(aMethodDetails->GetType(&dataType), NS_ERROR_FAILURE); + switch (dataType) { + case nsIMethodChangeDetails::GENERAL_DETAILS: { + nsCOMPtr<nsIGeneralChangeDetails> details = + do_QueryInterface(methodDetails); + MOZ_ASSERT(details); + IPCGeneralChangeDetails ipcGeneralDetails; + NS_ENSURE_SUCCESS(details->GetDetails(ipcGeneralDetails.details()), + NS_ERROR_FAILURE); + ipcChangeDetails = ipcGeneralDetails; + break; + } + case nsIMethodChangeDetails::BASICCARD_DETAILS: { + nsCOMPtr<nsIBasicCardChangeDetails> details = + do_QueryInterface(methodDetails); + MOZ_ASSERT(details); + IPCBasicCardChangeDetails ipcBasicCardDetails; + nsCOMPtr<nsIPaymentAddress> address; + NS_ENSURE_SUCCESS(details->GetBillingAddress(getter_AddRefs(address)), + NS_ERROR_FAILURE); + IPCPaymentAddress ipcAddress; + NS_ENSURE_SUCCESS(SerializeAddress(ipcAddress, address), + NS_ERROR_FAILURE); + ipcBasicCardDetails.billingAddress() = ipcAddress; + ipcChangeDetails = ipcBasicCardDetails; + break; + } + default: { + return NS_ERROR_FAILURE; + } + } + } + if (!SendChangePaymentMethod(requestId, methodName, ipcChangeDetails)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +mozilla::ipc::IPCResult PaymentRequestParent::Recv__delete__() { + mActorAlive = false; + return IPC_OK(); +} + +void PaymentRequestParent::ActorDestroy(ActorDestroyReason aWhy) { + mActorAlive = false; + nsCOMPtr<nsIPaymentRequestService> service = + do_GetService(NS_PAYMENT_REQUEST_SERVICE_CONTRACT_ID); + MOZ_ASSERT(service); + if (!mRequestId.Equals(u""_ns)) { + nsCOMPtr<nsIPaymentRequest> request; + nsresult rv = + service->GetPaymentRequestById(mRequestId, getter_AddRefs(request)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + if (!request) { + return; + } + payments::PaymentRequest* rowRequest = + static_cast<payments::PaymentRequest*>(request.get()); + MOZ_ASSERT(rowRequest); + rowRequest->SetIPC(nullptr); + } +} + +nsresult PaymentRequestParent::SerializeAddress(IPCPaymentAddress& aIPCAddress, + nsIPaymentAddress* aAddress) { + // address can be nullptr + if (!aAddress) { + return NS_OK; + } + nsAutoString country; + nsresult rv = aAddress->GetCountry(country); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIArray> iaddressLine; + rv = aAddress->GetAddressLine(getter_AddRefs(iaddressLine)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString region; + rv = aAddress->GetRegion(region); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString regionCode; + rv = aAddress->GetRegionCode(regionCode); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString city; + rv = aAddress->GetCity(city); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString dependentLocality; + rv = aAddress->GetDependentLocality(dependentLocality); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString postalCode; + rv = aAddress->GetPostalCode(postalCode); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString sortingCode; + rv = aAddress->GetSortingCode(sortingCode); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString organization; + rv = aAddress->GetOrganization(organization); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString recipient; + rv = aAddress->GetRecipient(recipient); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString phone; + rv = aAddress->GetPhone(phone); + NS_ENSURE_SUCCESS(rv, rv); + + nsTArray<nsString> addressLine; + uint32_t length; + rv = iaddressLine->GetLength(&length); + NS_ENSURE_SUCCESS(rv, rv); + for (uint32_t index = 0; index < length; ++index) { + nsCOMPtr<nsISupportsString> iaddress = + do_QueryElementAt(iaddressLine, index); + MOZ_ASSERT(iaddress); + nsAutoString address; + rv = iaddress->GetData(address); + NS_ENSURE_SUCCESS(rv, rv); + addressLine.AppendElement(address); + } + + aIPCAddress = IPCPaymentAddress(country, addressLine, region, regionCode, + city, dependentLocality, postalCode, + sortingCode, organization, recipient, phone); + return NS_OK; +} + +nsresult PaymentRequestParent::SerializeResponseData( + IPCPaymentResponseData& aIPCData, nsIPaymentResponseData* aData) { + NS_ENSURE_ARG_POINTER(aData); + uint32_t dataType; + NS_ENSURE_SUCCESS(aData->GetType(&dataType), NS_ERROR_FAILURE); + switch (dataType) { + case nsIPaymentResponseData::GENERAL_RESPONSE: { + nsCOMPtr<nsIGeneralResponseData> response = do_QueryInterface(aData); + MOZ_ASSERT(response); + IPCGeneralResponse data; + NS_ENSURE_SUCCESS(response->GetData(data.data()), NS_ERROR_FAILURE); + aIPCData = data; + break; + } + case nsIPaymentResponseData::BASICCARD_RESPONSE: { + nsCOMPtr<nsIBasicCardResponseData> response = do_QueryInterface(aData); + MOZ_ASSERT(response); + IPCBasicCardResponse data; + NS_ENSURE_SUCCESS(response->GetCardholderName(data.cardholderName()), + NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(response->GetCardNumber(data.cardNumber()), + NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(response->GetExpiryMonth(data.expiryMonth()), + NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(response->GetExpiryYear(data.expiryYear()), + NS_ERROR_FAILURE); + NS_ENSURE_SUCCESS(response->GetCardSecurityCode(data.cardSecurityCode()), + NS_ERROR_FAILURE); + nsCOMPtr<nsIPaymentAddress> address; + NS_ENSURE_SUCCESS(response->GetBillingAddress(getter_AddRefs(address)), + NS_ERROR_FAILURE); + IPCPaymentAddress ipcAddress; + NS_ENSURE_SUCCESS(SerializeAddress(ipcAddress, address), + NS_ERROR_FAILURE); + data.billingAddress() = ipcAddress; + aIPCData = data; + break; + } + default: { + return NS_ERROR_FAILURE; + } + } + return NS_OK; +} +} // namespace mozilla::dom |