diff options
Diffstat (limited to 'dom/payments/ipc')
-rw-r--r-- | dom/payments/ipc/PPaymentRequest.ipdl | 256 | ||||
-rw-r--r-- | dom/payments/ipc/PaymentRequestChild.cpp | 140 | ||||
-rw-r--r-- | dom/payments/ipc/PaymentRequestChild.h | 57 | ||||
-rw-r--r-- | dom/payments/ipc/PaymentRequestParent.cpp | 468 | ||||
-rw-r--r-- | dom/payments/ipc/PaymentRequestParent.h | 58 | ||||
-rw-r--r-- | dom/payments/ipc/moz.build | 26 |
6 files changed, 1005 insertions, 0 deletions
diff --git a/dom/payments/ipc/PPaymentRequest.ipdl b/dom/payments/ipc/PPaymentRequest.ipdl new file mode 100644 index 0000000000..1ac968887c --- /dev/null +++ b/dom/payments/ipc/PPaymentRequest.ipdl @@ -0,0 +1,256 @@ +/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ +/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */ +/* 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 protocol PBrowser; + +include "mozilla/dom/PermissionMessageUtils.h"; + +[RefCounted] using class nsIPrincipal from "nsIPrincipal.h"; + +namespace mozilla { +namespace dom { + +struct IPCPaymentMethodData +{ + nsString supportedMethods; + nsString data; +}; + +struct IPCPaymentCurrencyAmount +{ + nsString currency; + nsString value; +}; + +struct IPCPaymentItem +{ + nsString label; + IPCPaymentCurrencyAmount amount; + bool pending; +}; + +struct IPCPaymentDetailsModifier +{ + nsString supportedMethods; + IPCPaymentItem total; + IPCPaymentItem[] additionalDisplayItems; + nsString data; + bool additionalDisplayItemsPassed; +}; + +struct IPCPaymentShippingOption +{ + nsString id; + nsString label; + IPCPaymentCurrencyAmount amount; + bool selected; +}; + +struct IPCPaymentDetails +{ + nsString id; + IPCPaymentItem total; + IPCPaymentItem[] displayItems; + IPCPaymentShippingOption[] shippingOptions; + IPCPaymentDetailsModifier[] modifiers; + nsString error; + nsString shippingAddressErrors; + nsString payerErrors; + nsString paymentMethodErrors; +}; + +struct IPCPaymentOptions +{ + bool requestPayerName; + bool requestPayerEmail; + bool requestPayerPhone; + bool requestShipping; + bool requestBillingAddress; + nsString shippingType; +}; + +struct IPCPaymentCreateActionRequest +{ + uint64_t topOuterWindowId; + nsString requestId; + nullable nsIPrincipal topLevelPrincipal; + IPCPaymentMethodData[] methodData; + IPCPaymentDetails details; + IPCPaymentOptions options; + nsString shippingOption; +}; + +struct IPCPaymentCanMakeActionRequest +{ + nsString requestId; +}; + +struct IPCPaymentShowActionRequest +{ + nsString requestId; + bool isUpdating; +}; + +struct IPCPaymentAbortActionRequest +{ + nsString requestId; +}; + +struct IPCPaymentCompleteActionRequest +{ + nsString requestId; + nsString completeStatus; +}; + +struct IPCPaymentUpdateActionRequest +{ + nsString requestId; + IPCPaymentDetails details; + nsString shippingOption; +}; + +struct IPCPaymentCloseActionRequest +{ + nsString requestId; +}; + +struct IPCPaymentRetryActionRequest +{ + nsString requestId; + nsString error; + nsString payerErrors; + nsString paymentMethodErrors; + nsString shippingAddressErrors; +}; + +union IPCPaymentActionRequest +{ + IPCPaymentCreateActionRequest; + IPCPaymentCanMakeActionRequest; + IPCPaymentShowActionRequest; + IPCPaymentAbortActionRequest; + IPCPaymentCompleteActionRequest; + IPCPaymentUpdateActionRequest; + IPCPaymentCloseActionRequest; + IPCPaymentRetryActionRequest; +}; + +struct IPCPaymentCanMakeActionResponse +{ + nsString requestId; + bool result; +}; + +struct IPCPaymentAddress +{ + nsString country; + nsString[] addressLine; + nsString region; + nsString regionCode; + nsString city; + nsString dependentLocality; + nsString postalCode; + nsString sortingCode; + nsString organization; + nsString recipient; + nsString phone; +}; + +struct IPCGeneralResponse +{ + nsString data; +}; + +struct IPCBasicCardResponse +{ + nsString cardholderName; + nsString cardNumber; + nsString expiryMonth; + nsString expiryYear; + nsString cardSecurityCode; + IPCPaymentAddress billingAddress; +}; + +union IPCPaymentResponseData +{ + IPCGeneralResponse; + IPCBasicCardResponse; +}; + +struct IPCPaymentShowActionResponse +{ + nsString requestId; + uint32_t status; + nsString methodName; + IPCPaymentResponseData data; + nsString payerName; + nsString payerEmail; + nsString payerPhone; +}; + +struct IPCPaymentAbortActionResponse +{ + nsString requestId; + bool isSucceeded; +}; + +struct IPCPaymentCompleteActionResponse +{ + nsString requestId; + bool isCompleted; +}; + +union IPCPaymentActionResponse +{ + IPCPaymentCanMakeActionResponse; + IPCPaymentShowActionResponse; + IPCPaymentAbortActionResponse; + IPCPaymentCompleteActionResponse; +}; + +struct IPCGeneralChangeDetails +{ + nsString details; +}; + +struct IPCBasicCardChangeDetails +{ + IPCPaymentAddress billingAddress; +}; + +union IPCMethodChangeDetails +{ + IPCGeneralChangeDetails; + IPCBasicCardChangeDetails; +}; + +[ManualDealloc] +sync protocol PPaymentRequest +{ + manager PBrowser; + +parent: + async __delete__(); + + async RequestPayment(IPCPaymentActionRequest aAction); + +child: + async RespondPayment(IPCPaymentActionResponse aResponse); + async ChangeShippingAddress(nsString aRequestId, + IPCPaymentAddress aAddress); + async ChangeShippingOption(nsString aRequestId, + nsString aOption); + async ChangePayerDetail(nsString aRequestId, + nsString aPayerName, + nsString aPayerEmail, + nsString aPayerPhone); + async ChangePaymentMethod(nsString aRequestId, + nsString aMethodName, + IPCMethodChangeDetails aMethodDetails); +}; + +} // end of namespace dom +} // end of namespace mozilla diff --git a/dom/payments/ipc/PaymentRequestChild.cpp b/dom/payments/ipc/PaymentRequestChild.cpp new file mode 100644 index 0000000000..a3a22bf346 --- /dev/null +++ b/dom/payments/ipc/PaymentRequestChild.cpp @@ -0,0 +1,140 @@ +/* -*- 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 "PaymentRequestChild.h" +#include "mozilla/dom/PaymentRequest.h" +#include "mozilla/dom/PaymentRequestManager.h" + +namespace mozilla::dom { + +PaymentRequestChild::PaymentRequestChild(PaymentRequest* aRequest) + : mRequest(aRequest) { + mRequest->SetIPC(this); +} + +nsresult PaymentRequestChild::RequestPayment( + const IPCPaymentActionRequest& aAction) { + if (!mRequest) { + return NS_ERROR_FAILURE; + } + if (!SendRequestPayment(aAction)) { + return NS_ERROR_FAILURE; + } + return NS_OK; +} + +mozilla::ipc::IPCResult PaymentRequestChild::RecvRespondPayment( + const IPCPaymentActionResponse& aResponse) { + if (!mRequest) { + return IPC_FAIL_NO_REASON(this); + } + const IPCPaymentActionResponse& response = aResponse; + RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton(); + MOZ_ASSERT(manager); + + // Hold a strong reference to our request for the entire response. + RefPtr<PaymentRequest> request(mRequest); + nsresult rv = manager->RespondPayment(request, response); + if (NS_WARN_IF(NS_FAILED(rv))) { + return IPC_FAIL_NO_REASON(this); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult PaymentRequestChild::RecvChangeShippingAddress( + const nsString& aRequestId, const IPCPaymentAddress& aAddress) { + if (!mRequest) { + return IPC_FAIL_NO_REASON(this); + } + RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton(); + MOZ_ASSERT(manager); + RefPtr<PaymentRequest> request(mRequest); + nsresult rv = manager->ChangeShippingAddress(request, aAddress); + if (NS_WARN_IF(NS_FAILED(rv))) { + return IPC_FAIL_NO_REASON(this); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult PaymentRequestChild::RecvChangeShippingOption( + const nsString& aRequestId, const nsString& aOption) { + if (!mRequest) { + return IPC_FAIL_NO_REASON(this); + } + RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton(); + MOZ_ASSERT(manager); + RefPtr<PaymentRequest> request(mRequest); + nsresult rv = manager->ChangeShippingOption(request, aOption); + if (NS_WARN_IF(NS_FAILED(rv))) { + return IPC_FAIL_NO_REASON(this); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult PaymentRequestChild::RecvChangePayerDetail( + const nsString& aRequestId, const nsString& aPayerName, + const nsString& aPayerEmail, const nsString& aPayerPhone) { + if (!mRequest) { + return IPC_FAIL_NO_REASON(this); + } + RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton(); + MOZ_ASSERT(manager); + RefPtr<PaymentRequest> request(mRequest); + nsresult rv = + manager->ChangePayerDetail(request, aPayerName, aPayerEmail, aPayerPhone); + if (NS_WARN_IF(NS_FAILED(rv))) { + return IPC_FAIL_NO_REASON(this); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult PaymentRequestChild::RecvChangePaymentMethod( + const nsString& aRequestId, const nsString& aMethodName, + const IPCMethodChangeDetails& aMethodDetails) { + if (!mRequest) { + return IPC_FAIL_NO_REASON(this); + } + RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton(); + MOZ_ASSERT(manager); + RefPtr<PaymentRequest> request(mRequest); + nsresult rv = + manager->ChangePaymentMethod(request, aMethodName, aMethodDetails); + if (NS_WARN_IF(NS_FAILED(rv))) { + return IPC_FAIL_NO_REASON(this); + } + return IPC_OK(); +} + +void PaymentRequestChild::ActorDestroy(ActorDestroyReason aWhy) { + if (mRequest) { + DetachFromRequest(true); + } +} + +void PaymentRequestChild::MaybeDelete(bool aCanBeInManager) { + if (mRequest) { + DetachFromRequest(aCanBeInManager); + Send__delete__(this); + } +} + +void PaymentRequestChild::DetachFromRequest(bool aCanBeInManager) { + MOZ_ASSERT(mRequest); + + if (aCanBeInManager) { + RefPtr<PaymentRequestManager> manager = + PaymentRequestManager::GetSingleton(); + MOZ_ASSERT(manager); + + RefPtr<PaymentRequest> request(mRequest); + manager->RequestIPCOver(request); + } + + mRequest->SetIPC(nullptr); + mRequest = nullptr; +} + +} // namespace mozilla::dom diff --git a/dom/payments/ipc/PaymentRequestChild.h b/dom/payments/ipc/PaymentRequestChild.h new file mode 100644 index 0000000000..4047d2c055 --- /dev/null +++ b/dom/payments/ipc/PaymentRequestChild.h @@ -0,0 +1,57 @@ +/* -*- 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/. */ + +#ifndef mozilla_dom_PaymentRequestChild_h +#define mozilla_dom_PaymentRequestChild_h + +#include "mozilla/dom/PPaymentRequestChild.h" + +namespace mozilla::dom { + +class PaymentRequest; + +class PaymentRequestChild final : public PPaymentRequestChild { + friend class PPaymentRequestChild; + + public: + explicit PaymentRequestChild(PaymentRequest* aRequest); + + void MaybeDelete(bool aCanBeInManager); + + nsresult RequestPayment(const IPCPaymentActionRequest& aAction); + + protected: + mozilla::ipc::IPCResult RecvRespondPayment( + const IPCPaymentActionResponse& aResponse); + + mozilla::ipc::IPCResult RecvChangeShippingAddress( + const nsString& aRequestId, const IPCPaymentAddress& aAddress); + + mozilla::ipc::IPCResult RecvChangeShippingOption(const nsString& aRequestId, + const nsString& aOption); + + mozilla::ipc::IPCResult RecvChangePayerDetail(const nsString& aRequestId, + const nsString& aPayerName, + const nsString& aPayerEmail, + const nsString& aPayerPhone); + + mozilla::ipc::IPCResult RecvChangePaymentMethod( + const nsString& aRequestId, const nsString& aMethodName, + const IPCMethodChangeDetails& aMethodDetails); + + void ActorDestroy(ActorDestroyReason aWhy) override; + + private: + ~PaymentRequestChild() = default; + + void DetachFromRequest(bool aCanBeInManager); + + PaymentRequest* MOZ_NON_OWNING_REF mRequest; +}; + +} // namespace mozilla::dom + +#endif 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 diff --git a/dom/payments/ipc/PaymentRequestParent.h b/dom/payments/ipc/PaymentRequestParent.h new file mode 100644 index 0000000000..5bcab7b204 --- /dev/null +++ b/dom/payments/ipc/PaymentRequestParent.h @@ -0,0 +1,58 @@ +/* -*- 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/. */ + +#ifndef mozilla_dom_PaymentRequestParent_h +#define mozilla_dom_PaymentRequestParent_h + +#include "mozilla/dom/PPaymentRequestParent.h" +#include "nsIPaymentAddress.h" +#include "nsIPaymentActionResponse.h" + +namespace mozilla::dom { + +class PaymentRequestParent final : public PPaymentRequestParent { + friend class PPaymentRequestParent; + + NS_INLINE_DECL_REFCOUNTING(PaymentRequestParent) + public: + PaymentRequestParent(); + + nsresult RespondPayment(nsIPaymentActionResponse* aResponse); + nsresult ChangeShippingAddress(const nsAString& aRequestId, + nsIPaymentAddress* aAddress); + nsresult ChangeShippingOption(const nsAString& aRequestId, + const nsAString& aOption); + nsresult ChangePayerDetail(const nsAString& aRequestId, + const nsAString& aPayerName, + const nsAString& aPayerEmail, + const nsAString& aPayerPhone); + nsresult ChangePaymentMethod(const nsAString& aRequestId, + const nsAString& aMethodName, + nsIMethodChangeDetails* aMethodDetails); + + protected: + mozilla::ipc::IPCResult RecvRequestPayment( + const IPCPaymentActionRequest& aRequest); + + mozilla::ipc::IPCResult Recv__delete__() override; + + void ActorDestroy(ActorDestroyReason aWhy) override; + + private: + ~PaymentRequestParent() = default; + + nsresult SerializeAddress(IPCPaymentAddress& ipcAddress, + nsIPaymentAddress* aAddress); + nsresult SerializeResponseData(IPCPaymentResponseData& ipcData, + nsIPaymentResponseData* aData); + + bool mActorAlive; + nsString mRequestId; +}; + +} // namespace mozilla::dom + +#endif diff --git a/dom/payments/ipc/moz.build b/dom/payments/ipc/moz.build new file mode 100644 index 0000000000..83c5afd577 --- /dev/null +++ b/dom/payments/ipc/moz.build @@ -0,0 +1,26 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +EXPORTS.mozilla.dom += [ + "PaymentRequestChild.h", + "PaymentRequestParent.h", +] + +UNIFIED_SOURCES += [ + "PaymentRequestChild.cpp", + "PaymentRequestParent.cpp", +] + +IPDL_SOURCES += [ + "PPaymentRequest.ipdl", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +# Add libFuzzer configuration directives +include("/tools/fuzzing/libfuzzer-config.mozbuild") + +FINAL_LIBRARY = "xul" |