summaryrefslogtreecommitdiffstats
path: root/dom/payments/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'dom/payments/ipc')
-rw-r--r--dom/payments/ipc/PPaymentRequest.ipdl256
-rw-r--r--dom/payments/ipc/PaymentRequestChild.cpp140
-rw-r--r--dom/payments/ipc/PaymentRequestChild.h57
-rw-r--r--dom/payments/ipc/PaymentRequestParent.cpp468
-rw-r--r--dom/payments/ipc/PaymentRequestParent.h58
-rw-r--r--dom/payments/ipc/moz.build26
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"