1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/ClearOnShutdown.h"
8 #include "mozilla/dom/PaymentRequestChild.h"
9 #include "mozilla/dom/BrowserChild.h"
10 #include "mozilla/Preferences.h"
11 #include "nsContentUtils.h"
13 #include "nsIPrincipal.h"
14 #include "nsIPaymentActionResponse.h"
15 #include "PaymentRequestManager.h"
16 #include "PaymentRequestUtils.h"
17 #include "PaymentResponse.h"
19 namespace mozilla::dom
{
23 * Following Convert* functions are used for convert PaymentRequest structs
24 * to transferable structs for IPC.
26 void ConvertMethodData(JSContext
* aCx
, const PaymentMethodData
& aMethodData
,
27 IPCPaymentMethodData
& aIPCMethodData
, ErrorResult
& aRv
) {
29 // Convert JSObject to a serialized string
30 nsAutoString serializedData
;
31 if (aMethodData
.mData
.WasPassed()) {
32 JS::Rooted
<JSObject
*> object(aCx
, aMethodData
.mData
.Value());
34 NS_FAILED(SerializeFromJSObject(aCx
, object
, serializedData
)))) {
36 "The PaymentMethodData.data must be a serializable object");
41 IPCPaymentMethodData(aMethodData
.mSupportedMethods
, serializedData
);
44 void ConvertCurrencyAmount(const PaymentCurrencyAmount
& aAmount
,
45 IPCPaymentCurrencyAmount
& aIPCCurrencyAmount
) {
47 IPCPaymentCurrencyAmount(aAmount
.mCurrency
, aAmount
.mValue
);
50 void ConvertItem(const PaymentItem
& aItem
, IPCPaymentItem
& aIPCItem
) {
51 IPCPaymentCurrencyAmount amount
;
52 ConvertCurrencyAmount(aItem
.mAmount
, amount
);
53 aIPCItem
= IPCPaymentItem(aItem
.mLabel
, amount
, aItem
.mPending
);
56 void ConvertModifier(JSContext
* aCx
, const PaymentDetailsModifier
& aModifier
,
57 IPCPaymentDetailsModifier
& aIPCModifier
,
60 // Convert JSObject to a serialized string
61 nsAutoString serializedData
;
62 if (aModifier
.mData
.WasPassed()) {
63 JS::Rooted
<JSObject
*> object(aCx
, aModifier
.mData
.Value());
65 NS_FAILED(SerializeFromJSObject(aCx
, object
, serializedData
)))) {
66 aRv
.ThrowTypeError("The Modifier.data must be a serializable object");
72 if (aModifier
.mTotal
.WasPassed()) {
73 ConvertItem(aModifier
.mTotal
.Value(), total
);
76 nsTArray
<IPCPaymentItem
> additionalDisplayItems
;
77 if (aModifier
.mAdditionalDisplayItems
.WasPassed()) {
78 for (const PaymentItem
& item
: aModifier
.mAdditionalDisplayItems
.Value()) {
79 IPCPaymentItem displayItem
;
80 ConvertItem(item
, displayItem
);
81 additionalDisplayItems
.AppendElement(displayItem
);
84 aIPCModifier
= IPCPaymentDetailsModifier(
85 aModifier
.mSupportedMethods
, total
, additionalDisplayItems
,
86 serializedData
, aModifier
.mAdditionalDisplayItems
.WasPassed());
89 void ConvertShippingOption(const PaymentShippingOption
& aOption
,
90 IPCPaymentShippingOption
& aIPCOption
) {
91 IPCPaymentCurrencyAmount amount
;
92 ConvertCurrencyAmount(aOption
.mAmount
, amount
);
93 aIPCOption
= IPCPaymentShippingOption(aOption
.mId
, aOption
.mLabel
, amount
,
97 void ConvertDetailsBase(JSContext
* aCx
, const PaymentDetailsBase
& aDetails
,
98 nsTArray
<IPCPaymentItem
>& aDisplayItems
,
99 nsTArray
<IPCPaymentShippingOption
>& aShippingOptions
,
100 nsTArray
<IPCPaymentDetailsModifier
>& aModifiers
,
101 bool aRequestShipping
, ErrorResult
& aRv
) {
103 if (aDetails
.mDisplayItems
.WasPassed()) {
104 for (const PaymentItem
& item
: aDetails
.mDisplayItems
.Value()) {
105 IPCPaymentItem displayItem
;
106 ConvertItem(item
, displayItem
);
107 aDisplayItems
.AppendElement(displayItem
);
110 if (aRequestShipping
&& aDetails
.mShippingOptions
.WasPassed()) {
111 for (const PaymentShippingOption
& option
:
112 aDetails
.mShippingOptions
.Value()) {
113 IPCPaymentShippingOption shippingOption
;
114 ConvertShippingOption(option
, shippingOption
);
115 aShippingOptions
.AppendElement(shippingOption
);
118 if (aDetails
.mModifiers
.WasPassed()) {
119 for (const PaymentDetailsModifier
& modifier
: aDetails
.mModifiers
.Value()) {
120 IPCPaymentDetailsModifier detailsModifier
;
121 ConvertModifier(aCx
, modifier
, detailsModifier
, aRv
);
125 aModifiers
.AppendElement(detailsModifier
);
130 void ConvertDetailsInit(JSContext
* aCx
, const PaymentDetailsInit
& aDetails
,
131 IPCPaymentDetails
& aIPCDetails
, bool aRequestShipping
,
134 // Convert PaymentDetailsBase members
135 nsTArray
<IPCPaymentItem
> displayItems
;
136 nsTArray
<IPCPaymentShippingOption
> shippingOptions
;
137 nsTArray
<IPCPaymentDetailsModifier
> modifiers
;
138 ConvertDetailsBase(aCx
, aDetails
, displayItems
, shippingOptions
, modifiers
,
139 aRequestShipping
, aRv
);
146 if (aDetails
.mId
.WasPassed()) {
147 id
= aDetails
.mId
.Value();
150 // Convert required |total|
151 IPCPaymentItem total
;
152 ConvertItem(aDetails
.mTotal
, total
);
155 IPCPaymentDetails(id
, total
, displayItems
, shippingOptions
, modifiers
,
156 u
""_ns
, // error message
157 u
""_ns
, // shippingAddressErrors
158 u
""_ns
, // payerErrors
159 u
""_ns
); // paymentMethodErrors
162 void ConvertDetailsUpdate(JSContext
* aCx
, const PaymentDetailsUpdate
& aDetails
,
163 IPCPaymentDetails
& aIPCDetails
, bool aRequestShipping
,
166 // Convert PaymentDetailsBase members
167 nsTArray
<IPCPaymentItem
> displayItems
;
168 nsTArray
<IPCPaymentShippingOption
> shippingOptions
;
169 nsTArray
<IPCPaymentDetailsModifier
> modifiers
;
170 ConvertDetailsBase(aCx
, aDetails
, displayItems
, shippingOptions
, modifiers
,
171 aRequestShipping
, aRv
);
176 // Convert required |total|
177 IPCPaymentItem total
;
178 if (aDetails
.mTotal
.WasPassed()) {
179 ConvertItem(aDetails
.mTotal
.Value(), total
);
184 if (aDetails
.mError
.WasPassed()) {
185 error
= aDetails
.mError
.Value();
188 nsAutoString shippingAddressErrors
;
189 if (aDetails
.mShippingAddressErrors
.WasPassed()) {
190 if (!aDetails
.mShippingAddressErrors
.Value().ToJSON(
191 shippingAddressErrors
)) {
192 aRv
.ThrowTypeError("The ShippingAddressErrors can not be serailized");
197 nsAutoString payerErrors
;
198 if (aDetails
.mPayerErrors
.WasPassed()) {
199 if (!aDetails
.mPayerErrors
.Value().ToJSON(payerErrors
)) {
200 aRv
.ThrowTypeError("The PayerErrors can not be serialized");
205 nsAutoString paymentMethodErrors
;
206 if (aDetails
.mPaymentMethodErrors
.WasPassed()) {
207 JS::Rooted
<JSObject
*> object(aCx
, aDetails
.mPaymentMethodErrors
.Value());
208 if (NS_WARN_IF(NS_FAILED(
209 SerializeFromJSObject(aCx
, object
, paymentMethodErrors
)))) {
210 aRv
.ThrowTypeError("The PaymentMethodErrors can not be serialized");
215 aIPCDetails
= IPCPaymentDetails(u
""_ns
, // id
216 total
, displayItems
, shippingOptions
,
217 modifiers
, error
, shippingAddressErrors
,
218 payerErrors
, paymentMethodErrors
);
221 void ConvertOptions(const PaymentOptions
& aOptions
,
222 IPCPaymentOptions
& aIPCOption
) {
223 NS_ConvertASCIItoUTF16
shippingType(GetEnumString(aOptions
.mShippingType
));
225 IPCPaymentOptions(aOptions
.mRequestPayerName
, aOptions
.mRequestPayerEmail
,
226 aOptions
.mRequestPayerPhone
, aOptions
.mRequestShipping
,
227 aOptions
.mRequestBillingAddress
, shippingType
);
230 void ConvertResponseData(const IPCPaymentResponseData
& aIPCData
,
231 ResponseData
& aData
) {
232 switch (aIPCData
.type()) {
233 case IPCPaymentResponseData::TIPCGeneralResponse
: {
234 const IPCGeneralResponse
& data
= aIPCData
;
236 gData
.data
= data
.data();
240 case IPCPaymentResponseData::TIPCBasicCardResponse
: {
241 const IPCBasicCardResponse
& data
= aIPCData
;
243 bData
.cardholderName
= data
.cardholderName();
244 bData
.cardNumber
= data
.cardNumber();
245 bData
.expiryMonth
= data
.expiryMonth();
246 bData
.expiryYear
= data
.expiryYear();
247 bData
.cardSecurityCode
= data
.cardSecurityCode();
248 bData
.billingAddress
.country
= data
.billingAddress().country();
249 bData
.billingAddress
.addressLine
=
250 data
.billingAddress().addressLine().Clone();
251 bData
.billingAddress
.region
= data
.billingAddress().region();
252 bData
.billingAddress
.regionCode
= data
.billingAddress().regionCode();
253 bData
.billingAddress
.city
= data
.billingAddress().city();
254 bData
.billingAddress
.dependentLocality
=
255 data
.billingAddress().dependentLocality();
256 bData
.billingAddress
.postalCode
= data
.billingAddress().postalCode();
257 bData
.billingAddress
.sortingCode
= data
.billingAddress().sortingCode();
258 bData
.billingAddress
.organization
= data
.billingAddress().organization();
259 bData
.billingAddress
.recipient
= data
.billingAddress().recipient();
260 bData
.billingAddress
.phone
= data
.billingAddress().phone();
270 void ConvertMethodChangeDetails(const IPCMethodChangeDetails
& aIPCDetails
,
271 ChangeDetails
& aDetails
) {
272 switch (aIPCDetails
.type()) {
273 case IPCMethodChangeDetails::TIPCGeneralChangeDetails
: {
274 const IPCGeneralChangeDetails
& details
= aIPCDetails
;
275 GeneralDetails gDetails
;
276 gDetails
.details
= details
.details();
280 case IPCMethodChangeDetails::TIPCBasicCardChangeDetails
: {
281 const IPCBasicCardChangeDetails
& details
= aIPCDetails
;
282 BasicCardDetails bDetails
;
283 bDetails
.billingAddress
.country
= details
.billingAddress().country();
284 bDetails
.billingAddress
.addressLine
=
285 details
.billingAddress().addressLine();
286 bDetails
.billingAddress
.region
= details
.billingAddress().region();
287 bDetails
.billingAddress
.regionCode
=
288 details
.billingAddress().regionCode();
289 bDetails
.billingAddress
.city
= details
.billingAddress().city();
290 bDetails
.billingAddress
.dependentLocality
=
291 details
.billingAddress().dependentLocality();
292 bDetails
.billingAddress
.postalCode
=
293 details
.billingAddress().postalCode();
294 bDetails
.billingAddress
.sortingCode
=
295 details
.billingAddress().sortingCode();
296 bDetails
.billingAddress
.organization
=
297 details
.billingAddress().organization();
298 bDetails
.billingAddress
.recipient
= details
.billingAddress().recipient();
299 bDetails
.billingAddress
.phone
= details
.billingAddress().phone();
308 } // end of namespace
310 /* PaymentRequestManager */
312 StaticRefPtr
<PaymentRequestManager
> gPaymentManager
;
313 const char kSupportedRegionsPref
[] = "dom.payments.request.supportedRegions";
315 void SupportedRegionsPrefChangedCallback(const char* aPrefName
, void* aRetval
) {
316 auto retval
= static_cast<nsTArray
<nsString
>*>(aRetval
);
317 MOZ_ASSERT(NS_IsMainThread());
318 MOZ_ASSERT(!strcmp(aPrefName
, kSupportedRegionsPref
));
320 nsAutoString supportedRegions
;
321 Preferences::GetString(aPrefName
, supportedRegions
);
323 for (const nsAString
& each
: supportedRegions
.Split(',')) {
324 retval
->AppendElement(each
);
328 PaymentRequestManager::PaymentRequestManager() {
329 Preferences::RegisterCallbackAndCall(SupportedRegionsPrefChangedCallback
,
330 kSupportedRegionsPref
,
331 &this->mSupportedRegions
);
334 PaymentRequestManager::~PaymentRequestManager() {
335 MOZ_ASSERT(mActivePayments
.Count() == 0);
336 Preferences::UnregisterCallback(SupportedRegionsPrefChangedCallback
,
337 kSupportedRegionsPref
,
338 &this->mSupportedRegions
);
339 mSupportedRegions
.Clear();
342 bool PaymentRequestManager::IsRegionSupported(const nsAString
& region
) const {
343 return mSupportedRegions
.Contains(region
);
346 PaymentRequestChild
* PaymentRequestManager::GetPaymentChild(
347 PaymentRequest
* aRequest
) {
348 MOZ_ASSERT(aRequest
);
350 if (PaymentRequestChild
* child
= aRequest
->GetIPC()) {
354 nsPIDOMWindowInner
* win
= aRequest
->GetOwner();
355 NS_ENSURE_TRUE(win
, nullptr);
356 BrowserChild
* browserChild
= BrowserChild::GetFrom(win
->GetDocShell());
357 NS_ENSURE_TRUE(browserChild
, nullptr);
358 nsAutoString requestId
;
359 aRequest
->GetInternalId(requestId
);
361 PaymentRequestChild
* paymentChild
= new PaymentRequestChild(aRequest
);
362 if (!browserChild
->SendPPaymentRequestConstructor(paymentChild
)) {
363 // deleted by Constructor
370 nsresult
PaymentRequestManager::SendRequestPayment(
371 PaymentRequest
* aRequest
, const IPCPaymentActionRequest
& aAction
,
372 bool aResponseExpected
) {
373 PaymentRequestChild
* requestChild
= GetPaymentChild(aRequest
);
374 // bug 1580496, ignoring the case that requestChild is nullptr. It could be
375 // nullptr while the corresponding nsPIDOMWindowInner is nullptr.
376 if (NS_WARN_IF(!requestChild
)) {
377 return NS_ERROR_FAILURE
;
379 nsresult rv
= requestChild
->RequestPayment(aAction
);
380 if (NS_WARN_IF(NS_FAILED(rv
))) {
384 if (aResponseExpected
) {
385 ++mActivePayments
.LookupOrInsert(aRequest
, 0);
390 void PaymentRequestManager::NotifyRequestDone(PaymentRequest
* aRequest
) {
391 auto entry
= mActivePayments
.Lookup(aRequest
);
393 MOZ_ASSERT(entry
.Data() > 0);
395 uint32_t count
= --entry
.Data();
401 void PaymentRequestManager::RequestIPCOver(PaymentRequest
* aRequest
) {
402 // This must only be called from ActorDestroy or if we're sure we won't
403 // receive any more IPC for aRequest.
404 mActivePayments
.Remove(aRequest
);
407 already_AddRefed
<PaymentRequestManager
> PaymentRequestManager::GetSingleton() {
408 if (!gPaymentManager
) {
409 gPaymentManager
= new PaymentRequestManager();
410 ClearOnShutdown(&gPaymentManager
);
412 RefPtr
<PaymentRequestManager
> manager
= gPaymentManager
;
413 return manager
.forget();
416 void GetSelectedShippingOption(const PaymentDetailsBase
& aDetails
,
417 nsAString
& aOption
) {
418 SetDOMStringToNull(aOption
);
419 if (!aDetails
.mShippingOptions
.WasPassed()) {
423 const Sequence
<PaymentShippingOption
>& shippingOptions
=
424 aDetails
.mShippingOptions
.Value();
425 for (const PaymentShippingOption
& shippingOption
: shippingOptions
) {
426 // set aOption to last selected option's ID
427 if (shippingOption
.mSelected
) {
428 aOption
= shippingOption
.mId
;
433 void PaymentRequestManager::CreatePayment(
434 JSContext
* aCx
, nsPIDOMWindowInner
* aWindow
,
435 nsIPrincipal
* aTopLevelPrincipal
,
436 const Sequence
<PaymentMethodData
>& aMethodData
,
437 const PaymentDetailsInit
& aDetails
, const PaymentOptions
& aOptions
,
438 PaymentRequest
** aRequest
, ErrorResult
& aRv
) {
439 MOZ_ASSERT(NS_IsMainThread());
441 MOZ_ASSERT(aRequest
);
442 MOZ_ASSERT(aTopLevelPrincipal
);
445 RefPtr
<PaymentRequest
> request
=
446 PaymentRequest::CreatePaymentRequest(aWindow
, aRv
);
450 request
->SetOptions(aOptions
);
452 * Set request's |mId| to details.id if details.id exists.
453 * Otherwise, set |mId| to internal id.
455 nsAutoString requestId
;
456 if (aDetails
.mId
.WasPassed() && !aDetails
.mId
.Value().IsEmpty()) {
457 requestId
= aDetails
.mId
.Value();
459 request
->GetInternalId(requestId
);
461 request
->SetId(requestId
);
464 * Set request's |mShippingType| and |mShippingOption| if shipping is
465 * required. Set request's mShippingOption to last selected option's ID if
466 * details.shippingOptions exists, otherwise set it as null.
468 nsAutoString shippingOption
;
469 SetDOMStringToNull(shippingOption
);
470 if (aOptions
.mRequestShipping
) {
471 request
->ShippingWasRequested();
472 request
->SetShippingType(
473 Nullable
<PaymentShippingType
>(aOptions
.mShippingType
));
474 GetSelectedShippingOption(aDetails
, shippingOption
);
476 request
->SetShippingOption(shippingOption
);
478 nsAutoString internalId
;
479 request
->GetInternalId(internalId
);
481 nsTArray
<IPCPaymentMethodData
> methodData
;
482 for (const PaymentMethodData
& data
: aMethodData
) {
483 IPCPaymentMethodData ipcMethodData
;
484 ConvertMethodData(aCx
, data
, ipcMethodData
, aRv
);
488 methodData
.AppendElement(ipcMethodData
);
491 IPCPaymentDetails details
;
492 ConvertDetailsInit(aCx
, aDetails
, details
, aOptions
.mRequestShipping
, aRv
);
497 IPCPaymentOptions options
;
498 ConvertOptions(aOptions
, options
);
500 uint64_t topOuterWindowId
=
501 aWindow
->GetWindowContext()->TopWindowContext()->OuterWindowId();
502 IPCPaymentCreateActionRequest
action(topOuterWindowId
, internalId
,
503 aTopLevelPrincipal
, methodData
, details
,
504 options
, shippingOption
);
506 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(request
, action
, false)))) {
507 aRv
.ThrowUnknownError("Internal error sending payment request");
510 request
.forget(aRequest
);
513 void PaymentRequestManager::CanMakePayment(PaymentRequest
* aRequest
,
515 nsAutoString requestId
;
516 aRequest
->GetInternalId(requestId
);
517 IPCPaymentCanMakeActionRequest
action(requestId
);
518 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
)))) {
519 aRv
.ThrowUnknownError("Internal error sending payment request");
523 void PaymentRequestManager::ShowPayment(PaymentRequest
* aRequest
,
525 nsAutoString requestId
;
526 aRequest
->GetInternalId(requestId
);
527 IPCPaymentShowActionRequest
action(requestId
, aRequest
->IsUpdating());
528 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
)))) {
529 aRv
.ThrowUnknownError("Internal error sending payment request");
533 void PaymentRequestManager::AbortPayment(PaymentRequest
* aRequest
,
535 nsAutoString requestId
;
536 aRequest
->GetInternalId(requestId
);
537 IPCPaymentAbortActionRequest
action(requestId
);
538 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
)))) {
539 aRv
.ThrowUnknownError("Internal error sending payment request");
543 void PaymentRequestManager::CompletePayment(PaymentRequest
* aRequest
,
544 const PaymentComplete
& aComplete
,
545 ErrorResult
& aRv
, bool aTimedOut
) {
546 nsString
completeStatusString(u
"unknown"_ns
);
548 completeStatusString
.AssignLiteral("timeout");
550 completeStatusString
.AssignASCII(GetEnumString(aComplete
));
553 nsAutoString requestId
;
554 aRequest
->GetInternalId(requestId
);
555 IPCPaymentCompleteActionRequest
action(requestId
, completeStatusString
);
556 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
, false)))) {
557 aRv
.ThrowUnknownError("Internal error sending payment request");
561 void PaymentRequestManager::UpdatePayment(JSContext
* aCx
,
562 PaymentRequest
* aRequest
,
563 const PaymentDetailsUpdate
& aDetails
,
564 bool aRequestShipping
,
567 IPCPaymentDetails details
;
568 ConvertDetailsUpdate(aCx
, aDetails
, details
, aRequestShipping
, aRv
);
573 nsAutoString shippingOption
;
574 SetDOMStringToNull(shippingOption
);
575 if (aRequestShipping
) {
576 GetSelectedShippingOption(aDetails
, shippingOption
);
577 aRequest
->SetShippingOption(shippingOption
);
580 nsAutoString requestId
;
581 aRequest
->GetInternalId(requestId
);
582 IPCPaymentUpdateActionRequest
action(requestId
, details
, shippingOption
);
583 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
, false)))) {
584 aRv
.ThrowUnknownError("Internal error sending payment request");
588 nsresult
PaymentRequestManager::ClosePayment(PaymentRequest
* aRequest
) {
589 // for the case, the payment request is waiting for response from user.
590 if (auto entry
= mActivePayments
.Lookup(aRequest
)) {
591 NotifyRequestDone(aRequest
);
593 nsAutoString requestId
;
594 aRequest
->GetInternalId(requestId
);
595 IPCPaymentCloseActionRequest
action(requestId
);
596 return SendRequestPayment(aRequest
, action
, false);
599 void PaymentRequestManager::RetryPayment(JSContext
* aCx
,
600 PaymentRequest
* aRequest
,
601 const PaymentValidationErrors
& aErrors
,
604 MOZ_ASSERT(aRequest
);
606 nsAutoString requestId
;
607 aRequest
->GetInternalId(requestId
);
610 if (aErrors
.mError
.WasPassed()) {
611 error
= aErrors
.mError
.Value();
614 nsAutoString shippingAddressErrors
;
615 if (aErrors
.mShippingAddress
.WasPassed()) {
616 if (!aErrors
.mShippingAddress
.Value().ToJSON(shippingAddressErrors
)) {
617 aRv
.ThrowTypeError("The ShippingAddressErrors can not be serialized");
622 nsAutoString payerErrors
;
623 if (aErrors
.mPayer
.WasPassed()) {
624 if (!aErrors
.mPayer
.Value().ToJSON(payerErrors
)) {
625 aRv
.ThrowTypeError("The PayerErrors can not be serialized");
630 nsAutoString paymentMethodErrors
;
631 if (aErrors
.mPaymentMethod
.WasPassed()) {
632 JS::Rooted
<JSObject
*> object(aCx
, aErrors
.mPaymentMethod
.Value());
633 if (NS_WARN_IF(NS_FAILED(
634 SerializeFromJSObject(aCx
, object
, paymentMethodErrors
)))) {
635 aRv
.ThrowTypeError("The PaymentMethodErrors can not be serialized");
639 IPCPaymentRetryActionRequest
action(requestId
, error
, payerErrors
,
641 shippingAddressErrors
);
642 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
)))) {
643 aRv
.ThrowUnknownError("Internal error sending payment request");
647 nsresult
PaymentRequestManager::RespondPayment(
648 PaymentRequest
* aRequest
, const IPCPaymentActionResponse
& aResponse
) {
649 switch (aResponse
.type()) {
650 case IPCPaymentActionResponse::TIPCPaymentCanMakeActionResponse
: {
651 const IPCPaymentCanMakeActionResponse
& response
= aResponse
;
652 aRequest
->RespondCanMakePayment(response
.result());
653 NotifyRequestDone(aRequest
);
656 case IPCPaymentActionResponse::TIPCPaymentShowActionResponse
: {
657 const IPCPaymentShowActionResponse
& response
= aResponse
;
658 ErrorResult rejectedReason
;
659 ResponseData responseData
;
660 ConvertResponseData(response
.data(), responseData
);
661 switch (response
.status()) {
662 case nsIPaymentActionResponse::PAYMENT_ACCEPTED
: {
665 case nsIPaymentActionResponse::PAYMENT_REJECTED
: {
666 rejectedReason
.ThrowAbortError("The user rejected the payment");
669 case nsIPaymentActionResponse::PAYMENT_NOTSUPPORTED
: {
670 rejectedReason
.ThrowNotSupportedError("No supported payment method");
674 rejectedReason
.ThrowUnknownError("Unknown response for the payment");
678 // If PaymentActionResponse is not PAYMENT_ACCEPTED, no need to keep the
679 // PaymentRequestChild instance. Otherwise, keep PaymentRequestChild for
680 // merchants call PaymentResponse.complete()
681 if (rejectedReason
.Failed()) {
682 NotifyRequestDone(aRequest
);
684 aRequest
->RespondShowPayment(response
.methodName(), responseData
,
685 response
.payerName(), response
.payerEmail(),
686 response
.payerPhone(),
687 std::move(rejectedReason
));
690 case IPCPaymentActionResponse::TIPCPaymentAbortActionResponse
: {
691 const IPCPaymentAbortActionResponse
& response
= aResponse
;
692 aRequest
->RespondAbortPayment(response
.isSucceeded());
693 NotifyRequestDone(aRequest
);
696 case IPCPaymentActionResponse::TIPCPaymentCompleteActionResponse
: {
697 aRequest
->RespondComplete();
698 NotifyRequestDone(aRequest
);
702 return NS_ERROR_FAILURE
;
708 nsresult
PaymentRequestManager::ChangeShippingAddress(
709 PaymentRequest
* aRequest
, const IPCPaymentAddress
& aAddress
) {
710 return aRequest
->UpdateShippingAddress(
711 aAddress
.country(), aAddress
.addressLine(), aAddress
.region(),
712 aAddress
.regionCode(), aAddress
.city(), aAddress
.dependentLocality(),
713 aAddress
.postalCode(), aAddress
.sortingCode(), aAddress
.organization(),
714 aAddress
.recipient(), aAddress
.phone());
717 nsresult
PaymentRequestManager::ChangeShippingOption(PaymentRequest
* aRequest
,
718 const nsAString
& aOption
) {
719 return aRequest
->UpdateShippingOption(aOption
);
722 nsresult
PaymentRequestManager::ChangePayerDetail(
723 PaymentRequest
* aRequest
, const nsAString
& aPayerName
,
724 const nsAString
& aPayerEmail
, const nsAString
& aPayerPhone
) {
725 MOZ_ASSERT(aRequest
);
726 RefPtr
<PaymentResponse
> response
= aRequest
->GetResponse();
727 // ignoring the case call changePayerDetail during show().
731 return response
->UpdatePayerDetail(aPayerName
, aPayerEmail
, aPayerPhone
);
734 nsresult
PaymentRequestManager::ChangePaymentMethod(
735 PaymentRequest
* aRequest
, const nsAString
& aMethodName
,
736 const IPCMethodChangeDetails
& aMethodDetails
) {
737 NS_ENSURE_ARG_POINTER(aRequest
);
738 ChangeDetails methodDetails
;
739 ConvertMethodChangeDetails(aMethodDetails
, methodDetails
);
740 return aRequest
->UpdatePaymentMethod(aMethodName
, methodDetails
);
743 } // namespace mozilla::dom