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(
224 PaymentShippingTypeValues::GetString(aOptions
.mShippingType
));
226 IPCPaymentOptions(aOptions
.mRequestPayerName
, aOptions
.mRequestPayerEmail
,
227 aOptions
.mRequestPayerPhone
, aOptions
.mRequestShipping
,
228 aOptions
.mRequestBillingAddress
, shippingType
);
231 void ConvertResponseData(const IPCPaymentResponseData
& aIPCData
,
232 ResponseData
& aData
) {
233 switch (aIPCData
.type()) {
234 case IPCPaymentResponseData::TIPCGeneralResponse
: {
235 const IPCGeneralResponse
& data
= aIPCData
;
237 gData
.data
= data
.data();
241 case IPCPaymentResponseData::TIPCBasicCardResponse
: {
242 const IPCBasicCardResponse
& data
= aIPCData
;
244 bData
.cardholderName
= data
.cardholderName();
245 bData
.cardNumber
= data
.cardNumber();
246 bData
.expiryMonth
= data
.expiryMonth();
247 bData
.expiryYear
= data
.expiryYear();
248 bData
.cardSecurityCode
= data
.cardSecurityCode();
249 bData
.billingAddress
.country
= data
.billingAddress().country();
250 bData
.billingAddress
.addressLine
=
251 data
.billingAddress().addressLine().Clone();
252 bData
.billingAddress
.region
= data
.billingAddress().region();
253 bData
.billingAddress
.regionCode
= data
.billingAddress().regionCode();
254 bData
.billingAddress
.city
= data
.billingAddress().city();
255 bData
.billingAddress
.dependentLocality
=
256 data
.billingAddress().dependentLocality();
257 bData
.billingAddress
.postalCode
= data
.billingAddress().postalCode();
258 bData
.billingAddress
.sortingCode
= data
.billingAddress().sortingCode();
259 bData
.billingAddress
.organization
= data
.billingAddress().organization();
260 bData
.billingAddress
.recipient
= data
.billingAddress().recipient();
261 bData
.billingAddress
.phone
= data
.billingAddress().phone();
271 void ConvertMethodChangeDetails(const IPCMethodChangeDetails
& aIPCDetails
,
272 ChangeDetails
& aDetails
) {
273 switch (aIPCDetails
.type()) {
274 case IPCMethodChangeDetails::TIPCGeneralChangeDetails
: {
275 const IPCGeneralChangeDetails
& details
= aIPCDetails
;
276 GeneralDetails gDetails
;
277 gDetails
.details
= details
.details();
281 case IPCMethodChangeDetails::TIPCBasicCardChangeDetails
: {
282 const IPCBasicCardChangeDetails
& details
= aIPCDetails
;
283 BasicCardDetails bDetails
;
284 bDetails
.billingAddress
.country
= details
.billingAddress().country();
285 bDetails
.billingAddress
.addressLine
=
286 details
.billingAddress().addressLine();
287 bDetails
.billingAddress
.region
= details
.billingAddress().region();
288 bDetails
.billingAddress
.regionCode
=
289 details
.billingAddress().regionCode();
290 bDetails
.billingAddress
.city
= details
.billingAddress().city();
291 bDetails
.billingAddress
.dependentLocality
=
292 details
.billingAddress().dependentLocality();
293 bDetails
.billingAddress
.postalCode
=
294 details
.billingAddress().postalCode();
295 bDetails
.billingAddress
.sortingCode
=
296 details
.billingAddress().sortingCode();
297 bDetails
.billingAddress
.organization
=
298 details
.billingAddress().organization();
299 bDetails
.billingAddress
.recipient
= details
.billingAddress().recipient();
300 bDetails
.billingAddress
.phone
= details
.billingAddress().phone();
309 } // end of namespace
311 /* PaymentRequestManager */
313 StaticRefPtr
<PaymentRequestManager
> gPaymentManager
;
314 const char kSupportedRegionsPref
[] = "dom.payments.request.supportedRegions";
316 void SupportedRegionsPrefChangedCallback(const char* aPrefName
, void* aRetval
) {
317 auto retval
= static_cast<nsTArray
<nsString
>*>(aRetval
);
318 MOZ_ASSERT(NS_IsMainThread());
319 MOZ_ASSERT(!strcmp(aPrefName
, kSupportedRegionsPref
));
321 nsAutoString supportedRegions
;
322 Preferences::GetString(aPrefName
, supportedRegions
);
324 for (const nsAString
& each
: supportedRegions
.Split(',')) {
325 retval
->AppendElement(each
);
329 PaymentRequestManager::PaymentRequestManager() {
330 Preferences::RegisterCallbackAndCall(SupportedRegionsPrefChangedCallback
,
331 kSupportedRegionsPref
,
332 &this->mSupportedRegions
);
335 PaymentRequestManager::~PaymentRequestManager() {
336 MOZ_ASSERT(mActivePayments
.Count() == 0);
337 Preferences::UnregisterCallback(SupportedRegionsPrefChangedCallback
,
338 kSupportedRegionsPref
,
339 &this->mSupportedRegions
);
340 mSupportedRegions
.Clear();
343 bool PaymentRequestManager::IsRegionSupported(const nsAString
& region
) const {
344 return mSupportedRegions
.Contains(region
);
347 PaymentRequestChild
* PaymentRequestManager::GetPaymentChild(
348 PaymentRequest
* aRequest
) {
349 MOZ_ASSERT(aRequest
);
351 if (PaymentRequestChild
* child
= aRequest
->GetIPC()) {
355 nsPIDOMWindowInner
* win
= aRequest
->GetOwner();
356 NS_ENSURE_TRUE(win
, nullptr);
357 BrowserChild
* browserChild
= BrowserChild::GetFrom(win
->GetDocShell());
358 NS_ENSURE_TRUE(browserChild
, nullptr);
359 nsAutoString requestId
;
360 aRequest
->GetInternalId(requestId
);
362 PaymentRequestChild
* paymentChild
= new PaymentRequestChild(aRequest
);
363 browserChild
->SendPPaymentRequestConstructor(paymentChild
);
368 nsresult
PaymentRequestManager::SendRequestPayment(
369 PaymentRequest
* aRequest
, const IPCPaymentActionRequest
& aAction
,
370 bool aResponseExpected
) {
371 PaymentRequestChild
* requestChild
= GetPaymentChild(aRequest
);
372 // bug 1580496, ignoring the case that requestChild is nullptr. It could be
373 // nullptr while the corresponding nsPIDOMWindowInner is nullptr.
374 if (NS_WARN_IF(!requestChild
)) {
375 return NS_ERROR_FAILURE
;
377 nsresult rv
= requestChild
->RequestPayment(aAction
);
378 if (NS_WARN_IF(NS_FAILED(rv
))) {
382 if (aResponseExpected
) {
383 ++mActivePayments
.LookupOrInsert(aRequest
, 0);
388 void PaymentRequestManager::NotifyRequestDone(PaymentRequest
* aRequest
) {
389 auto entry
= mActivePayments
.Lookup(aRequest
);
391 MOZ_ASSERT(entry
.Data() > 0);
393 uint32_t count
= --entry
.Data();
399 void PaymentRequestManager::RequestIPCOver(PaymentRequest
* aRequest
) {
400 // This must only be called from ActorDestroy or if we're sure we won't
401 // receive any more IPC for aRequest.
402 mActivePayments
.Remove(aRequest
);
405 already_AddRefed
<PaymentRequestManager
> PaymentRequestManager::GetSingleton() {
406 if (!gPaymentManager
) {
407 gPaymentManager
= new PaymentRequestManager();
408 ClearOnShutdown(&gPaymentManager
);
410 RefPtr
<PaymentRequestManager
> manager
= gPaymentManager
;
411 return manager
.forget();
414 void GetSelectedShippingOption(const PaymentDetailsBase
& aDetails
,
415 nsAString
& aOption
) {
416 SetDOMStringToNull(aOption
);
417 if (!aDetails
.mShippingOptions
.WasPassed()) {
421 const Sequence
<PaymentShippingOption
>& shippingOptions
=
422 aDetails
.mShippingOptions
.Value();
423 for (const PaymentShippingOption
& shippingOption
: shippingOptions
) {
424 // set aOption to last selected option's ID
425 if (shippingOption
.mSelected
) {
426 aOption
= shippingOption
.mId
;
431 void PaymentRequestManager::CreatePayment(
432 JSContext
* aCx
, nsPIDOMWindowInner
* aWindow
,
433 nsIPrincipal
* aTopLevelPrincipal
,
434 const Sequence
<PaymentMethodData
>& aMethodData
,
435 const PaymentDetailsInit
& aDetails
, const PaymentOptions
& aOptions
,
436 PaymentRequest
** aRequest
, ErrorResult
& aRv
) {
437 MOZ_ASSERT(NS_IsMainThread());
439 MOZ_ASSERT(aRequest
);
440 MOZ_ASSERT(aTopLevelPrincipal
);
443 RefPtr
<PaymentRequest
> request
=
444 PaymentRequest::CreatePaymentRequest(aWindow
, aRv
);
448 request
->SetOptions(aOptions
);
450 * Set request's |mId| to details.id if details.id exists.
451 * Otherwise, set |mId| to internal id.
453 nsAutoString requestId
;
454 if (aDetails
.mId
.WasPassed() && !aDetails
.mId
.Value().IsEmpty()) {
455 requestId
= aDetails
.mId
.Value();
457 request
->GetInternalId(requestId
);
459 request
->SetId(requestId
);
462 * Set request's |mShippingType| and |mShippingOption| if shipping is
463 * required. Set request's mShippingOption to last selected option's ID if
464 * details.shippingOptions exists, otherwise set it as null.
466 nsAutoString shippingOption
;
467 SetDOMStringToNull(shippingOption
);
468 if (aOptions
.mRequestShipping
) {
469 request
->ShippingWasRequested();
470 request
->SetShippingType(
471 Nullable
<PaymentShippingType
>(aOptions
.mShippingType
));
472 GetSelectedShippingOption(aDetails
, shippingOption
);
474 request
->SetShippingOption(shippingOption
);
476 nsAutoString internalId
;
477 request
->GetInternalId(internalId
);
479 nsTArray
<IPCPaymentMethodData
> methodData
;
480 for (const PaymentMethodData
& data
: aMethodData
) {
481 IPCPaymentMethodData ipcMethodData
;
482 ConvertMethodData(aCx
, data
, ipcMethodData
, aRv
);
486 methodData
.AppendElement(ipcMethodData
);
489 IPCPaymentDetails details
;
490 ConvertDetailsInit(aCx
, aDetails
, details
, aOptions
.mRequestShipping
, aRv
);
495 IPCPaymentOptions options
;
496 ConvertOptions(aOptions
, options
);
498 uint64_t topOuterWindowId
=
499 aWindow
->GetWindowContext()->TopWindowContext()->OuterWindowId();
500 IPCPaymentCreateActionRequest
action(topOuterWindowId
, internalId
,
501 aTopLevelPrincipal
, methodData
, details
,
502 options
, shippingOption
);
504 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(request
, action
, false)))) {
505 aRv
.ThrowUnknownError("Internal error sending payment request");
508 request
.forget(aRequest
);
511 void PaymentRequestManager::CanMakePayment(PaymentRequest
* aRequest
,
513 nsAutoString requestId
;
514 aRequest
->GetInternalId(requestId
);
515 IPCPaymentCanMakeActionRequest
action(requestId
);
516 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
)))) {
517 aRv
.ThrowUnknownError("Internal error sending payment request");
521 void PaymentRequestManager::ShowPayment(PaymentRequest
* aRequest
,
523 nsAutoString requestId
;
524 aRequest
->GetInternalId(requestId
);
525 IPCPaymentShowActionRequest
action(requestId
, aRequest
->IsUpdating());
526 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
)))) {
527 aRv
.ThrowUnknownError("Internal error sending payment request");
531 void PaymentRequestManager::AbortPayment(PaymentRequest
* aRequest
,
533 nsAutoString requestId
;
534 aRequest
->GetInternalId(requestId
);
535 IPCPaymentAbortActionRequest
action(requestId
);
536 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
)))) {
537 aRv
.ThrowUnknownError("Internal error sending payment request");
541 void PaymentRequestManager::CompletePayment(PaymentRequest
* aRequest
,
542 const PaymentComplete
& aComplete
,
543 ErrorResult
& aRv
, bool aTimedOut
) {
544 nsString
completeStatusString(u
"unknown"_ns
);
546 completeStatusString
.AssignLiteral("timeout");
548 completeStatusString
.AssignASCII(
549 PaymentCompleteValues::GetString(aComplete
));
552 nsAutoString requestId
;
553 aRequest
->GetInternalId(requestId
);
554 IPCPaymentCompleteActionRequest
action(requestId
, completeStatusString
);
555 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
, false)))) {
556 aRv
.ThrowUnknownError("Internal error sending payment request");
560 void PaymentRequestManager::UpdatePayment(JSContext
* aCx
,
561 PaymentRequest
* aRequest
,
562 const PaymentDetailsUpdate
& aDetails
,
563 bool aRequestShipping
,
566 IPCPaymentDetails details
;
567 ConvertDetailsUpdate(aCx
, aDetails
, details
, aRequestShipping
, aRv
);
572 nsAutoString shippingOption
;
573 SetDOMStringToNull(shippingOption
);
574 if (aRequestShipping
) {
575 GetSelectedShippingOption(aDetails
, shippingOption
);
576 aRequest
->SetShippingOption(shippingOption
);
579 nsAutoString requestId
;
580 aRequest
->GetInternalId(requestId
);
581 IPCPaymentUpdateActionRequest
action(requestId
, details
, shippingOption
);
582 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
, false)))) {
583 aRv
.ThrowUnknownError("Internal error sending payment request");
587 nsresult
PaymentRequestManager::ClosePayment(PaymentRequest
* aRequest
) {
588 // for the case, the payment request is waiting for response from user.
589 if (auto entry
= mActivePayments
.Lookup(aRequest
)) {
590 NotifyRequestDone(aRequest
);
592 nsAutoString requestId
;
593 aRequest
->GetInternalId(requestId
);
594 IPCPaymentCloseActionRequest
action(requestId
);
595 return SendRequestPayment(aRequest
, action
, false);
598 void PaymentRequestManager::RetryPayment(JSContext
* aCx
,
599 PaymentRequest
* aRequest
,
600 const PaymentValidationErrors
& aErrors
,
603 MOZ_ASSERT(aRequest
);
605 nsAutoString requestId
;
606 aRequest
->GetInternalId(requestId
);
609 if (aErrors
.mError
.WasPassed()) {
610 error
= aErrors
.mError
.Value();
613 nsAutoString shippingAddressErrors
;
614 if (aErrors
.mShippingAddress
.WasPassed()) {
615 if (!aErrors
.mShippingAddress
.Value().ToJSON(shippingAddressErrors
)) {
616 aRv
.ThrowTypeError("The ShippingAddressErrors can not be serialized");
621 nsAutoString payerErrors
;
622 if (aErrors
.mPayer
.WasPassed()) {
623 if (!aErrors
.mPayer
.Value().ToJSON(payerErrors
)) {
624 aRv
.ThrowTypeError("The PayerErrors can not be serialized");
629 nsAutoString paymentMethodErrors
;
630 if (aErrors
.mPaymentMethod
.WasPassed()) {
631 JS::Rooted
<JSObject
*> object(aCx
, aErrors
.mPaymentMethod
.Value());
632 if (NS_WARN_IF(NS_FAILED(
633 SerializeFromJSObject(aCx
, object
, paymentMethodErrors
)))) {
634 aRv
.ThrowTypeError("The PaymentMethodErrors can not be serialized");
638 IPCPaymentRetryActionRequest
action(requestId
, error
, payerErrors
,
640 shippingAddressErrors
);
641 if (NS_WARN_IF(NS_FAILED(SendRequestPayment(aRequest
, action
)))) {
642 aRv
.ThrowUnknownError("Internal error sending payment request");
646 nsresult
PaymentRequestManager::RespondPayment(
647 PaymentRequest
* aRequest
, const IPCPaymentActionResponse
& aResponse
) {
648 switch (aResponse
.type()) {
649 case IPCPaymentActionResponse::TIPCPaymentCanMakeActionResponse
: {
650 const IPCPaymentCanMakeActionResponse
& response
= aResponse
;
651 aRequest
->RespondCanMakePayment(response
.result());
652 NotifyRequestDone(aRequest
);
655 case IPCPaymentActionResponse::TIPCPaymentShowActionResponse
: {
656 const IPCPaymentShowActionResponse
& response
= aResponse
;
657 ErrorResult rejectedReason
;
658 ResponseData responseData
;
659 ConvertResponseData(response
.data(), responseData
);
660 switch (response
.status()) {
661 case nsIPaymentActionResponse::PAYMENT_ACCEPTED
: {
664 case nsIPaymentActionResponse::PAYMENT_REJECTED
: {
665 rejectedReason
.ThrowAbortError("The user rejected the payment");
668 case nsIPaymentActionResponse::PAYMENT_NOTSUPPORTED
: {
669 rejectedReason
.ThrowNotSupportedError("No supported payment method");
673 rejectedReason
.ThrowUnknownError("Unknown response for the payment");
677 // If PaymentActionResponse is not PAYMENT_ACCEPTED, no need to keep the
678 // PaymentRequestChild instance. Otherwise, keep PaymentRequestChild for
679 // merchants call PaymentResponse.complete()
680 if (rejectedReason
.Failed()) {
681 NotifyRequestDone(aRequest
);
683 aRequest
->RespondShowPayment(response
.methodName(), responseData
,
684 response
.payerName(), response
.payerEmail(),
685 response
.payerPhone(),
686 std::move(rejectedReason
));
689 case IPCPaymentActionResponse::TIPCPaymentAbortActionResponse
: {
690 const IPCPaymentAbortActionResponse
& response
= aResponse
;
691 aRequest
->RespondAbortPayment(response
.isSucceeded());
692 NotifyRequestDone(aRequest
);
695 case IPCPaymentActionResponse::TIPCPaymentCompleteActionResponse
: {
696 aRequest
->RespondComplete();
697 NotifyRequestDone(aRequest
);
701 return NS_ERROR_FAILURE
;
707 nsresult
PaymentRequestManager::ChangeShippingAddress(
708 PaymentRequest
* aRequest
, const IPCPaymentAddress
& aAddress
) {
709 return aRequest
->UpdateShippingAddress(
710 aAddress
.country(), aAddress
.addressLine(), aAddress
.region(),
711 aAddress
.regionCode(), aAddress
.city(), aAddress
.dependentLocality(),
712 aAddress
.postalCode(), aAddress
.sortingCode(), aAddress
.organization(),
713 aAddress
.recipient(), aAddress
.phone());
716 nsresult
PaymentRequestManager::ChangeShippingOption(PaymentRequest
* aRequest
,
717 const nsAString
& aOption
) {
718 return aRequest
->UpdateShippingOption(aOption
);
721 nsresult
PaymentRequestManager::ChangePayerDetail(
722 PaymentRequest
* aRequest
, const nsAString
& aPayerName
,
723 const nsAString
& aPayerEmail
, const nsAString
& aPayerPhone
) {
724 MOZ_ASSERT(aRequest
);
725 RefPtr
<PaymentResponse
> response
= aRequest
->GetResponse();
726 // ignoring the case call changePayerDetail during show().
730 return response
->UpdatePayerDetail(aPayerName
, aPayerEmail
, aPayerPhone
);
733 nsresult
PaymentRequestManager::ChangePaymentMethod(
734 PaymentRequest
* aRequest
, const nsAString
& aMethodName
,
735 const IPCMethodChangeDetails
& aMethodDetails
) {
736 NS_ENSURE_ARG_POINTER(aRequest
);
737 ChangeDetails methodDetails
;
738 ConvertMethodChangeDetails(aMethodDetails
, methodDetails
);
739 return aRequest
->UpdatePaymentMethod(aMethodName
, methodDetails
);
742 } // namespace mozilla::dom